mirror of
https://github.com/golang/go.git
synced 2025-05-22 16:09:37 +00:00
go/types: add unexported start and end positions to type checker errors
Tools often need to associate errors not with a single position, but with a span of source code. For example, gopls currently estimates diagnostic spans using heuristics to expand the positions reported by the type checker to surrounding source code. Unfortunately this is often inaccurate. This CL lays the groundwork to solve this within go/types by adding a start and end position to type checker errors. This is an experimental API, both because we are uncertain of the ideal representation for these spans and because their initial positioning is naive. In most cases this CL simply expands errors to the surrounding ast.Node being typechecked, if available. This might not be the best error span to present to the user. For these reasons the API is unexported -- gopls can read these positions using reflection, allowing us to gain experience and improve them during the next development cycle. For golang/go#42290 Change-Id: I39a04d70ea2bb2134b4d4c937f32b2ddb4456430 Reviewed-on: https://go-review.googlesource.com/c/go/+/265250 Run-TryBot: Robert Findley <rfindley@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Robert Griesemer <gri@golang.org> Trust: Robert Findley <rfindley@google.com> Trust: Robert Griesemer <gri@golang.org>
This commit is contained in:
parent
d508d86cf1
commit
2822bae168
@ -49,7 +49,9 @@ type Error struct {
|
||||
// to preview this feature may read go116code using reflection (see
|
||||
// errorcodes_test.go), but beware that there is no guarantee of future
|
||||
// compatibility.
|
||||
go116code errorCode
|
||||
go116code errorCode
|
||||
go116start token.Pos
|
||||
go116end token.Pos
|
||||
}
|
||||
|
||||
// Error returns an error string formatted as follows:
|
||||
|
@ -38,7 +38,7 @@ func (check *Checker) assignment(x *operand, T Type, context string) {
|
||||
// complex, or string constant."
|
||||
if T == nil || IsInterface(T) {
|
||||
if T == nil && x.typ == Typ[UntypedNil] {
|
||||
check.errorf(x.pos(), _UntypedNil, "use of untyped nil in %s", context)
|
||||
check.errorf(x, _UntypedNil, "use of untyped nil in %s", context)
|
||||
x.mode = invalid
|
||||
return
|
||||
}
|
||||
@ -59,7 +59,7 @@ func (check *Checker) assignment(x *operand, T Type, context string) {
|
||||
code = ierr.go116code
|
||||
}
|
||||
}
|
||||
check.error(x.pos(), code, msg)
|
||||
check.error(x, code, msg)
|
||||
x.mode = invalid
|
||||
return
|
||||
}
|
||||
@ -76,9 +76,9 @@ func (check *Checker) assignment(x *operand, T Type, context string) {
|
||||
reason := ""
|
||||
if ok, code := x.assignableTo(check, T, &reason); !ok {
|
||||
if reason != "" {
|
||||
check.errorf(x.pos(), code, "cannot use %s as %s value in %s: %s", x, T, context, reason)
|
||||
check.errorf(x, code, "cannot use %s as %s value in %s: %s", x, T, context, reason)
|
||||
} else {
|
||||
check.errorf(x.pos(), code, "cannot use %s as %s value in %s", x, T, context)
|
||||
check.errorf(x, code, "cannot use %s as %s value in %s", x, T, context)
|
||||
}
|
||||
x.mode = invalid
|
||||
}
|
||||
@ -94,7 +94,7 @@ func (check *Checker) initConst(lhs *Const, x *operand) {
|
||||
|
||||
// rhs must be a constant
|
||||
if x.mode != constant_ {
|
||||
check.errorf(x.pos(), _InvalidConstInit, "%s is not constant", x)
|
||||
check.errorf(x, _InvalidConstInit, "%s is not constant", x)
|
||||
if lhs.typ == nil {
|
||||
lhs.typ = Typ[Invalid]
|
||||
}
|
||||
@ -129,7 +129,7 @@ func (check *Checker) initVar(lhs *Var, x *operand, context string) Type {
|
||||
if isUntyped(typ) {
|
||||
// convert untyped types to default types
|
||||
if typ == Typ[UntypedNil] {
|
||||
check.errorf(x.pos(), _UntypedNil, "use of untyped nil in %s", context)
|
||||
check.errorf(x, _UntypedNil, "use of untyped nil in %s", context)
|
||||
lhs.typ = Typ[Invalid]
|
||||
return nil
|
||||
}
|
||||
@ -203,11 +203,11 @@ func (check *Checker) assignVar(lhs ast.Expr, x *operand) Type {
|
||||
var op operand
|
||||
check.expr(&op, sel.X)
|
||||
if op.mode == mapindex {
|
||||
check.errorf(z.pos(), _UnaddressableFieldAssign, "cannot assign to struct field %s in map", ExprString(z.expr))
|
||||
check.errorf(&z, _UnaddressableFieldAssign, "cannot assign to struct field %s in map", ExprString(z.expr))
|
||||
return nil
|
||||
}
|
||||
}
|
||||
check.errorf(z.pos(), _UnassignableOperand, "cannot assign to %s", &z)
|
||||
check.errorf(&z, _UnassignableOperand, "cannot assign to %s", &z)
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -236,10 +236,10 @@ func (check *Checker) initVars(lhs []*Var, rhs []ast.Expr, returnPos token.Pos)
|
||||
}
|
||||
check.useGetter(get, r)
|
||||
if returnPos.IsValid() {
|
||||
check.errorf(returnPos, _WrongResultCount, "wrong number of return values (want %d, got %d)", l, r)
|
||||
check.errorf(atPos(returnPos), _WrongResultCount, "wrong number of return values (want %d, got %d)", l, r)
|
||||
return
|
||||
}
|
||||
check.errorf(rhs[0].Pos(), _WrongAssignCount, "cannot initialize %d variables with %d values", l, r)
|
||||
check.errorf(rhs[0], _WrongAssignCount, "cannot initialize %d variables with %d values", l, r)
|
||||
return
|
||||
}
|
||||
|
||||
@ -274,7 +274,7 @@ func (check *Checker) assignVars(lhs, rhs []ast.Expr) {
|
||||
}
|
||||
if l != r {
|
||||
check.useGetter(get, r)
|
||||
check.errorf(rhs[0].Pos(), _WrongAssignCount, "cannot assign %d values to %d variables", r, l)
|
||||
check.errorf(rhs[0], _WrongAssignCount, "cannot assign %d values to %d variables", r, l)
|
||||
return
|
||||
}
|
||||
|
||||
@ -295,7 +295,7 @@ func (check *Checker) assignVars(lhs, rhs []ast.Expr) {
|
||||
}
|
||||
}
|
||||
|
||||
func (check *Checker) shortVarDecl(pos token.Pos, lhs, rhs []ast.Expr) {
|
||||
func (check *Checker) shortVarDecl(pos positioner, lhs, rhs []ast.Expr) {
|
||||
top := len(check.delayed)
|
||||
scope := check.scope
|
||||
|
||||
@ -315,7 +315,7 @@ func (check *Checker) shortVarDecl(pos token.Pos, lhs, rhs []ast.Expr) {
|
||||
if alt, _ := alt.(*Var); alt != nil {
|
||||
obj = alt
|
||||
} else {
|
||||
check.errorf(lhs.Pos(), _UnassignableOperand, "cannot assign to %s", lhs)
|
||||
check.errorf(lhs, _UnassignableOperand, "cannot assign to %s", lhs)
|
||||
}
|
||||
check.recordUse(ident, alt)
|
||||
} else {
|
||||
@ -328,7 +328,7 @@ func (check *Checker) shortVarDecl(pos token.Pos, lhs, rhs []ast.Expr) {
|
||||
}
|
||||
} else {
|
||||
check.useLHS(lhs)
|
||||
check.invalidAST(lhs.Pos(), "cannot declare %s", lhs)
|
||||
check.invalidAST(lhs, "cannot declare %s", lhs)
|
||||
}
|
||||
if obj == nil {
|
||||
obj = NewVar(lhs.Pos(), check.pkg, "_", nil) // dummy variable
|
||||
|
@ -21,7 +21,9 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
|
||||
// append is the only built-in that permits the use of ... for the last argument
|
||||
bin := predeclaredFuncs[id]
|
||||
if call.Ellipsis.IsValid() && id != _Append {
|
||||
check.invalidOp(call.Ellipsis, _InvalidDotDotDot, "invalid use of ... with built-in %s", bin.name)
|
||||
check.invalidOp(atPos(call.Ellipsis),
|
||||
_InvalidDotDotDot,
|
||||
"invalid use of ... with built-in %s", bin.name)
|
||||
check.use(call.Args...)
|
||||
return
|
||||
}
|
||||
@ -68,7 +70,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
|
||||
msg = "too many"
|
||||
}
|
||||
if msg != "" {
|
||||
check.invalidOp(call.Rparen, _WrongArgCount, "%s arguments for %s (expected %d, found %d)", msg, call, bin.nargs, nargs)
|
||||
check.invalidOp(inNode(call, call.Rparen), _WrongArgCount, "%s arguments for %s (expected %d, found %d)", msg, call, bin.nargs, nargs)
|
||||
return
|
||||
}
|
||||
}
|
||||
@ -85,7 +87,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
|
||||
if s, _ := S.Underlying().(*Slice); s != nil {
|
||||
T = s.elem
|
||||
} else {
|
||||
check.invalidArg(x.pos(), _InvalidAppend, "%s is not a slice", x)
|
||||
check.invalidArg(x, _InvalidAppend, "%s is not a slice", x)
|
||||
return
|
||||
}
|
||||
|
||||
@ -181,7 +183,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
|
||||
if id == _Len {
|
||||
code = _InvalidLen
|
||||
}
|
||||
check.invalidArg(x.pos(), code, "%s for %s", x, bin.name)
|
||||
check.invalidArg(x, code, "%s for %s", x, bin.name)
|
||||
return
|
||||
}
|
||||
|
||||
@ -196,11 +198,11 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
|
||||
// close(c)
|
||||
c, _ := x.typ.Underlying().(*Chan)
|
||||
if c == nil {
|
||||
check.invalidArg(x.pos(), _InvalidClose, "%s is not a channel", x)
|
||||
check.invalidArg(x, _InvalidClose, "%s is not a channel", x)
|
||||
return
|
||||
}
|
||||
if c.dir == RecvOnly {
|
||||
check.invalidArg(x.pos(), _InvalidClose, "%s must not be a receive-only channel", x)
|
||||
check.invalidArg(x, _InvalidClose, "%s must not be a receive-only channel", x)
|
||||
return
|
||||
}
|
||||
|
||||
@ -264,13 +266,13 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
|
||||
|
||||
// both argument types must be identical
|
||||
if !check.identical(x.typ, y.typ) {
|
||||
check.invalidArg(x.pos(), _InvalidComplex, "mismatched types %s and %s", x.typ, y.typ)
|
||||
check.invalidArg(x, _InvalidComplex, "mismatched types %s and %s", x.typ, y.typ)
|
||||
return
|
||||
}
|
||||
|
||||
// the argument types must be of floating-point type
|
||||
if !isFloat(x.typ) {
|
||||
check.invalidArg(x.pos(), _InvalidComplex, "arguments have type %s, expected floating-point", x.typ)
|
||||
check.invalidArg(x, _InvalidComplex, "arguments have type %s, expected floating-point", x.typ)
|
||||
return
|
||||
}
|
||||
|
||||
@ -324,12 +326,12 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
|
||||
}
|
||||
|
||||
if dst == nil || src == nil {
|
||||
check.invalidArg(x.pos(), _InvalidCopy, "copy expects slice arguments; found %s and %s", x, &y)
|
||||
check.invalidArg(x, _InvalidCopy, "copy expects slice arguments; found %s and %s", x, &y)
|
||||
return
|
||||
}
|
||||
|
||||
if !check.identical(dst, src) {
|
||||
check.invalidArg(x.pos(), _InvalidCopy, "arguments to copy %s and %s have different element types %s and %s", x, &y, dst, src)
|
||||
check.invalidArg(x, _InvalidCopy, "arguments to copy %s and %s have different element types %s and %s", x, &y, dst, src)
|
||||
return
|
||||
}
|
||||
|
||||
@ -343,7 +345,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
|
||||
// delete(m, k)
|
||||
m, _ := x.typ.Underlying().(*Map)
|
||||
if m == nil {
|
||||
check.invalidArg(x.pos(), _InvalidDelete, "%s is not a map", x)
|
||||
check.invalidArg(x, _InvalidDelete, "%s is not a map", x)
|
||||
return
|
||||
}
|
||||
arg(x, 1) // k
|
||||
@ -352,7 +354,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
|
||||
}
|
||||
|
||||
if ok, code := x.assignableTo(check, m.key, nil); !ok {
|
||||
check.invalidArg(x.pos(), code, "%s is not assignable to %s", x, m.key)
|
||||
check.invalidArg(x, code, "%s is not assignable to %s", x, m.key)
|
||||
return
|
||||
}
|
||||
|
||||
@ -392,7 +394,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
|
||||
if id == _Real {
|
||||
code = _InvalidReal
|
||||
}
|
||||
check.invalidArg(x.pos(), code, "argument has type %s, expected complex type", x.typ)
|
||||
check.invalidArg(x, code, "argument has type %s, expected complex type", x.typ)
|
||||
return
|
||||
}
|
||||
|
||||
@ -444,11 +446,11 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
|
||||
case *Map, *Chan:
|
||||
min = 1
|
||||
default:
|
||||
check.invalidArg(arg0.Pos(), _InvalidMake, "cannot make %s; type must be slice, map, or channel", arg0)
|
||||
check.invalidArg(arg0, _InvalidMake, "cannot make %s; type must be slice, map, or channel", arg0)
|
||||
return
|
||||
}
|
||||
if nargs < min || min+1 < nargs {
|
||||
check.errorf(call.Pos(), _WrongArgCount, "%v expects %d or %d arguments; found %d", call, min, min+1, nargs)
|
||||
check.errorf(call, _WrongArgCount, "%v expects %d or %d arguments; found %d", call, min, min+1, nargs)
|
||||
return
|
||||
}
|
||||
types := []Type{T}
|
||||
@ -461,7 +463,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
|
||||
}
|
||||
}
|
||||
if len(sizes) == 2 && sizes[0] > sizes[1] {
|
||||
check.invalidArg(call.Args[1].Pos(), _SwappedMakeArgs, "length and capacity swapped")
|
||||
check.invalidArg(call.Args[1], _SwappedMakeArgs, "length and capacity swapped")
|
||||
// safe to continue
|
||||
}
|
||||
x.mode = value
|
||||
@ -559,7 +561,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
|
||||
arg0 := call.Args[0]
|
||||
selx, _ := unparen(arg0).(*ast.SelectorExpr)
|
||||
if selx == nil {
|
||||
check.invalidArg(arg0.Pos(), _BadOffsetofSyntax, "%s is not a selector expression", arg0)
|
||||
check.invalidArg(arg0, _BadOffsetofSyntax, "%s is not a selector expression", arg0)
|
||||
check.use(arg0)
|
||||
return
|
||||
}
|
||||
@ -574,18 +576,18 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
|
||||
obj, index, indirect := check.lookupFieldOrMethod(base, false, check.pkg, sel)
|
||||
switch obj.(type) {
|
||||
case nil:
|
||||
check.invalidArg(x.pos(), _MissingFieldOrMethod, "%s has no single field %s", base, sel)
|
||||
check.invalidArg(x, _MissingFieldOrMethod, "%s has no single field %s", base, sel)
|
||||
return
|
||||
case *Func:
|
||||
// TODO(gri) Using derefStructPtr may result in methods being found
|
||||
// that don't actually exist. An error either way, but the error
|
||||
// message is confusing. See: https://play.golang.org/p/al75v23kUy ,
|
||||
// but go/types reports: "invalid argument: x.m is a method value".
|
||||
check.invalidArg(arg0.Pos(), _InvalidOffsetof, "%s is a method value", arg0)
|
||||
check.invalidArg(arg0, _InvalidOffsetof, "%s is a method value", arg0)
|
||||
return
|
||||
}
|
||||
if indirect {
|
||||
check.invalidArg(x.pos(), _InvalidOffsetof, "field %s is embedded via a pointer in %s", sel, base)
|
||||
check.invalidArg(x, _InvalidOffsetof, "field %s is embedded via a pointer in %s", sel, base)
|
||||
return
|
||||
}
|
||||
|
||||
@ -615,15 +617,15 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
|
||||
// The result of assert is the value of pred if there is no error.
|
||||
// Note: assert is only available in self-test mode.
|
||||
if x.mode != constant_ || !isBoolean(x.typ) {
|
||||
check.invalidArg(x.pos(), _Test, "%s is not a boolean constant", x)
|
||||
check.invalidArg(x, _Test, "%s is not a boolean constant", x)
|
||||
return
|
||||
}
|
||||
if x.val.Kind() != constant.Bool {
|
||||
check.errorf(x.pos(), _Test, "internal error: value of %s should be a boolean constant", x)
|
||||
check.errorf(x, _Test, "internal error: value of %s should be a boolean constant", x)
|
||||
return
|
||||
}
|
||||
if !constant.BoolVal(x.val) {
|
||||
check.errorf(call.Pos(), _Test, "%v failed", call)
|
||||
check.errorf(call, _Test, "%v failed", call)
|
||||
// compile-time assertion failure - safe to continue
|
||||
}
|
||||
// result is constant - no need to record signature
|
||||
@ -643,7 +645,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
|
||||
x1 := x
|
||||
for _, arg := range call.Args {
|
||||
check.rawExpr(x1, arg, nil) // permit trace for types, e.g.: new(trace(T))
|
||||
check.dump("%v: %s", x1.pos(), x1)
|
||||
check.dump("%v: %s", x1.Pos(), x1)
|
||||
x1 = &t // use incoming x only for first argument
|
||||
}
|
||||
// trace is only available in test mode - no need to record signature
|
||||
|
@ -29,7 +29,7 @@ func (check *Checker) call(x *operand, e *ast.CallExpr) exprKind {
|
||||
x.mode = invalid
|
||||
switch n := len(e.Args); n {
|
||||
case 0:
|
||||
check.errorf(e.Rparen, _WrongArgCount, "missing argument in conversion to %s", T)
|
||||
check.errorf(inNode(e, e.Rparen), _WrongArgCount, "missing argument in conversion to %s", T)
|
||||
case 1:
|
||||
check.expr(x, e.Args[0])
|
||||
if x.mode != invalid {
|
||||
@ -37,7 +37,7 @@ func (check *Checker) call(x *operand, e *ast.CallExpr) exprKind {
|
||||
}
|
||||
default:
|
||||
check.use(e.Args...)
|
||||
check.errorf(e.Args[n-1].Pos(), _WrongArgCount, "too many arguments in conversion to %s", T)
|
||||
check.errorf(e.Args[n-1], _WrongArgCount, "too many arguments in conversion to %s", T)
|
||||
}
|
||||
x.expr = e
|
||||
return conversion
|
||||
@ -60,7 +60,7 @@ func (check *Checker) call(x *operand, e *ast.CallExpr) exprKind {
|
||||
|
||||
sig, _ := x.typ.Underlying().(*Signature)
|
||||
if sig == nil {
|
||||
check.invalidOp(x.pos(), _InvalidCall, "cannot call non-function %s", x)
|
||||
check.invalidOp(x, _InvalidCall, "cannot call non-function %s", x)
|
||||
x.mode = invalid
|
||||
x.expr = e
|
||||
return statement
|
||||
@ -231,13 +231,13 @@ func (check *Checker) arguments(x *operand, call *ast.CallExpr, sig *Signature,
|
||||
if call.Ellipsis.IsValid() {
|
||||
// last argument is of the form x...
|
||||
if !sig.variadic {
|
||||
check.errorf(call.Ellipsis, _NonVariadicDotDotDot, "cannot use ... in call to non-variadic %s", call.Fun)
|
||||
check.errorf(atPos(call.Ellipsis), _NonVariadicDotDotDot, "cannot use ... in call to non-variadic %s", call.Fun)
|
||||
check.useGetter(arg, n)
|
||||
return
|
||||
}
|
||||
if len(call.Args) == 1 && n > 1 {
|
||||
// f()... is not permitted if f() is multi-valued
|
||||
check.errorf(call.Ellipsis, _InvalidDotDotDotOperand, "cannot use ... with %d-valued %s", n, call.Args[0])
|
||||
check.errorf(atPos(call.Ellipsis), _InvalidDotDotDotOperand, "cannot use ... with %d-valued %s", n, call.Args[0])
|
||||
check.useGetter(arg, n)
|
||||
return
|
||||
}
|
||||
@ -263,7 +263,7 @@ func (check *Checker) arguments(x *operand, call *ast.CallExpr, sig *Signature,
|
||||
n++
|
||||
}
|
||||
if n < sig.params.Len() {
|
||||
check.errorf(call.Rparen, _WrongArgCount, "too few arguments in call to %s", call.Fun)
|
||||
check.errorf(inNode(call, call.Rparen), _WrongArgCount, "too few arguments in call to %s", call.Fun)
|
||||
// ok to continue
|
||||
}
|
||||
}
|
||||
@ -291,18 +291,18 @@ func (check *Checker) argument(sig *Signature, i int, x *operand, ellipsis token
|
||||
}
|
||||
}
|
||||
default:
|
||||
check.errorf(x.pos(), _WrongArgCount, "too many arguments")
|
||||
check.errorf(x, _WrongArgCount, "too many arguments")
|
||||
return
|
||||
}
|
||||
|
||||
if ellipsis.IsValid() {
|
||||
if i != n-1 {
|
||||
check.errorf(ellipsis, _MisplacedDotDotDot, "can only use ... with matching parameter")
|
||||
check.errorf(atPos(ellipsis), _MisplacedDotDotDot, "can only use ... with matching parameter")
|
||||
return
|
||||
}
|
||||
// argument is of the form x... and x is single-valued
|
||||
if _, ok := x.typ.Underlying().(*Slice); !ok && x.typ != Typ[UntypedNil] { // see issue #18268
|
||||
check.errorf(x.pos(), _InvalidDotDotDotOperand, "cannot use %s as parameter of type %s", x, typ)
|
||||
check.errorf(x, _InvalidDotDotDotOperand, "cannot use %s as parameter of type %s", x, typ)
|
||||
return
|
||||
}
|
||||
} else if sig.variadic && i >= n-1 {
|
||||
@ -365,7 +365,7 @@ func (check *Checker) selector(x *operand, e *ast.SelectorExpr) {
|
||||
}
|
||||
}
|
||||
if exp == nil {
|
||||
check.errorf(e.Sel.Pos(), _UndeclaredImportedName, "%s not declared by package C", sel)
|
||||
check.errorf(e.Sel, _UndeclaredImportedName, "%s not declared by package C", sel)
|
||||
goto Error
|
||||
}
|
||||
check.objDecl(exp, nil)
|
||||
@ -373,12 +373,12 @@ func (check *Checker) selector(x *operand, e *ast.SelectorExpr) {
|
||||
exp = pkg.scope.Lookup(sel)
|
||||
if exp == nil {
|
||||
if !pkg.fake {
|
||||
check.errorf(e.Sel.Pos(), _UndeclaredImportedName, "%s not declared by package %s", sel, pkg.name)
|
||||
check.errorf(e.Sel, _UndeclaredImportedName, "%s not declared by package %s", sel, pkg.name)
|
||||
}
|
||||
goto Error
|
||||
}
|
||||
if !exp.Exported() {
|
||||
check.errorf(e.Sel.Pos(), _UnexportedName, "%s not exported by package %s", sel, pkg.name)
|
||||
check.errorf(e.Sel, _UnexportedName, "%s not exported by package %s", sel, pkg.name)
|
||||
// ok to continue
|
||||
}
|
||||
}
|
||||
@ -431,9 +431,9 @@ func (check *Checker) selector(x *operand, e *ast.SelectorExpr) {
|
||||
switch {
|
||||
case index != nil:
|
||||
// TODO(gri) should provide actual type where the conflict happens
|
||||
check.errorf(e.Sel.Pos(), _AmbiguousSelector, "ambiguous selector %s.%s", x.expr, sel)
|
||||
check.errorf(e.Sel, _AmbiguousSelector, "ambiguous selector %s.%s", x.expr, sel)
|
||||
case indirect:
|
||||
check.errorf(e.Sel.Pos(), _InvalidMethodExpr, "cannot call pointer method %s on %s", sel, x.typ)
|
||||
check.errorf(e.Sel, _InvalidMethodExpr, "cannot call pointer method %s on %s", sel, x.typ)
|
||||
default:
|
||||
// Check if capitalization of sel matters and provide better error
|
||||
// message in that case.
|
||||
@ -445,11 +445,11 @@ func (check *Checker) selector(x *operand, e *ast.SelectorExpr) {
|
||||
changeCase = string(unicode.ToUpper(r)) + sel[1:]
|
||||
}
|
||||
if obj, _, _ = check.lookupFieldOrMethod(x.typ, x.mode == variable, check.pkg, changeCase); obj != nil {
|
||||
check.errorf(e.Sel.Pos(), _MissingFieldOrMethod, "%s.%s undefined (type %s has no field or method %s, but does have %s)", x.expr, sel, x.typ, sel, changeCase)
|
||||
check.errorf(e.Sel, _MissingFieldOrMethod, "%s.%s undefined (type %s has no field or method %s, but does have %s)", x.expr, sel, x.typ, sel, changeCase)
|
||||
break
|
||||
}
|
||||
}
|
||||
check.errorf(e.Sel.Pos(), _MissingFieldOrMethod, "%s.%s undefined (type %s has no field or method %s)", x.expr, sel, x.typ, sel)
|
||||
check.errorf(e.Sel, _MissingFieldOrMethod, "%s.%s undefined (type %s has no field or method %s)", x.expr, sel, x.typ, sel)
|
||||
}
|
||||
goto Error
|
||||
}
|
||||
@ -464,7 +464,7 @@ func (check *Checker) selector(x *operand, e *ast.SelectorExpr) {
|
||||
m, _ := obj.(*Func)
|
||||
if m == nil {
|
||||
// TODO(gri) should check if capitalization of sel matters and provide better error message in that case
|
||||
check.errorf(e.Sel.Pos(), _MissingFieldOrMethod, "%s.%s undefined (type %s has no method %s)", x.expr, sel, x.typ, sel)
|
||||
check.errorf(e.Sel, _MissingFieldOrMethod, "%s.%s undefined (type %s has no method %s)", x.expr, sel, x.typ, sel)
|
||||
goto Error
|
||||
}
|
||||
|
||||
|
@ -85,8 +85,8 @@ type Checker struct {
|
||||
// information collected during type-checking of a set of package files
|
||||
// (initialized by Files, valid only for the duration of check.Files;
|
||||
// maps and lists are allocated on demand)
|
||||
files []*ast.File // package files
|
||||
unusedDotImports map[*Scope]map[*Package]token.Pos // positions of unused dot-imported packages for each file scope
|
||||
files []*ast.File // package files
|
||||
unusedDotImports map[*Scope]map[*Package]*ast.ImportSpec // unused dot-imported packages
|
||||
|
||||
firstErr error // first error encountered
|
||||
methods map[*TypeName][]*Func // maps package scope type names to associated non-blank (non-interface) methods
|
||||
@ -105,18 +105,18 @@ type Checker struct {
|
||||
|
||||
// addUnusedImport adds the position of a dot-imported package
|
||||
// pkg to the map of dot imports for the given file scope.
|
||||
func (check *Checker) addUnusedDotImport(scope *Scope, pkg *Package, pos token.Pos) {
|
||||
func (check *Checker) addUnusedDotImport(scope *Scope, pkg *Package, spec *ast.ImportSpec) {
|
||||
mm := check.unusedDotImports
|
||||
if mm == nil {
|
||||
mm = make(map[*Scope]map[*Package]token.Pos)
|
||||
mm = make(map[*Scope]map[*Package]*ast.ImportSpec)
|
||||
check.unusedDotImports = mm
|
||||
}
|
||||
m := mm[scope]
|
||||
if m == nil {
|
||||
m = make(map[*Package]token.Pos)
|
||||
m = make(map[*Package]*ast.ImportSpec)
|
||||
mm[scope] = m
|
||||
}
|
||||
m[pkg] = pos
|
||||
m[pkg] = spec
|
||||
}
|
||||
|
||||
// addDeclDep adds the dependency edge (check.decl -> to) if check.decl exists
|
||||
@ -217,7 +217,7 @@ func (check *Checker) initFiles(files []*ast.File) {
|
||||
if name != "_" {
|
||||
pkg.name = name
|
||||
} else {
|
||||
check.errorf(file.Name.Pos(), _BlankPkgName, "invalid package name _")
|
||||
check.errorf(file.Name, _BlankPkgName, "invalid package name _")
|
||||
}
|
||||
fallthrough
|
||||
|
||||
@ -225,7 +225,7 @@ func (check *Checker) initFiles(files []*ast.File) {
|
||||
check.files = append(check.files, file)
|
||||
|
||||
default:
|
||||
check.errorf(file.Package, _MismatchedPkgName, "package %s; expected %s", name, pkg.name)
|
||||
check.errorf(atPos(file.Package), _MismatchedPkgName, "package %s; expected %s", name, pkg.name)
|
||||
// ignore this file
|
||||
}
|
||||
}
|
||||
|
@ -38,7 +38,7 @@ func (check *Checker) conversion(x *operand, T Type) {
|
||||
}
|
||||
|
||||
if !ok {
|
||||
check.errorf(x.pos(), _InvalidConversion, "cannot convert %s to %s", x, T)
|
||||
check.errorf(x, _InvalidConversion, "cannot convert %s to %s", x, T)
|
||||
x.mode = invalid
|
||||
return
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ func (check *Checker) reportAltDecl(obj Object) {
|
||||
// We use "other" rather than "previous" here because
|
||||
// the first declaration seen may not be textually
|
||||
// earlier in the source.
|
||||
check.errorf(pos, _DuplicateDecl, "\tother declaration of %s", obj.Name()) // secondary error, \t indented
|
||||
check.errorf(obj, _DuplicateDecl, "\tother declaration of %s", obj.Name()) // secondary error, \t indented
|
||||
}
|
||||
}
|
||||
|
||||
@ -26,7 +26,7 @@ func (check *Checker) declare(scope *Scope, id *ast.Ident, obj Object, pos token
|
||||
// binding."
|
||||
if obj.Name() != "_" {
|
||||
if alt := scope.Insert(obj); alt != nil {
|
||||
check.errorf(obj.Pos(), _DuplicateDecl, "%s redeclared in this block", obj.Name())
|
||||
check.errorf(obj, _DuplicateDecl, "%s redeclared in this block", obj.Name())
|
||||
check.reportAltDecl(alt)
|
||||
return
|
||||
}
|
||||
@ -357,16 +357,16 @@ func (check *Checker) cycleError(cycle []Object) {
|
||||
// cycle? That would be more consistent with other error messages.
|
||||
i := firstInSrc(cycle)
|
||||
obj := cycle[i]
|
||||
check.errorf(obj.Pos(), _InvalidDeclCycle, "illegal cycle in declaration of %s", obj.Name())
|
||||
check.errorf(obj, _InvalidDeclCycle, "illegal cycle in declaration of %s", obj.Name())
|
||||
for range cycle {
|
||||
check.errorf(obj.Pos(), _InvalidDeclCycle, "\t%s refers to", obj.Name()) // secondary error, \t indented
|
||||
check.errorf(obj, _InvalidDeclCycle, "\t%s refers to", obj.Name()) // secondary error, \t indented
|
||||
i++
|
||||
if i >= len(cycle) {
|
||||
i = 0
|
||||
}
|
||||
obj = cycle[i]
|
||||
}
|
||||
check.errorf(obj.Pos(), _InvalidDeclCycle, "\t%s", obj.Name())
|
||||
check.errorf(obj, _InvalidDeclCycle, "\t%s", obj.Name())
|
||||
}
|
||||
|
||||
// firstInSrc reports the index of the object with the "smallest"
|
||||
@ -436,18 +436,18 @@ func (check *Checker) walkDecl(d ast.Decl, f func(decl)) {
|
||||
check.arityMatch(s, nil)
|
||||
f(varDecl{s})
|
||||
default:
|
||||
check.invalidAST(s.Pos(), "invalid token %s", d.Tok)
|
||||
check.invalidAST(s, "invalid token %s", d.Tok)
|
||||
}
|
||||
case *ast.TypeSpec:
|
||||
f(typeDecl{s})
|
||||
default:
|
||||
check.invalidAST(s.Pos(), "unknown ast.Spec node %T", s)
|
||||
check.invalidAST(s, "unknown ast.Spec node %T", s)
|
||||
}
|
||||
}
|
||||
case *ast.FuncDecl:
|
||||
f(funcDecl{d})
|
||||
default:
|
||||
check.invalidAST(d.Pos(), "unknown ast.Decl node %T", d)
|
||||
check.invalidAST(d, "unknown ast.Decl node %T", d)
|
||||
}
|
||||
}
|
||||
|
||||
@ -468,7 +468,7 @@ func (check *Checker) constDecl(obj *Const, typ, init ast.Expr) {
|
||||
// don't report an error if the type is an invalid C (defined) type
|
||||
// (issue #22090)
|
||||
if t.Underlying() != Typ[Invalid] {
|
||||
check.errorf(typ.Pos(), _InvalidConstType, "invalid constant type %s", t)
|
||||
check.errorf(typ, _InvalidConstType, "invalid constant type %s", t)
|
||||
}
|
||||
obj.typ = Typ[Invalid]
|
||||
return
|
||||
@ -694,9 +694,9 @@ func (check *Checker) addMethodDecls(obj *TypeName) {
|
||||
if alt := mset.insert(m); alt != nil {
|
||||
switch alt.(type) {
|
||||
case *Var:
|
||||
check.errorf(m.pos, _DuplicateFieldAndMethod, "field and method with the same name %s", m.name)
|
||||
check.errorf(m, _DuplicateFieldAndMethod, "field and method with the same name %s", m.name)
|
||||
case *Func:
|
||||
check.errorf(m.pos, _DuplicateMethod, "method %s already declared for %s", m.name, obj)
|
||||
check.errorf(m, _DuplicateMethod, "method %s already declared for %s", m.name, obj)
|
||||
default:
|
||||
unreachable()
|
||||
}
|
||||
@ -721,7 +721,7 @@ func (check *Checker) funcDecl(obj *Func, decl *declInfo) {
|
||||
fdecl := decl.fdecl
|
||||
check.funcType(sig, fdecl.Recv, fdecl.Type)
|
||||
if sig.recv == nil && obj.name == "init" && (sig.params.Len() > 0 || sig.results.Len() > 0) {
|
||||
check.errorf(fdecl.Pos(), _InvalidInitSig, "func init must have no arguments and no return values")
|
||||
check.errorf(fdecl, _InvalidInitSig, "func init must have no arguments and no return values")
|
||||
// ok to continue
|
||||
}
|
||||
|
||||
@ -832,7 +832,7 @@ func (check *Checker) declStmt(d ast.Decl) {
|
||||
check.typeDecl(obj, d.spec.Type, nil, d.spec.Assign.IsValid())
|
||||
check.pop().setColor(black)
|
||||
default:
|
||||
check.invalidAST(d.node().Pos(), "unknown ast.Decl node %T", d.node())
|
||||
check.invalidAST(d.node(), "unknown ast.Decl node %T", d.node())
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -110,43 +110,106 @@ func (check *Checker) err(err error) {
|
||||
f(err)
|
||||
}
|
||||
|
||||
func (check *Checker) error(pos token.Pos, code errorCode, msg string) {
|
||||
check.err(Error{Fset: check.fset, Pos: pos, Msg: msg, go116code: code})
|
||||
}
|
||||
|
||||
// newErrorf creates a new Error, but does not handle it.
|
||||
func (check *Checker) newErrorf(pos token.Pos, code errorCode, format string, args ...interface{}) error {
|
||||
func (check *Checker) newError(at positioner, code errorCode, soft bool, msg string) error {
|
||||
ext := spanOf(at)
|
||||
return Error{
|
||||
Fset: check.fset,
|
||||
Pos: pos,
|
||||
Msg: check.sprintf(format, args...),
|
||||
Soft: false,
|
||||
go116code: code,
|
||||
Fset: check.fset,
|
||||
Pos: ext.pos,
|
||||
Msg: msg,
|
||||
Soft: soft,
|
||||
go116code: code,
|
||||
go116start: ext.start,
|
||||
go116end: ext.end,
|
||||
}
|
||||
}
|
||||
|
||||
func (check *Checker) errorf(pos token.Pos, code errorCode, format string, args ...interface{}) {
|
||||
check.error(pos, code, check.sprintf(format, args...))
|
||||
// newErrorf creates a new Error, but does not handle it.
|
||||
func (check *Checker) newErrorf(at positioner, code errorCode, soft bool, format string, args ...interface{}) error {
|
||||
msg := check.sprintf(format, args...)
|
||||
return check.newError(at, code, soft, msg)
|
||||
}
|
||||
|
||||
func (check *Checker) softErrorf(pos token.Pos, code errorCode, format string, args ...interface{}) {
|
||||
check.err(Error{
|
||||
Fset: check.fset,
|
||||
Pos: pos,
|
||||
Msg: check.sprintf(format, args...),
|
||||
Soft: true,
|
||||
go116code: code,
|
||||
})
|
||||
func (check *Checker) error(at positioner, code errorCode, msg string) {
|
||||
check.err(check.newError(at, code, false, msg))
|
||||
}
|
||||
|
||||
func (check *Checker) invalidAST(pos token.Pos, format string, args ...interface{}) {
|
||||
check.errorf(pos, 0, "invalid AST: "+format, args...)
|
||||
func (check *Checker) errorf(at positioner, code errorCode, format string, args ...interface{}) {
|
||||
check.error(at, code, check.sprintf(format, args...))
|
||||
}
|
||||
|
||||
func (check *Checker) invalidArg(pos token.Pos, code errorCode, format string, args ...interface{}) {
|
||||
check.errorf(pos, code, "invalid argument: "+format, args...)
|
||||
func (check *Checker) softErrorf(at positioner, code errorCode, format string, args ...interface{}) {
|
||||
check.err(check.newErrorf(at, code, true, format, args...))
|
||||
}
|
||||
|
||||
func (check *Checker) invalidOp(pos token.Pos, code errorCode, format string, args ...interface{}) {
|
||||
check.errorf(pos, code, "invalid operation: "+format, args...)
|
||||
func (check *Checker) invalidAST(at positioner, format string, args ...interface{}) {
|
||||
check.errorf(at, 0, "invalid AST: "+format, args...)
|
||||
}
|
||||
|
||||
func (check *Checker) invalidArg(at positioner, code errorCode, format string, args ...interface{}) {
|
||||
check.errorf(at, code, "invalid argument: "+format, args...)
|
||||
}
|
||||
|
||||
func (check *Checker) invalidOp(at positioner, code errorCode, format string, args ...interface{}) {
|
||||
check.errorf(at, code, "invalid operation: "+format, args...)
|
||||
}
|
||||
|
||||
// The positioner interface is used to extract the position of type-checker
|
||||
// errors.
|
||||
type positioner interface {
|
||||
Pos() token.Pos
|
||||
}
|
||||
|
||||
// posSpan holds a position range along with a highlighted position within that
|
||||
// range. This is used for positioning errors, with pos by convention being the
|
||||
// first position in the source where the error is known to exist, and start
|
||||
// and end defining the full span of syntax being considered when the error was
|
||||
// detected. Invariant: start <= pos < end || start == pos == end.
|
||||
type posSpan struct {
|
||||
start, pos, end token.Pos
|
||||
}
|
||||
|
||||
func (e posSpan) Pos() token.Pos {
|
||||
return e.pos
|
||||
}
|
||||
|
||||
// inNode creates a posSpan for the given node.
|
||||
// Invariant: node.Pos() <= pos < node.End() (node.End() is the position of the
|
||||
// first byte after node within the source).
|
||||
func inNode(node ast.Node, pos token.Pos) posSpan {
|
||||
start, end := node.Pos(), node.End()
|
||||
if debug {
|
||||
assert(start <= pos && pos < end)
|
||||
}
|
||||
return posSpan{start, pos, end}
|
||||
}
|
||||
|
||||
// atPos wraps a token.Pos to implement the positioner interface.
|
||||
type atPos token.Pos
|
||||
|
||||
func (s atPos) Pos() token.Pos {
|
||||
return token.Pos(s)
|
||||
}
|
||||
|
||||
// spanOf extracts an error span from the given positioner. By default this is
|
||||
// the trivial span starting and ending at pos, but this span is expanded when
|
||||
// the argument naturally corresponds to a span of source code.
|
||||
func spanOf(at positioner) posSpan {
|
||||
switch x := at.(type) {
|
||||
case nil:
|
||||
panic("internal error: nil")
|
||||
case posSpan:
|
||||
return x
|
||||
case ast.Node:
|
||||
pos := x.Pos()
|
||||
return posSpan{pos, pos, x.End()}
|
||||
case *operand:
|
||||
if x.expr != nil {
|
||||
pos := x.Pos()
|
||||
return posSpan{pos, pos, x.expr.End()}
|
||||
}
|
||||
return posSpan{token.NoPos, token.NoPos, token.NoPos}
|
||||
default:
|
||||
pos := at.Pos()
|
||||
return posSpan{pos, pos, pos}
|
||||
}
|
||||
}
|
||||
|
@ -68,11 +68,11 @@ var unaryOpPredicates = opPredicates{
|
||||
func (check *Checker) op(m opPredicates, x *operand, op token.Token) bool {
|
||||
if pred := m[op]; pred != nil {
|
||||
if !pred(x.typ) {
|
||||
check.invalidOp(x.pos(), _UndefinedOp, "operator %s not defined for %s", op, x)
|
||||
check.invalidOp(x, _UndefinedOp, "operator %s not defined for %s", op, x)
|
||||
return false
|
||||
}
|
||||
} else {
|
||||
check.invalidAST(x.pos(), "unknown operator %s", op)
|
||||
check.invalidAST(x, "unknown operator %s", op)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
@ -85,7 +85,7 @@ func (check *Checker) unary(x *operand, e *ast.UnaryExpr, op token.Token) {
|
||||
// spec: "As an exception to the addressability
|
||||
// requirement x may also be a composite literal."
|
||||
if _, ok := unparen(x.expr).(*ast.CompositeLit); !ok && x.mode != variable {
|
||||
check.invalidOp(x.pos(), _UnaddressableOperand, "cannot take address of %s", x)
|
||||
check.invalidOp(x, _UnaddressableOperand, "cannot take address of %s", x)
|
||||
x.mode = invalid
|
||||
return
|
||||
}
|
||||
@ -96,12 +96,12 @@ func (check *Checker) unary(x *operand, e *ast.UnaryExpr, op token.Token) {
|
||||
case token.ARROW:
|
||||
typ, ok := x.typ.Underlying().(*Chan)
|
||||
if !ok {
|
||||
check.invalidOp(x.pos(), _InvalidReceive, "cannot receive from non-channel %s", x)
|
||||
check.invalidOp(x, _InvalidReceive, "cannot receive from non-channel %s", x)
|
||||
x.mode = invalid
|
||||
return
|
||||
}
|
||||
if typ.dir == SendOnly {
|
||||
check.invalidOp(x.pos(), _InvalidReceive, "cannot receive from send-only channel %s", x)
|
||||
check.invalidOp(x, _InvalidReceive, "cannot receive from send-only channel %s", x)
|
||||
x.mode = invalid
|
||||
return
|
||||
}
|
||||
@ -362,7 +362,7 @@ func (check *Checker) isRepresentable(x *operand, typ *Basic) error {
|
||||
msg = "cannot convert %s to %s"
|
||||
code = _InvalidConstVal
|
||||
}
|
||||
return check.newErrorf(x.pos(), code, msg, x, typ)
|
||||
return check.newErrorf(x, code, false, msg, x, typ)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@ -470,7 +470,7 @@ func (check *Checker) updateExprType(x ast.Expr, typ Type, final bool) {
|
||||
// We already know from the shift check that it is representable
|
||||
// as an integer if it is a constant.
|
||||
if !isInteger(typ) {
|
||||
check.invalidOp(x.Pos(), _InvalidShiftOperand, "shifted operand %s (type %s) must be integer", x, typ)
|
||||
check.invalidOp(x, _InvalidShiftOperand, "shifted operand %s (type %s) must be integer", x, typ)
|
||||
return
|
||||
}
|
||||
// Even if we have an integer, if the value is a constant we
|
||||
@ -521,7 +521,7 @@ func (check *Checker) canConvertUntyped(x *operand, target Type) error {
|
||||
check.updateExprType(x.expr, target, false)
|
||||
}
|
||||
} else if xkind != tkind {
|
||||
return check.newErrorf(x.pos(), _InvalidUntypedConversion, "cannot convert %s to %s", x, target)
|
||||
return check.newErrorf(x, _InvalidUntypedConversion, false, "cannot convert %s to %s", x, target)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@ -535,7 +535,7 @@ func (check *Checker) canConvertUntyped(x *operand, target Type) error {
|
||||
} else {
|
||||
newTarget := check.implicitType(x, target)
|
||||
if newTarget == nil {
|
||||
return check.newErrorf(x.pos(), _InvalidUntypedConversion, "cannot convert %s to %s", x, target)
|
||||
return check.newErrorf(x, _InvalidUntypedConversion, false, "cannot convert %s to %s", x, target)
|
||||
}
|
||||
target = newTarget
|
||||
}
|
||||
@ -641,7 +641,7 @@ func (check *Checker) comparison(x, y *operand, op token.Token) {
|
||||
}
|
||||
|
||||
if err != "" {
|
||||
check.errorf(x.pos(), code, "cannot compare %s %s %s (%s)", x.expr, op, y.expr, err)
|
||||
check.errorf(x, code, "cannot compare %s %s %s (%s)", x.expr, op, y.expr, err)
|
||||
x.mode = invalid
|
||||
return
|
||||
}
|
||||
@ -678,7 +678,7 @@ func (check *Checker) shift(x, y *operand, e *ast.BinaryExpr, op token.Token) {
|
||||
// as an integer. Nothing to do.
|
||||
} else {
|
||||
// shift has no chance
|
||||
check.invalidOp(x.pos(), _InvalidShiftOperand, "shifted operand %s must be integer", x)
|
||||
check.invalidOp(x, _InvalidShiftOperand, "shifted operand %s must be integer", x)
|
||||
x.mode = invalid
|
||||
return
|
||||
}
|
||||
@ -695,7 +695,7 @@ func (check *Checker) shift(x, y *operand, e *ast.BinaryExpr, op token.Token) {
|
||||
return
|
||||
}
|
||||
default:
|
||||
check.invalidOp(y.pos(), _InvalidShiftCount, "shift count %s must be integer", y)
|
||||
check.invalidOp(y, _InvalidShiftCount, "shift count %s must be integer", y)
|
||||
x.mode = invalid
|
||||
return
|
||||
}
|
||||
@ -708,7 +708,7 @@ func (check *Checker) shift(x, y *operand, e *ast.BinaryExpr, op token.Token) {
|
||||
yval = constant.ToInt(y.val)
|
||||
assert(yval.Kind() == constant.Int)
|
||||
if constant.Sign(yval) < 0 {
|
||||
check.invalidOp(y.pos(), _InvalidShiftCount, "negative shift count %s", y)
|
||||
check.invalidOp(y, _InvalidShiftCount, "negative shift count %s", y)
|
||||
x.mode = invalid
|
||||
return
|
||||
}
|
||||
@ -720,7 +720,7 @@ func (check *Checker) shift(x, y *operand, e *ast.BinaryExpr, op token.Token) {
|
||||
const shiftBound = 1023 - 1 + 52 // so we can express smallestFloat64
|
||||
s, ok := constant.Uint64Val(yval)
|
||||
if !ok || s > shiftBound {
|
||||
check.invalidOp(y.pos(), _InvalidShiftCount, "invalid shift count %s", y)
|
||||
check.invalidOp(y, _InvalidShiftCount, "invalid shift count %s", y)
|
||||
x.mode = invalid
|
||||
return
|
||||
}
|
||||
@ -777,7 +777,7 @@ func (check *Checker) shift(x, y *operand, e *ast.BinaryExpr, op token.Token) {
|
||||
|
||||
// non-constant shift - lhs must be an integer
|
||||
if !isInteger(x.typ) {
|
||||
check.invalidOp(x.pos(), _InvalidShiftOperand, "shifted operand %s must be integer", x)
|
||||
check.invalidOp(x, _InvalidShiftOperand, "shifted operand %s must be integer", x)
|
||||
x.mode = invalid
|
||||
return
|
||||
}
|
||||
@ -841,7 +841,11 @@ func (check *Checker) binary(x *operand, e *ast.BinaryExpr, lhs, rhs ast.Expr, o
|
||||
// only report an error if we have valid types
|
||||
// (otherwise we had an error reported elsewhere already)
|
||||
if x.typ != Typ[Invalid] && y.typ != Typ[Invalid] {
|
||||
check.invalidOp(x.pos(), _MismatchedTypes, "mismatched types %s and %s", x.typ, y.typ)
|
||||
var posn positioner = x
|
||||
if e != nil {
|
||||
posn = e
|
||||
}
|
||||
check.invalidOp(posn, _MismatchedTypes, "mismatched types %s and %s", x.typ, y.typ)
|
||||
}
|
||||
x.mode = invalid
|
||||
return
|
||||
@ -855,7 +859,7 @@ func (check *Checker) binary(x *operand, e *ast.BinaryExpr, lhs, rhs ast.Expr, o
|
||||
if op == token.QUO || op == token.REM {
|
||||
// check for zero divisor
|
||||
if (x.mode == constant_ || isInteger(x.typ)) && y.mode == constant_ && constant.Sign(y.val) == 0 {
|
||||
check.invalidOp(y.pos(), _DivByZero, "division by zero")
|
||||
check.invalidOp(&y, _DivByZero, "division by zero")
|
||||
x.mode = invalid
|
||||
return
|
||||
}
|
||||
@ -865,7 +869,7 @@ func (check *Checker) binary(x *operand, e *ast.BinaryExpr, lhs, rhs ast.Expr, o
|
||||
re, im := constant.Real(y.val), constant.Imag(y.val)
|
||||
re2, im2 := constant.BinaryOp(re, token.MUL, re), constant.BinaryOp(im, token.MUL, im)
|
||||
if constant.Sign(re2) == 0 && constant.Sign(im2) == 0 {
|
||||
check.invalidOp(y.pos(), _DivByZero, "division by zero")
|
||||
check.invalidOp(&y, _DivByZero, "division by zero")
|
||||
x.mode = invalid
|
||||
return
|
||||
}
|
||||
@ -918,7 +922,7 @@ func (check *Checker) index(index ast.Expr, max int64) (typ Type, val int64) {
|
||||
|
||||
// the index must be of integer type
|
||||
if !isInteger(x.typ) {
|
||||
check.invalidArg(x.pos(), _InvalidIndex, "index %s must be integer", &x)
|
||||
check.invalidArg(&x, _InvalidIndex, "index %s must be integer", &x)
|
||||
return
|
||||
}
|
||||
|
||||
@ -928,13 +932,13 @@ func (check *Checker) index(index ast.Expr, max int64) (typ Type, val int64) {
|
||||
|
||||
// a constant index i must be in bounds
|
||||
if constant.Sign(x.val) < 0 {
|
||||
check.invalidArg(x.pos(), _InvalidIndex, "index %s must not be negative", &x)
|
||||
check.invalidArg(&x, _InvalidIndex, "index %s must not be negative", &x)
|
||||
return
|
||||
}
|
||||
|
||||
v, valid := constant.Int64Val(constant.ToInt(x.val))
|
||||
if !valid || max >= 0 && v >= max {
|
||||
check.errorf(x.pos(), _InvalidIndex, "index %s is out of bounds", &x)
|
||||
check.errorf(&x, _InvalidIndex, "index %s is out of bounds", &x)
|
||||
return
|
||||
}
|
||||
|
||||
@ -960,12 +964,12 @@ func (check *Checker) indexedElts(elts []ast.Expr, typ Type, length int64) int64
|
||||
index = i
|
||||
validIndex = true
|
||||
} else {
|
||||
check.errorf(e.Pos(), _InvalidLitIndex, "index %s must be integer constant", kv.Key)
|
||||
check.errorf(e, _InvalidLitIndex, "index %s must be integer constant", kv.Key)
|
||||
}
|
||||
}
|
||||
eval = kv.Value
|
||||
} else if length >= 0 && index >= length {
|
||||
check.errorf(e.Pos(), _OversizeArrayLit, "index %d is out of bounds (>= %d)", index, length)
|
||||
check.errorf(e, _OversizeArrayLit, "index %d is out of bounds (>= %d)", index, length)
|
||||
} else {
|
||||
validIndex = true
|
||||
}
|
||||
@ -973,7 +977,7 @@ func (check *Checker) indexedElts(elts []ast.Expr, typ Type, length int64) int64
|
||||
// if we have a valid index, check for duplicate entries
|
||||
if validIndex {
|
||||
if visited[index] {
|
||||
check.errorf(e.Pos(), _DuplicateLitKey, "duplicate index %d in array or slice literal", index)
|
||||
check.errorf(e, _DuplicateLitKey, "duplicate index %d in array or slice literal", index)
|
||||
}
|
||||
visited[index] = true
|
||||
}
|
||||
@ -1063,13 +1067,13 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
|
||||
case *ast.Ellipsis:
|
||||
// ellipses are handled explicitly where they are legal
|
||||
// (array composite literals and parameter lists)
|
||||
check.error(e.Pos(), _BadDotDotDotSyntax, "invalid use of '...'")
|
||||
check.error(e, _BadDotDotDotSyntax, "invalid use of '...'")
|
||||
goto Error
|
||||
|
||||
case *ast.BasicLit:
|
||||
x.setConst(e.Kind, e.Value)
|
||||
if x.mode == invalid {
|
||||
check.invalidAST(e.Pos(), "invalid literal %v", e.Value)
|
||||
check.invalidAST(e, "invalid literal %v", e.Value)
|
||||
goto Error
|
||||
}
|
||||
|
||||
@ -1090,7 +1094,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
|
||||
x.mode = value
|
||||
x.typ = sig
|
||||
} else {
|
||||
check.invalidAST(e.Pos(), "invalid function literal %s", e)
|
||||
check.invalidAST(e, "invalid function literal %s", e)
|
||||
goto Error
|
||||
}
|
||||
|
||||
@ -1122,7 +1126,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
|
||||
|
||||
default:
|
||||
// TODO(gri) provide better error messages depending on context
|
||||
check.error(e.Pos(), _UntypedLit, "missing type in composite literal")
|
||||
check.error(e, _UntypedLit, "missing type in composite literal")
|
||||
goto Error
|
||||
}
|
||||
|
||||
@ -1138,7 +1142,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
|
||||
for _, e := range e.Elts {
|
||||
kv, _ := e.(*ast.KeyValueExpr)
|
||||
if kv == nil {
|
||||
check.error(e.Pos(), _MixedStructLit, "mixture of field:value and value elements in struct literal")
|
||||
check.error(e, _MixedStructLit, "mixture of field:value and value elements in struct literal")
|
||||
continue
|
||||
}
|
||||
key, _ := kv.Key.(*ast.Ident)
|
||||
@ -1146,12 +1150,12 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
|
||||
// so we don't drop information on the floor
|
||||
check.expr(x, kv.Value)
|
||||
if key == nil {
|
||||
check.errorf(kv.Pos(), _InvalidLitField, "invalid field name %s in struct literal", kv.Key)
|
||||
check.errorf(kv, _InvalidLitField, "invalid field name %s in struct literal", kv.Key)
|
||||
continue
|
||||
}
|
||||
i := fieldIndex(utyp.fields, check.pkg, key.Name)
|
||||
if i < 0 {
|
||||
check.errorf(kv.Pos(), _MissingLitField, "unknown field %s in struct literal", key.Name)
|
||||
check.errorf(kv, _MissingLitField, "unknown field %s in struct literal", key.Name)
|
||||
continue
|
||||
}
|
||||
fld := fields[i]
|
||||
@ -1160,7 +1164,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
|
||||
check.assignment(x, etyp, "struct literal")
|
||||
// 0 <= i < len(fields)
|
||||
if visited[i] {
|
||||
check.errorf(kv.Pos(), _DuplicateLitField, "duplicate field name %s in struct literal", key.Name)
|
||||
check.errorf(kv, _DuplicateLitField, "duplicate field name %s in struct literal", key.Name)
|
||||
continue
|
||||
}
|
||||
visited[i] = true
|
||||
@ -1169,25 +1173,27 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
|
||||
// no element must have a key
|
||||
for i, e := range e.Elts {
|
||||
if kv, _ := e.(*ast.KeyValueExpr); kv != nil {
|
||||
check.error(kv.Pos(), _MixedStructLit, "mixture of field:value and value elements in struct literal")
|
||||
check.error(kv, _MixedStructLit, "mixture of field:value and value elements in struct literal")
|
||||
continue
|
||||
}
|
||||
check.expr(x, e)
|
||||
if i >= len(fields) {
|
||||
check.error(x.pos(), _InvalidStructLit, "too many values in struct literal")
|
||||
check.error(x, _InvalidStructLit, "too many values in struct literal")
|
||||
break // cannot continue
|
||||
}
|
||||
// i < len(fields)
|
||||
fld := fields[i]
|
||||
if !fld.Exported() && fld.pkg != check.pkg {
|
||||
check.errorf(x.pos(), _UnexportedLitField, "implicit assignment to unexported field %s in %s literal", fld.name, typ)
|
||||
check.errorf(x,
|
||||
_UnexportedLitField,
|
||||
"implicit assignment to unexported field %s in %s literal", fld.name, typ)
|
||||
continue
|
||||
}
|
||||
etyp := fld.typ
|
||||
check.assignment(x, etyp, "struct literal")
|
||||
}
|
||||
if len(e.Elts) < len(fields) {
|
||||
check.error(e.Rbrace, _InvalidStructLit, "too few values in struct literal")
|
||||
check.error(inNode(e, e.Rbrace), _InvalidStructLit, "too few values in struct literal")
|
||||
// ok to continue
|
||||
}
|
||||
}
|
||||
@ -1197,7 +1203,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
|
||||
// This is a stop-gap solution. Should use Checker.objPath to report entire
|
||||
// path starting with earliest declaration in the source. TODO(gri) fix this.
|
||||
if utyp.elem == nil {
|
||||
check.error(e.Pos(), _InvalidTypeCycle, "illegal cycle in type declaration")
|
||||
check.error(e, _InvalidTypeCycle, "illegal cycle in type declaration")
|
||||
goto Error
|
||||
}
|
||||
n := check.indexedElts(e.Elts, utyp.elem, utyp.len)
|
||||
@ -1224,7 +1230,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
|
||||
// Prevent crash if the slice referred to is not yet set up.
|
||||
// See analogous comment for *Array.
|
||||
if utyp.elem == nil {
|
||||
check.error(e.Pos(), _InvalidTypeCycle, "illegal cycle in type declaration")
|
||||
check.error(e, _InvalidTypeCycle, "illegal cycle in type declaration")
|
||||
goto Error
|
||||
}
|
||||
check.indexedElts(e.Elts, utyp.elem, -1)
|
||||
@ -1233,14 +1239,14 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
|
||||
// Prevent crash if the map referred to is not yet set up.
|
||||
// See analogous comment for *Array.
|
||||
if utyp.key == nil || utyp.elem == nil {
|
||||
check.error(e.Pos(), _InvalidTypeCycle, "illegal cycle in type declaration")
|
||||
check.error(e, _InvalidTypeCycle, "illegal cycle in type declaration")
|
||||
goto Error
|
||||
}
|
||||
visited := make(map[interface{}][]Type, len(e.Elts))
|
||||
for _, e := range e.Elts {
|
||||
kv, _ := e.(*ast.KeyValueExpr)
|
||||
if kv == nil {
|
||||
check.error(e.Pos(), _MissingLitKey, "missing key in map literal")
|
||||
check.error(e, _MissingLitKey, "missing key in map literal")
|
||||
continue
|
||||
}
|
||||
check.exprWithHint(x, kv.Key, utyp.key)
|
||||
@ -1265,7 +1271,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
|
||||
visited[xkey] = nil
|
||||
}
|
||||
if duplicate {
|
||||
check.errorf(x.pos(), _DuplicateLitKey, "duplicate key %s in map literal", x.val)
|
||||
check.errorf(x, _DuplicateLitKey, "duplicate key %s in map literal", x.val)
|
||||
continue
|
||||
}
|
||||
}
|
||||
@ -1287,7 +1293,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
|
||||
}
|
||||
// if utyp is invalid, an error was reported before
|
||||
if utyp != Typ[Invalid] {
|
||||
check.errorf(e.Pos(), _InvalidLit, "invalid composite literal type %s", typ)
|
||||
check.errorf(e, _InvalidLit, "invalid composite literal type %s", typ)
|
||||
goto Error
|
||||
}
|
||||
}
|
||||
@ -1361,12 +1367,12 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
|
||||
}
|
||||
|
||||
if !valid {
|
||||
check.invalidOp(x.pos(), _NonIndexableOperand, "cannot index %s", x)
|
||||
check.invalidOp(x, _NonIndexableOperand, "cannot index %s", x)
|
||||
goto Error
|
||||
}
|
||||
|
||||
if e.Index == nil {
|
||||
check.invalidAST(e.Pos(), "missing index for %s", x)
|
||||
check.invalidAST(e, "missing index for %s", x)
|
||||
goto Error
|
||||
}
|
||||
|
||||
@ -1386,7 +1392,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
|
||||
case *Basic:
|
||||
if isString(typ) {
|
||||
if e.Slice3 {
|
||||
check.invalidOp(x.pos(), _InvalidSliceExpr, "3-index slice of string")
|
||||
check.invalidOp(x, _InvalidSliceExpr, "3-index slice of string")
|
||||
goto Error
|
||||
}
|
||||
valid = true
|
||||
@ -1404,7 +1410,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
|
||||
valid = true
|
||||
length = typ.len
|
||||
if x.mode != variable {
|
||||
check.invalidOp(x.pos(), _NonSliceableOperand, "cannot slice %s (value not addressable)", x)
|
||||
check.invalidOp(x, _NonSliceableOperand, "cannot slice %s (value not addressable)", x)
|
||||
goto Error
|
||||
}
|
||||
x.typ = &Slice{elem: typ.elem}
|
||||
@ -1422,7 +1428,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
|
||||
}
|
||||
|
||||
if !valid {
|
||||
check.invalidOp(x.pos(), _NonSliceableOperand, "cannot slice %s", x)
|
||||
check.invalidOp(x, _NonSliceableOperand, "cannot slice %s", x)
|
||||
goto Error
|
||||
}
|
||||
|
||||
@ -1430,7 +1436,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
|
||||
|
||||
// spec: "Only the first index may be omitted; it defaults to 0."
|
||||
if e.Slice3 && (e.High == nil || e.Max == nil) {
|
||||
check.invalidAST(e.Rbrack, "2nd and 3rd index required in 3-index slice")
|
||||
check.invalidAST(inNode(e, e.Rbrack), "2nd and 3rd index required in 3-index slice")
|
||||
goto Error
|
||||
}
|
||||
|
||||
@ -1467,7 +1473,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
|
||||
if x > 0 {
|
||||
for _, y := range ind[i+1:] {
|
||||
if y >= 0 && x > y {
|
||||
check.errorf(e.Rbrack, _SwappedSliceIndices, "swapped slice indices: %d > %d", x, y)
|
||||
check.errorf(inNode(e, e.Rbrack), _SwappedSliceIndices, "swapped slice indices: %d > %d", x, y)
|
||||
break L // only report one error, ok to continue
|
||||
}
|
||||
}
|
||||
@ -1481,21 +1487,21 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
|
||||
}
|
||||
xtyp, _ := x.typ.Underlying().(*Interface)
|
||||
if xtyp == nil {
|
||||
check.invalidOp(x.pos(), _InvalidAssert, "%s is not an interface", x)
|
||||
check.invalidOp(x, _InvalidAssert, "%s is not an interface", x)
|
||||
goto Error
|
||||
}
|
||||
// x.(type) expressions are handled explicitly in type switches
|
||||
if e.Type == nil {
|
||||
// Don't use invalidAST because this can occur in the AST produced by
|
||||
// go/parser.
|
||||
check.error(e.Pos(), _BadTypeKeyword, "use of .(type) outside type switch")
|
||||
check.error(e, _BadTypeKeyword, "use of .(type) outside type switch")
|
||||
goto Error
|
||||
}
|
||||
T := check.typ(e.Type)
|
||||
if T == Typ[Invalid] {
|
||||
goto Error
|
||||
}
|
||||
check.typeAssertion(x.pos(), x, xtyp, T)
|
||||
check.typeAssertion(x, x, xtyp, T)
|
||||
x.mode = commaok
|
||||
x.typ = T
|
||||
|
||||
@ -1514,7 +1520,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
|
||||
x.mode = variable
|
||||
x.typ = typ.base
|
||||
} else {
|
||||
check.invalidOp(x.pos(), _InvalidIndirection, "cannot indirect %s", x)
|
||||
check.invalidOp(x, _InvalidIndirection, "cannot indirect %s", x)
|
||||
goto Error
|
||||
}
|
||||
}
|
||||
@ -1541,7 +1547,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
|
||||
|
||||
case *ast.KeyValueExpr:
|
||||
// key:value expressions are handled in composite literals
|
||||
check.invalidAST(e.Pos(), "no key:value expected")
|
||||
check.invalidAST(e, "no key:value expected")
|
||||
goto Error
|
||||
|
||||
case *ast.ArrayType, *ast.StructType, *ast.FuncType,
|
||||
@ -1593,7 +1599,7 @@ func keyVal(x constant.Value) interface{} {
|
||||
}
|
||||
|
||||
// typeAssertion checks that x.(T) is legal; xtyp must be the type of x.
|
||||
func (check *Checker) typeAssertion(pos token.Pos, x *operand, xtyp *Interface, T Type) {
|
||||
func (check *Checker) typeAssertion(at positioner, x *operand, xtyp *Interface, T Type) {
|
||||
method, wrongType := check.assertableTo(xtyp, T)
|
||||
if method == nil {
|
||||
return
|
||||
@ -1608,7 +1614,7 @@ func (check *Checker) typeAssertion(pos token.Pos, x *operand, xtyp *Interface,
|
||||
} else {
|
||||
msg = "missing method " + method.name
|
||||
}
|
||||
check.errorf(pos, _ImpossibleAssert, "%s cannot have dynamic type %s (%s)", x, T, msg)
|
||||
check.errorf(at, _ImpossibleAssert, "%s cannot have dynamic type %s (%s)", x, T, msg)
|
||||
}
|
||||
|
||||
func (check *Checker) singleValue(x *operand) {
|
||||
@ -1616,7 +1622,7 @@ func (check *Checker) singleValue(x *operand) {
|
||||
// tuple types are never named - no need for underlying type below
|
||||
if t, ok := x.typ.(*Tuple); ok {
|
||||
assert(t.Len() != 1)
|
||||
check.errorf(x.pos(), _TooManyValues, "%d-valued %s where single value is expected", t.Len(), x)
|
||||
check.errorf(x, _TooManyValues, "%d-valued %s where single value is expected", t.Len(), x)
|
||||
x.mode = invalid
|
||||
}
|
||||
}
|
||||
@ -1649,7 +1655,7 @@ func (check *Checker) multiExpr(x *operand, e ast.Expr) {
|
||||
msg = "%s is not an expression"
|
||||
code = _NotAnExpr
|
||||
}
|
||||
check.errorf(x.pos(), code, msg, x)
|
||||
check.errorf(x, code, msg, x)
|
||||
x.mode = invalid
|
||||
}
|
||||
|
||||
@ -1676,7 +1682,7 @@ func (check *Checker) exprWithHint(x *operand, e ast.Expr, hint Type) {
|
||||
msg = "%s is not an expression"
|
||||
code = _NotAnExpr
|
||||
}
|
||||
check.errorf(x.pos(), code, msg, x)
|
||||
check.errorf(x, code, msg, x)
|
||||
x.mode = invalid
|
||||
}
|
||||
|
||||
@ -1687,7 +1693,7 @@ func (check *Checker) exprOrType(x *operand, e ast.Expr) {
|
||||
check.rawExpr(x, e, nil)
|
||||
check.singleValue(x)
|
||||
if x.mode == novalue {
|
||||
check.errorf(x.pos(), _NotAnExpr, "%s used as value or type", x)
|
||||
check.errorf(x, _NotAnExpr, "%s used as value or type", x)
|
||||
x.mode = invalid
|
||||
}
|
||||
}
|
||||
|
@ -151,14 +151,14 @@ func findPath(objMap map[Object]*declInfo, from, to Object, seen map[Object]bool
|
||||
// reportCycle reports an error for the given cycle.
|
||||
func (check *Checker) reportCycle(cycle []Object) {
|
||||
obj := cycle[0]
|
||||
check.errorf(obj.Pos(), _InvalidInitCycle, "initialization cycle for %s", obj.Name())
|
||||
check.errorf(obj, _InvalidInitCycle, "initialization cycle for %s", obj.Name())
|
||||
// subtle loop: print cycle[i] for i = 0, n-1, n-2, ... 1 for len(cycle) = n
|
||||
for i := len(cycle) - 1; i >= 0; i-- {
|
||||
check.errorf(obj.Pos(), _InvalidInitCycle, "\t%s refers to", obj.Name()) // secondary error, \t indented
|
||||
check.errorf(obj, _InvalidInitCycle, "\t%s refers to", obj.Name()) // secondary error, \t indented
|
||||
obj = cycle[i]
|
||||
}
|
||||
// print cycle[0] again to close the cycle
|
||||
check.errorf(obj.Pos(), _InvalidInitCycle, "\t%s", obj.Name())
|
||||
check.errorf(obj, _InvalidInitCycle, "\t%s", obj.Name())
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
@ -32,13 +32,13 @@ func (check *Checker) labels(body *ast.BlockStmt) {
|
||||
msg = "label %s not declared"
|
||||
code = _UndeclaredLabel
|
||||
}
|
||||
check.errorf(jmp.Label.Pos(), code, msg, name)
|
||||
check.errorf(jmp.Label, code, msg, name)
|
||||
}
|
||||
|
||||
// spec: "It is illegal to define a label that is never used."
|
||||
for _, obj := range all.elems {
|
||||
if lbl := obj.(*Label); !lbl.used {
|
||||
check.softErrorf(lbl.pos, _UnusedLabel, "label %s declared but not used", lbl.name)
|
||||
check.softErrorf(lbl, _UnusedLabel, "label %s declared but not used", lbl.name)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -136,7 +136,7 @@ func (check *Checker) blockBranches(all *Scope, parent *block, lstmt *ast.Labele
|
||||
if name := s.Label.Name; name != "_" {
|
||||
lbl := NewLabel(s.Label.Pos(), check.pkg, name)
|
||||
if alt := all.Insert(lbl); alt != nil {
|
||||
check.softErrorf(lbl.pos, _DuplicateLabel, "label %s already declared", name)
|
||||
check.softErrorf(lbl, _DuplicateLabel, "label %s already declared", name)
|
||||
check.reportAltDecl(alt)
|
||||
// ok to continue
|
||||
} else {
|
||||
@ -152,7 +152,7 @@ func (check *Checker) blockBranches(all *Scope, parent *block, lstmt *ast.Labele
|
||||
check.recordUse(jmp.Label, lbl)
|
||||
if jumpsOverVarDecl(jmp) {
|
||||
check.softErrorf(
|
||||
jmp.Label.Pos(),
|
||||
jmp.Label,
|
||||
_JumpOverDecl,
|
||||
"goto %s jumps over variable declaration at line %d",
|
||||
name,
|
||||
@ -191,7 +191,7 @@ func (check *Checker) blockBranches(all *Scope, parent *block, lstmt *ast.Labele
|
||||
}
|
||||
}
|
||||
if !valid {
|
||||
check.errorf(s.Label.Pos(), _MisplacedLabel, "invalid break label %s", name)
|
||||
check.errorf(s.Label, _MisplacedLabel, "invalid break label %s", name)
|
||||
return
|
||||
}
|
||||
|
||||
@ -206,7 +206,7 @@ func (check *Checker) blockBranches(all *Scope, parent *block, lstmt *ast.Labele
|
||||
}
|
||||
}
|
||||
if !valid {
|
||||
check.errorf(s.Label.Pos(), _MisplacedLabel, "invalid continue label %s", name)
|
||||
check.errorf(s.Label, _MisplacedLabel, "invalid continue label %s", name)
|
||||
return
|
||||
}
|
||||
|
||||
@ -218,7 +218,7 @@ func (check *Checker) blockBranches(all *Scope, parent *block, lstmt *ast.Labele
|
||||
}
|
||||
|
||||
default:
|
||||
check.invalidAST(s.Pos(), "branch statement: %s %s", s.Tok, name)
|
||||
check.invalidAST(s, "branch statement: %s %s", s.Tok, name)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -59,10 +59,10 @@ type operand struct {
|
||||
id builtinId
|
||||
}
|
||||
|
||||
// pos returns the position of the expression corresponding to x.
|
||||
// Pos returns the position of the expression corresponding to x.
|
||||
// If x is invalid the position is token.NoPos.
|
||||
//
|
||||
func (x *operand) pos() token.Pos {
|
||||
func (x *operand) Pos() token.Pos {
|
||||
// x.expr may not be set if x is invalid
|
||||
if x.expr == nil {
|
||||
return token.NoPos
|
||||
|
@ -60,22 +60,22 @@ func (check *Checker) arityMatch(s, init *ast.ValueSpec) {
|
||||
case init == nil && r == 0:
|
||||
// var decl w/o init expr
|
||||
if s.Type == nil {
|
||||
check.errorf(s.Pos(), code, "missing type or init expr")
|
||||
check.errorf(s, code, "missing type or init expr")
|
||||
}
|
||||
case l < r:
|
||||
if l < len(s.Values) {
|
||||
// init exprs from s
|
||||
n := s.Values[l]
|
||||
check.errorf(n.Pos(), code, "extra init expr %s", n)
|
||||
check.errorf(n, code, "extra init expr %s", n)
|
||||
// TODO(gri) avoid declared but not used error here
|
||||
} else {
|
||||
// init exprs "inherited"
|
||||
check.errorf(s.Pos(), code, "extra init expr at %s", check.fset.Position(init.Pos()))
|
||||
check.errorf(s, code, "extra init expr at %s", check.fset.Position(init.Pos()))
|
||||
// TODO(gri) avoid declared but not used error here
|
||||
}
|
||||
case l > r && (init != nil || r != 1):
|
||||
n := s.Names[r]
|
||||
check.errorf(n.Pos(), code, "missing init expr for %s", n)
|
||||
check.errorf(n, code, "missing init expr for %s", n)
|
||||
}
|
||||
}
|
||||
|
||||
@ -104,14 +104,14 @@ func (check *Checker) declarePkgObj(ident *ast.Ident, obj Object, d *declInfo) {
|
||||
// spec: "A package-scope or file-scope identifier with name init
|
||||
// may only be declared to be a function with this (func()) signature."
|
||||
if ident.Name == "init" {
|
||||
check.errorf(ident.Pos(), _InvalidInitDecl, "cannot declare init - must be func")
|
||||
check.errorf(ident, _InvalidInitDecl, "cannot declare init - must be func")
|
||||
return
|
||||
}
|
||||
|
||||
// spec: "The main package must have package name main and declare
|
||||
// a function main that takes no arguments and returns no value."
|
||||
if ident.Name == "main" && check.pkg.name == "main" {
|
||||
check.errorf(ident.Pos(), _InvalidMainDecl, "cannot declare main - must be func")
|
||||
check.errorf(ident, _InvalidMainDecl, "cannot declare main - must be func")
|
||||
return
|
||||
}
|
||||
|
||||
@ -169,7 +169,7 @@ func (check *Checker) importPackage(pos token.Pos, path, dir string) *Package {
|
||||
imp = nil // create fake package below
|
||||
}
|
||||
if err != nil {
|
||||
check.errorf(pos, _BrokenImport, "could not import %s (%s)", path, err)
|
||||
check.errorf(atPos(pos), _BrokenImport, "could not import %s (%s)", path, err)
|
||||
if imp == nil {
|
||||
// create a new fake package
|
||||
// come up with a sensible package name (heuristic)
|
||||
@ -242,7 +242,7 @@ func (check *Checker) collectObjects() {
|
||||
// import package
|
||||
path, err := validatedImportPath(d.spec.Path.Value)
|
||||
if err != nil {
|
||||
check.errorf(d.spec.Path.Pos(), _BadImportPath, "invalid import path (%s)", err)
|
||||
check.errorf(d.spec.Path, _BadImportPath, "invalid import path (%s)", err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -265,11 +265,11 @@ func (check *Checker) collectObjects() {
|
||||
name = d.spec.Name.Name
|
||||
if path == "C" {
|
||||
// match cmd/compile (not prescribed by spec)
|
||||
check.errorf(d.spec.Name.Pos(), _ImportCRenamed, `cannot rename import "C"`)
|
||||
check.errorf(d.spec.Name, _ImportCRenamed, `cannot rename import "C"`)
|
||||
return
|
||||
}
|
||||
if name == "init" {
|
||||
check.errorf(d.spec.Name.Pos(), _InvalidInitDecl, "cannot declare init - must be func")
|
||||
check.errorf(d.spec.Name, _InvalidInitDecl, "cannot declare init - must be func")
|
||||
return
|
||||
}
|
||||
}
|
||||
@ -300,14 +300,14 @@ func (check *Checker) collectObjects() {
|
||||
// the object may be imported into more than one file scope
|
||||
// concurrently. See issue #32154.)
|
||||
if alt := fileScope.Insert(obj); alt != nil {
|
||||
check.errorf(d.spec.Name.Pos(), _DuplicateDecl, "%s redeclared in this block", obj.Name())
|
||||
check.errorf(d.spec.Name, _DuplicateDecl, "%s redeclared in this block", obj.Name())
|
||||
check.reportAltDecl(alt)
|
||||
}
|
||||
}
|
||||
}
|
||||
// add position to set of dot-import positions for this file
|
||||
// (this is only needed for "imported but not used" errors)
|
||||
check.addUnusedDotImport(fileScope, imp, d.spec.Pos())
|
||||
check.addUnusedDotImport(fileScope, imp, d.spec)
|
||||
} else {
|
||||
// declare imported package object in file scope
|
||||
// (no need to provide s.Name since we called check.recordDef earlier)
|
||||
@ -373,7 +373,7 @@ func (check *Checker) collectObjects() {
|
||||
check.recordDef(d.decl.Name, obj)
|
||||
// init functions must have a body
|
||||
if d.decl.Body == nil {
|
||||
check.softErrorf(obj.pos, _MissingInitBody, "missing function body")
|
||||
check.softErrorf(obj, _MissingInitBody, "missing function body")
|
||||
}
|
||||
} else {
|
||||
check.declare(pkg.scope, d.decl.Name, obj, token.NoPos)
|
||||
@ -403,10 +403,10 @@ func (check *Checker) collectObjects() {
|
||||
for _, obj := range scope.elems {
|
||||
if alt := pkg.scope.Lookup(obj.Name()); alt != nil {
|
||||
if pkg, ok := obj.(*PkgName); ok {
|
||||
check.errorf(alt.Pos(), _DuplicateDecl, "%s already declared through import of %s", alt.Name(), pkg.Imported())
|
||||
check.errorf(alt, _DuplicateDecl, "%s already declared through import of %s", alt.Name(), pkg.Imported())
|
||||
check.reportAltDecl(pkg)
|
||||
} else {
|
||||
check.errorf(alt.Pos(), _DuplicateDecl, "%s already declared through dot-import of %s", alt.Name(), obj.Pkg())
|
||||
check.errorf(alt, _DuplicateDecl, "%s already declared through dot-import of %s", alt.Name(), obj.Pkg())
|
||||
// TODO(gri) dot-imported objects don't have a position; reportAltDecl won't print anything
|
||||
check.reportAltDecl(obj)
|
||||
}
|
||||
@ -575,9 +575,9 @@ func (check *Checker) unusedImports() {
|
||||
path := obj.imported.path
|
||||
base := pkgName(path)
|
||||
if obj.name == base {
|
||||
check.softErrorf(obj.pos, _UnusedImport, "%q imported but not used", path)
|
||||
check.softErrorf(obj, _UnusedImport, "%q imported but not used", path)
|
||||
} else {
|
||||
check.softErrorf(obj.pos, _UnusedImport, "%q imported but not used as %s", path, obj.name)
|
||||
check.softErrorf(obj, _UnusedImport, "%q imported but not used as %s", path, obj.name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -46,7 +46,7 @@ func (check *Checker) funcBody(decl *declInfo, name string, sig *Signature, body
|
||||
}
|
||||
|
||||
if sig.results.Len() > 0 && !check.isTerminating(body, "") {
|
||||
check.error(body.Rbrace, _MissingReturn, "missing return")
|
||||
check.error(atPos(body.Rbrace), _MissingReturn, "missing return")
|
||||
}
|
||||
|
||||
// spec: "Implementation restriction: A compiler may make it illegal to
|
||||
@ -65,7 +65,7 @@ func (check *Checker) usage(scope *Scope) {
|
||||
return unused[i].pos < unused[j].pos
|
||||
})
|
||||
for _, v := range unused {
|
||||
check.softErrorf(v.pos, _UnusedVar, "%s declared but not used", v.name)
|
||||
check.softErrorf(v, _UnusedVar, "%s declared but not used", v.name)
|
||||
}
|
||||
|
||||
for _, scope := range scope.children {
|
||||
@ -135,11 +135,11 @@ func (check *Checker) multipleDefaults(list []ast.Stmt) {
|
||||
d = s
|
||||
}
|
||||
default:
|
||||
check.invalidAST(s.Pos(), "case/communication clause expected")
|
||||
check.invalidAST(s, "case/communication clause expected")
|
||||
}
|
||||
if d != nil {
|
||||
if first != nil {
|
||||
check.errorf(d.Pos(), _DuplicateDefault, "multiple defaults (first at %s)", check.fset.Position(first.Pos()))
|
||||
check.errorf(d, _DuplicateDefault, "multiple defaults (first at %s)", check.fset.Position(first.Pos()))
|
||||
} else {
|
||||
first = d
|
||||
}
|
||||
@ -184,7 +184,7 @@ func (check *Checker) suspendedCall(keyword string, call *ast.CallExpr) {
|
||||
default:
|
||||
unreachable()
|
||||
}
|
||||
check.errorf(x.pos(), code, "%s %s %s", keyword, msg, &x)
|
||||
check.errorf(&x, code, "%s %s %s", keyword, msg, &x)
|
||||
}
|
||||
|
||||
// goVal returns the Go value for val, or nil.
|
||||
@ -256,17 +256,17 @@ L:
|
||||
// (quadratic algorithm, but these lists tend to be very short)
|
||||
for _, vt := range seen[val] {
|
||||
if check.identical(v.typ, vt.typ) {
|
||||
check.errorf(v.pos(), _DuplicateCase, "duplicate case %s in expression switch", &v)
|
||||
check.error(vt.pos, _DuplicateCase, "\tprevious case") // secondary error, \t indented
|
||||
check.errorf(&v, _DuplicateCase, "duplicate case %s in expression switch", &v)
|
||||
check.error(atPos(vt.pos), _DuplicateCase, "\tprevious case") // secondary error, \t indented
|
||||
continue L
|
||||
}
|
||||
}
|
||||
seen[val] = append(seen[val], valueType{v.pos(), v.typ})
|
||||
seen[val] = append(seen[val], valueType{v.Pos(), v.typ})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (check *Checker) caseTypes(x *operand, xtyp *Interface, types []ast.Expr, seen map[Type]token.Pos) (T Type) {
|
||||
func (check *Checker) caseTypes(x *operand, xtyp *Interface, types []ast.Expr, seen map[Type]ast.Expr) (T Type) {
|
||||
L:
|
||||
for _, e := range types {
|
||||
T = check.typOrNil(e)
|
||||
@ -275,21 +275,21 @@ L:
|
||||
}
|
||||
// look for duplicate types
|
||||
// (quadratic algorithm, but type switches tend to be reasonably small)
|
||||
for t, pos := range seen {
|
||||
for t, other := range seen {
|
||||
if T == nil && t == nil || T != nil && t != nil && check.identical(T, t) {
|
||||
// talk about "case" rather than "type" because of nil case
|
||||
Ts := "nil"
|
||||
if T != nil {
|
||||
Ts = T.String()
|
||||
}
|
||||
check.errorf(e.Pos(), _DuplicateCase, "duplicate case %s in type switch", Ts)
|
||||
check.error(pos, _DuplicateCase, "\tprevious case") // secondary error, \t indented
|
||||
check.errorf(e, _DuplicateCase, "duplicate case %s in type switch", Ts)
|
||||
check.error(other, _DuplicateCase, "\tprevious case") // secondary error, \t indented
|
||||
continue L
|
||||
}
|
||||
}
|
||||
seen[T] = e.Pos()
|
||||
seen[T] = e
|
||||
if T != nil {
|
||||
check.typeAssertion(e.Pos(), x, xtyp, T)
|
||||
check.typeAssertion(e, x, xtyp, T)
|
||||
}
|
||||
}
|
||||
return
|
||||
@ -345,7 +345,7 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) {
|
||||
msg = "is not an expression"
|
||||
code = _NotAnExpr
|
||||
}
|
||||
check.errorf(x.pos(), code, "%s %s", &x, msg)
|
||||
check.errorf(&x, code, "%s %s", &x, msg)
|
||||
|
||||
case *ast.SendStmt:
|
||||
var ch, x operand
|
||||
@ -357,12 +357,12 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) {
|
||||
|
||||
tch, ok := ch.typ.Underlying().(*Chan)
|
||||
if !ok {
|
||||
check.invalidOp(s.Arrow, _InvalidSend, "cannot send to non-chan type %s", ch.typ)
|
||||
check.invalidOp(inNode(s, s.Arrow), _InvalidSend, "cannot send to non-chan type %s", ch.typ)
|
||||
return
|
||||
}
|
||||
|
||||
if tch.dir == RecvOnly {
|
||||
check.invalidOp(s.Arrow, _InvalidSend, "cannot send to receive-only type %s", tch)
|
||||
check.invalidOp(inNode(s, s.Arrow), _InvalidSend, "cannot send to receive-only type %s", tch)
|
||||
return
|
||||
}
|
||||
|
||||
@ -376,7 +376,7 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) {
|
||||
case token.DEC:
|
||||
op = token.SUB
|
||||
default:
|
||||
check.invalidAST(s.TokPos, "unknown inc/dec operation %s", s.Tok)
|
||||
check.invalidAST(inNode(s, s.TokPos), "unknown inc/dec operation %s", s.Tok)
|
||||
return
|
||||
}
|
||||
|
||||
@ -386,7 +386,7 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) {
|
||||
return
|
||||
}
|
||||
if !isNumeric(x.typ) {
|
||||
check.invalidOp(s.X.Pos(), _NonNumericIncDec, "%s%s (non-numeric type %s)", s.X, s.Tok, x.typ)
|
||||
check.invalidOp(s.X, _NonNumericIncDec, "%s%s (non-numeric type %s)", s.X, s.Tok, x.typ)
|
||||
return
|
||||
}
|
||||
|
||||
@ -401,11 +401,11 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) {
|
||||
switch s.Tok {
|
||||
case token.ASSIGN, token.DEFINE:
|
||||
if len(s.Lhs) == 0 {
|
||||
check.invalidAST(s.Pos(), "missing lhs in assignment")
|
||||
check.invalidAST(s, "missing lhs in assignment")
|
||||
return
|
||||
}
|
||||
if s.Tok == token.DEFINE {
|
||||
check.shortVarDecl(s.TokPos, s.Lhs, s.Rhs)
|
||||
check.shortVarDecl(inNode(s, s.TokPos), s.Lhs, s.Rhs)
|
||||
} else {
|
||||
// regular assignment
|
||||
check.assignVars(s.Lhs, s.Rhs)
|
||||
@ -414,12 +414,12 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) {
|
||||
default:
|
||||
// assignment operations
|
||||
if len(s.Lhs) != 1 || len(s.Rhs) != 1 {
|
||||
check.errorf(s.TokPos, _MultiValAssignOp, "assignment operation %s requires single-valued expressions", s.Tok)
|
||||
check.errorf(inNode(s, s.TokPos), _MultiValAssignOp, "assignment operation %s requires single-valued expressions", s.Tok)
|
||||
return
|
||||
}
|
||||
op := assignOp(s.Tok)
|
||||
if op == token.ILLEGAL {
|
||||
check.invalidAST(s.TokPos, "unknown assignment operation %s", s.Tok)
|
||||
check.invalidAST(atPos(s.TokPos), "unknown assignment operation %s", s.Tok)
|
||||
return
|
||||
}
|
||||
var x operand
|
||||
@ -447,8 +447,8 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) {
|
||||
// with the same name as a result parameter is in scope at the place of the return."
|
||||
for _, obj := range res.vars {
|
||||
if alt := check.lookup(obj.name); alt != nil && alt != obj {
|
||||
check.errorf(s.Pos(), _OutOfScopeResult, "result parameter %s not in scope at return", obj.name)
|
||||
check.errorf(alt.Pos(), _OutOfScopeResult, "\tinner declaration of %s", obj)
|
||||
check.errorf(s, _OutOfScopeResult, "result parameter %s not in scope at return", obj.name)
|
||||
check.errorf(alt, _OutOfScopeResult, "\tinner declaration of %s", obj)
|
||||
// ok to continue
|
||||
}
|
||||
}
|
||||
@ -457,7 +457,7 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) {
|
||||
check.initVars(res.vars, s.Results, s.Return)
|
||||
}
|
||||
} else if len(s.Results) > 0 {
|
||||
check.error(s.Results[0].Pos(), _WrongResultCount, "no result values expected")
|
||||
check.error(s.Results[0], _WrongResultCount, "no result values expected")
|
||||
check.use(s.Results...)
|
||||
}
|
||||
|
||||
@ -469,11 +469,11 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) {
|
||||
switch s.Tok {
|
||||
case token.BREAK:
|
||||
if ctxt&breakOk == 0 {
|
||||
check.error(s.Pos(), _MisplacedBreak, "break not in for, switch, or select statement")
|
||||
check.error(s, _MisplacedBreak, "break not in for, switch, or select statement")
|
||||
}
|
||||
case token.CONTINUE:
|
||||
if ctxt&continueOk == 0 {
|
||||
check.error(s.Pos(), _MisplacedContinue, "continue not in for statement")
|
||||
check.error(s, _MisplacedContinue, "continue not in for statement")
|
||||
}
|
||||
case token.FALLTHROUGH:
|
||||
if ctxt&fallthroughOk == 0 {
|
||||
@ -482,10 +482,10 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) {
|
||||
if ctxt&finalSwitchCase != 0 {
|
||||
msg = "cannot fallthrough final case in switch"
|
||||
}
|
||||
check.error(s.Pos(), code, msg)
|
||||
check.error(s, code, msg)
|
||||
}
|
||||
default:
|
||||
check.invalidAST(s.Pos(), "branch statement: %s", s.Tok)
|
||||
check.invalidAST(s, "branch statement: %s", s.Tok)
|
||||
}
|
||||
|
||||
case *ast.BlockStmt:
|
||||
@ -502,7 +502,7 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) {
|
||||
var x operand
|
||||
check.expr(&x, s.Cond)
|
||||
if x.mode != invalid && !isBoolean(x.typ) {
|
||||
check.error(s.Cond.Pos(), _InvalidCond, "non-boolean condition in if statement")
|
||||
check.error(s.Cond, _InvalidCond, "non-boolean condition in if statement")
|
||||
}
|
||||
check.stmt(inner, s.Body)
|
||||
// The parser produces a correct AST but if it was modified
|
||||
@ -513,7 +513,7 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) {
|
||||
case *ast.IfStmt, *ast.BlockStmt:
|
||||
check.stmt(inner, s.Else)
|
||||
default:
|
||||
check.invalidAST(s.Else.Pos(), "invalid else branch in if statement")
|
||||
check.invalidAST(s.Else, "invalid else branch in if statement")
|
||||
}
|
||||
|
||||
case *ast.SwitchStmt:
|
||||
@ -543,7 +543,7 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) {
|
||||
for i, c := range s.Body.List {
|
||||
clause, _ := c.(*ast.CaseClause)
|
||||
if clause == nil {
|
||||
check.invalidAST(c.Pos(), "incorrect expression switch case")
|
||||
check.invalidAST(c, "incorrect expression switch case")
|
||||
continue
|
||||
}
|
||||
check.caseValues(&x, clause.List, seen)
|
||||
@ -580,19 +580,19 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) {
|
||||
rhs = guard.X
|
||||
case *ast.AssignStmt:
|
||||
if len(guard.Lhs) != 1 || guard.Tok != token.DEFINE || len(guard.Rhs) != 1 {
|
||||
check.invalidAST(s.Pos(), "incorrect form of type switch guard")
|
||||
check.invalidAST(s, "incorrect form of type switch guard")
|
||||
return
|
||||
}
|
||||
|
||||
lhs, _ = guard.Lhs[0].(*ast.Ident)
|
||||
if lhs == nil {
|
||||
check.invalidAST(s.Pos(), "incorrect form of type switch guard")
|
||||
check.invalidAST(s, "incorrect form of type switch guard")
|
||||
return
|
||||
}
|
||||
|
||||
if lhs.Name == "_" {
|
||||
// _ := x.(type) is an invalid short variable declaration
|
||||
check.softErrorf(lhs.Pos(), _NoNewVar, "no new variable on left side of :=")
|
||||
check.softErrorf(lhs, _NoNewVar, "no new variable on left side of :=")
|
||||
lhs = nil // avoid declared but not used error below
|
||||
} else {
|
||||
check.recordDef(lhs, nil) // lhs variable is implicitly declared in each cause clause
|
||||
@ -601,14 +601,14 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) {
|
||||
rhs = guard.Rhs[0]
|
||||
|
||||
default:
|
||||
check.invalidAST(s.Pos(), "incorrect form of type switch guard")
|
||||
check.invalidAST(s, "incorrect form of type switch guard")
|
||||
return
|
||||
}
|
||||
|
||||
// rhs must be of the form: expr.(type) and expr must be an interface
|
||||
expr, _ := rhs.(*ast.TypeAssertExpr)
|
||||
if expr == nil || expr.Type != nil {
|
||||
check.invalidAST(s.Pos(), "incorrect form of type switch guard")
|
||||
check.invalidAST(s, "incorrect form of type switch guard")
|
||||
return
|
||||
}
|
||||
var x operand
|
||||
@ -618,18 +618,18 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) {
|
||||
}
|
||||
xtyp, _ := x.typ.Underlying().(*Interface)
|
||||
if xtyp == nil {
|
||||
check.errorf(x.pos(), _InvalidTypeSwitch, "%s is not an interface", &x)
|
||||
check.errorf(&x, _InvalidTypeSwitch, "%s is not an interface", &x)
|
||||
return
|
||||
}
|
||||
|
||||
check.multipleDefaults(s.Body.List)
|
||||
|
||||
var lhsVars []*Var // list of implicitly declared lhs variables
|
||||
seen := make(map[Type]token.Pos) // map of seen types to positions
|
||||
var lhsVars []*Var // list of implicitly declared lhs variables
|
||||
seen := make(map[Type]ast.Expr) // map of seen types to positions
|
||||
for _, s := range s.Body.List {
|
||||
clause, _ := s.(*ast.CaseClause)
|
||||
if clause == nil {
|
||||
check.invalidAST(s.Pos(), "incorrect type switch case")
|
||||
check.invalidAST(s, "incorrect type switch case")
|
||||
continue
|
||||
}
|
||||
// Check each type in this type switch case.
|
||||
@ -671,7 +671,7 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) {
|
||||
v.used = true // avoid usage error when checking entire function
|
||||
}
|
||||
if !used {
|
||||
check.softErrorf(lhs.Pos(), _UnusedVar, "%s declared but not used", lhs.Name)
|
||||
check.softErrorf(lhs, _UnusedVar, "%s declared but not used", lhs.Name)
|
||||
}
|
||||
}
|
||||
|
||||
@ -708,7 +708,7 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) {
|
||||
}
|
||||
|
||||
if !valid {
|
||||
check.error(clause.Comm.Pos(), _InvalidSelectCase, "select case must be send or receive (possibly with assignment)")
|
||||
check.error(clause.Comm, _InvalidSelectCase, "select case must be send or receive (possibly with assignment)")
|
||||
continue
|
||||
}
|
||||
|
||||
@ -730,14 +730,14 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) {
|
||||
var x operand
|
||||
check.expr(&x, s.Cond)
|
||||
if x.mode != invalid && !isBoolean(x.typ) {
|
||||
check.error(s.Cond.Pos(), _InvalidCond, "non-boolean condition in for statement")
|
||||
check.error(s.Cond, _InvalidCond, "non-boolean condition in for statement")
|
||||
}
|
||||
}
|
||||
check.simpleStmt(s.Post)
|
||||
// spec: "The init statement may be a short variable
|
||||
// declaration, but the post statement must not."
|
||||
if s, _ := s.Post.(*ast.AssignStmt); s != nil && s.Tok == token.DEFINE {
|
||||
check.softErrorf(s.Pos(), _InvalidPostDecl, "cannot declare in post statement")
|
||||
check.softErrorf(s, _InvalidPostDecl, "cannot declare in post statement")
|
||||
// Don't call useLHS here because we want to use the lhs in
|
||||
// this erroneous statement so that we don't get errors about
|
||||
// these lhs variables being declared but not used.
|
||||
@ -781,18 +781,18 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) {
|
||||
key = typ.elem
|
||||
val = Typ[Invalid]
|
||||
if typ.dir == SendOnly {
|
||||
check.errorf(x.pos(), _InvalidChanRange, "cannot range over send-only channel %s", &x)
|
||||
check.errorf(&x, _InvalidChanRange, "cannot range over send-only channel %s", &x)
|
||||
// ok to continue
|
||||
}
|
||||
if s.Value != nil {
|
||||
check.errorf(s.Value.Pos(), _InvalidIterVar, "iteration over %s permits only one iteration variable", &x)
|
||||
check.errorf(atPos(s.Value.Pos()), _InvalidIterVar, "iteration over %s permits only one iteration variable", &x)
|
||||
// ok to continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if key == nil {
|
||||
check.errorf(x.pos(), _InvalidRangeExpr, "cannot range over %s", &x)
|
||||
check.errorf(&x, _InvalidRangeExpr, "cannot range over %s", &x)
|
||||
// ok to continue
|
||||
}
|
||||
|
||||
@ -825,7 +825,7 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) {
|
||||
vars = append(vars, obj)
|
||||
}
|
||||
} else {
|
||||
check.invalidAST(lhs.Pos(), "cannot declare %s", lhs)
|
||||
check.invalidAST(lhs, "cannot declare %s", lhs)
|
||||
obj = NewVar(lhs.Pos(), check.pkg, "_", nil) // dummy variable
|
||||
}
|
||||
|
||||
@ -852,7 +852,7 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) {
|
||||
check.declare(check.scope, nil /* recordDef already called */, obj, scopePos)
|
||||
}
|
||||
} else {
|
||||
check.error(s.TokPos, _NoNewVar, "no new variables on left side of :=")
|
||||
check.error(inNode(s, s.TokPos), _NoNewVar, "no new variables on left side of :=")
|
||||
}
|
||||
} else {
|
||||
// ordinary assignment
|
||||
@ -872,6 +872,6 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) {
|
||||
check.stmt(inner, s.Body)
|
||||
|
||||
default:
|
||||
check.invalidAST(s.Pos(), "invalid statement")
|
||||
check.invalidAST(s, "invalid statement")
|
||||
}
|
||||
}
|
||||
|
@ -28,9 +28,9 @@ func (check *Checker) ident(x *operand, e *ast.Ident, def *Named, wantType bool)
|
||||
scope, obj := check.scope.LookupParent(e.Name, check.pos)
|
||||
if obj == nil {
|
||||
if e.Name == "_" {
|
||||
check.errorf(e.Pos(), _InvalidBlank, "cannot use _ as value or type")
|
||||
check.errorf(e, _InvalidBlank, "cannot use _ as value or type")
|
||||
} else {
|
||||
check.errorf(e.Pos(), _UndeclaredName, "undeclared name: %s", e.Name)
|
||||
check.errorf(e, _UndeclaredName, "undeclared name: %s", e.Name)
|
||||
}
|
||||
return
|
||||
}
|
||||
@ -61,7 +61,7 @@ func (check *Checker) ident(x *operand, e *ast.Ident, def *Named, wantType bool)
|
||||
|
||||
switch obj := obj.(type) {
|
||||
case *PkgName:
|
||||
check.errorf(e.Pos(), _InvalidPkgUse, "use of package %s not in selector", obj.name)
|
||||
check.errorf(e, _InvalidPkgUse, "use of package %s not in selector", obj.name)
|
||||
return
|
||||
|
||||
case *Const:
|
||||
@ -71,7 +71,7 @@ func (check *Checker) ident(x *operand, e *ast.Ident, def *Named, wantType bool)
|
||||
}
|
||||
if obj == universeIota {
|
||||
if check.iota == nil {
|
||||
check.errorf(e.Pos(), _InvalidIota, "cannot use iota outside constant declaration")
|
||||
check.errorf(e, _InvalidIota, "cannot use iota outside constant declaration")
|
||||
return
|
||||
}
|
||||
x.val = check.iota
|
||||
@ -159,11 +159,11 @@ func (check *Checker) funcType(sig *Signature, recvPar *ast.FieldList, ftyp *ast
|
||||
var recv *Var
|
||||
switch len(recvList) {
|
||||
case 0:
|
||||
check.error(recvPar.Pos(), _BadRecv, "method is missing receiver")
|
||||
check.error(recvPar, _BadRecv, "method is missing receiver")
|
||||
recv = NewParam(0, nil, "", Typ[Invalid]) // ignore recv below
|
||||
default:
|
||||
// more than one receiver
|
||||
check.error(recvList[len(recvList)-1].Pos(), _BadRecv, "method must have exactly one receiver")
|
||||
check.error(recvList[len(recvList)-1], _BadRecv, "method must have exactly one receiver")
|
||||
fallthrough // continue with first receiver
|
||||
case 1:
|
||||
recv = recvList[0]
|
||||
@ -194,7 +194,7 @@ func (check *Checker) funcType(sig *Signature, recvPar *ast.FieldList, ftyp *ast
|
||||
err = "basic or unnamed type"
|
||||
}
|
||||
if err != "" {
|
||||
check.errorf(recv.pos, _InvalidRecv, "invalid receiver %s (%s)", recv.typ, err)
|
||||
check.errorf(recv, _InvalidRecv, "invalid receiver %s (%s)", recv.typ, err)
|
||||
// ok to continue
|
||||
}
|
||||
}
|
||||
@ -227,9 +227,9 @@ func (check *Checker) typInternal(e ast.Expr, def *Named) Type {
|
||||
case invalid:
|
||||
// ignore - error reported before
|
||||
case novalue:
|
||||
check.errorf(x.pos(), _NotAType, "%s used as type", &x)
|
||||
check.errorf(&x, _NotAType, "%s used as type", &x)
|
||||
default:
|
||||
check.errorf(x.pos(), _NotAType, "%s is not a type", &x)
|
||||
check.errorf(&x, _NotAType, "%s is not a type", &x)
|
||||
}
|
||||
|
||||
case *ast.SelectorExpr:
|
||||
@ -244,9 +244,9 @@ func (check *Checker) typInternal(e ast.Expr, def *Named) Type {
|
||||
case invalid:
|
||||
// ignore - error reported before
|
||||
case novalue:
|
||||
check.errorf(x.pos(), _NotAType, "%s used as type", &x)
|
||||
check.errorf(&x, _NotAType, "%s used as type", &x)
|
||||
default:
|
||||
check.errorf(x.pos(), _NotAType, "%s is not a type", &x)
|
||||
check.errorf(&x, _NotAType, "%s is not a type", &x)
|
||||
}
|
||||
|
||||
case *ast.ParenExpr:
|
||||
@ -306,7 +306,7 @@ func (check *Checker) typInternal(e ast.Expr, def *Named) Type {
|
||||
// it is safe to continue in any case (was issue 6667).
|
||||
check.atEnd(func() {
|
||||
if !Comparable(typ.key) {
|
||||
check.errorf(e.Key.Pos(), _IncomparableMapKey, "incomparable map key type %s", typ.key)
|
||||
check.errorf(e.Key, _IncomparableMapKey, "incomparable map key type %s", typ.key)
|
||||
}
|
||||
})
|
||||
|
||||
@ -325,7 +325,7 @@ func (check *Checker) typInternal(e ast.Expr, def *Named) Type {
|
||||
case ast.RECV:
|
||||
dir = RecvOnly
|
||||
default:
|
||||
check.invalidAST(e.Pos(), "unknown channel direction %d", e.Dir)
|
||||
check.invalidAST(e, "unknown channel direction %d", e.Dir)
|
||||
// ok to continue
|
||||
}
|
||||
|
||||
@ -334,7 +334,7 @@ func (check *Checker) typInternal(e ast.Expr, def *Named) Type {
|
||||
return typ
|
||||
|
||||
default:
|
||||
check.errorf(e.Pos(), _NotAType, "%s is not a type", e)
|
||||
check.errorf(e, _NotAType, "%s is not a type", e)
|
||||
}
|
||||
|
||||
typ := Typ[Invalid]
|
||||
@ -353,7 +353,7 @@ func (check *Checker) typOrNil(e ast.Expr) Type {
|
||||
case invalid:
|
||||
// ignore - error reported before
|
||||
case novalue:
|
||||
check.errorf(x.pos(), _NotAType, "%s used as type", &x)
|
||||
check.errorf(&x, _NotAType, "%s used as type", &x)
|
||||
case typexpr:
|
||||
return x.typ
|
||||
case value:
|
||||
@ -362,7 +362,7 @@ func (check *Checker) typOrNil(e ast.Expr) Type {
|
||||
}
|
||||
fallthrough
|
||||
default:
|
||||
check.errorf(x.pos(), _NotAType, "%s is not a type", &x)
|
||||
check.errorf(&x, _NotAType, "%s is not a type", &x)
|
||||
}
|
||||
return Typ[Invalid]
|
||||
}
|
||||
@ -375,7 +375,7 @@ func (check *Checker) arrayLength(e ast.Expr) int64 {
|
||||
check.expr(&x, e)
|
||||
if x.mode != constant_ {
|
||||
if x.mode != invalid {
|
||||
check.errorf(x.pos(), _InvalidArrayLen, "array length %s must be constant", &x)
|
||||
check.errorf(&x, _InvalidArrayLen, "array length %s must be constant", &x)
|
||||
}
|
||||
return -1
|
||||
}
|
||||
@ -385,12 +385,12 @@ func (check *Checker) arrayLength(e ast.Expr) int64 {
|
||||
if n, ok := constant.Int64Val(val); ok && n >= 0 {
|
||||
return n
|
||||
}
|
||||
check.errorf(x.pos(), _InvalidArrayLen, "invalid array length %s", &x)
|
||||
check.errorf(&x, _InvalidArrayLen, "invalid array length %s", &x)
|
||||
return -1
|
||||
}
|
||||
}
|
||||
}
|
||||
check.errorf(x.pos(), _InvalidArrayLen, "array length %s must be integer", &x)
|
||||
check.errorf(&x, _InvalidArrayLen, "array length %s must be integer", &x)
|
||||
return -1
|
||||
}
|
||||
|
||||
@ -407,7 +407,7 @@ func (check *Checker) collectParams(scope *Scope, list *ast.FieldList, variadicO
|
||||
if variadicOk && i == len(list.List)-1 && len(field.Names) <= 1 {
|
||||
variadic = true
|
||||
} else {
|
||||
check.softErrorf(t.Pos(), _MisplacedDotDotDot, "can only use ... with final parameter in list")
|
||||
check.softErrorf(t, _MisplacedDotDotDot, "can only use ... with final parameter in list")
|
||||
// ignore ... and continue
|
||||
}
|
||||
}
|
||||
@ -418,7 +418,7 @@ func (check *Checker) collectParams(scope *Scope, list *ast.FieldList, variadicO
|
||||
// named parameter
|
||||
for _, name := range field.Names {
|
||||
if name.Name == "" {
|
||||
check.invalidAST(name.Pos(), "anonymous parameter")
|
||||
check.invalidAST(name, "anonymous parameter")
|
||||
// ok to continue
|
||||
}
|
||||
par := NewParam(name.Pos(), check.pkg, name.Name, typ)
|
||||
@ -436,7 +436,7 @@ func (check *Checker) collectParams(scope *Scope, list *ast.FieldList, variadicO
|
||||
}
|
||||
|
||||
if named && anonymous {
|
||||
check.invalidAST(list.Pos(), "list contains both named and anonymous parameters")
|
||||
check.invalidAST(list, "list contains both named and anonymous parameters")
|
||||
// ok to continue
|
||||
}
|
||||
|
||||
@ -454,7 +454,7 @@ func (check *Checker) collectParams(scope *Scope, list *ast.FieldList, variadicO
|
||||
|
||||
func (check *Checker) declareInSet(oset *objset, pos token.Pos, obj Object) bool {
|
||||
if alt := oset.insert(obj); alt != nil {
|
||||
check.errorf(pos, _DuplicateDecl, "%s redeclared", obj.Name())
|
||||
check.errorf(atPos(pos), _DuplicateDecl, "%s redeclared", obj.Name())
|
||||
check.reportAltDecl(alt)
|
||||
return false
|
||||
}
|
||||
@ -469,7 +469,7 @@ func (check *Checker) interfaceType(ityp *Interface, iface *ast.InterfaceType, d
|
||||
// and we don't care if a constructed AST has more.)
|
||||
name := f.Names[0]
|
||||
if name.Name == "_" {
|
||||
check.errorf(name.Pos(), _BlankIfaceMethod, "invalid method name _")
|
||||
check.errorf(name, _BlankIfaceMethod, "invalid method name _")
|
||||
continue // ignore
|
||||
}
|
||||
|
||||
@ -477,7 +477,7 @@ func (check *Checker) interfaceType(ityp *Interface, iface *ast.InterfaceType, d
|
||||
sig, _ := typ.(*Signature)
|
||||
if sig == nil {
|
||||
if typ != Typ[Invalid] {
|
||||
check.invalidAST(f.Type.Pos(), "%s is not a method signature", typ)
|
||||
check.invalidAST(f.Type, "%s is not a method signature", typ)
|
||||
}
|
||||
continue // ignore
|
||||
}
|
||||
@ -501,7 +501,7 @@ func (check *Checker) interfaceType(ityp *Interface, iface *ast.InterfaceType, d
|
||||
utyp := check.underlying(typ)
|
||||
if _, ok := utyp.(*Interface); !ok {
|
||||
if utyp != Typ[Invalid] {
|
||||
check.errorf(f.Type.Pos(), _InvalidIfaceEmbed, "%s is not an interface", typ)
|
||||
check.errorf(f.Type, _InvalidIfaceEmbed, "%s is not an interface", typ)
|
||||
}
|
||||
continue
|
||||
}
|
||||
@ -575,14 +575,14 @@ func (check *Checker) completeInterface(ityp *Interface) {
|
||||
methods = append(methods, m)
|
||||
mpos[m] = pos
|
||||
case explicit:
|
||||
check.errorf(pos, _DuplicateDecl, "duplicate method %s", m.name)
|
||||
check.errorf(mpos[other.(*Func)], _DuplicateDecl, "\tother declaration of %s", m.name) // secondary error, \t indented
|
||||
check.errorf(atPos(pos), _DuplicateDecl, "duplicate method %s", m.name)
|
||||
check.errorf(atPos(mpos[other.(*Func)]), _DuplicateDecl, "\tother declaration of %s", m.name) // secondary error, \t indented
|
||||
default:
|
||||
// check method signatures after all types are computed (issue #33656)
|
||||
check.atEnd(func() {
|
||||
if !check.identical(m.typ, other.Type()) {
|
||||
check.errorf(pos, _DuplicateDecl, "duplicate method %s", m.name)
|
||||
check.errorf(mpos[other.(*Func)], _DuplicateDecl, "\tother declaration of %s", m.name) // secondary error, \t indented
|
||||
check.errorf(atPos(pos), _DuplicateDecl, "duplicate method %s", m.name)
|
||||
check.errorf(atPos(mpos[other.(*Func)]), _DuplicateDecl, "\tother declaration of %s", m.name) // secondary error, \t indented
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -641,7 +641,7 @@ func (check *Checker) tag(t *ast.BasicLit) string {
|
||||
return val
|
||||
}
|
||||
}
|
||||
check.invalidAST(t.Pos(), "incorrect tag syntax: %q", t.Value)
|
||||
check.invalidAST(t, "incorrect tag syntax: %q", t.Value)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
@ -704,7 +704,7 @@ func (check *Checker) structType(styp *Struct, e *ast.StructType) {
|
||||
pos := f.Type.Pos()
|
||||
name := embeddedFieldIdent(f.Type)
|
||||
if name == nil {
|
||||
check.invalidAST(pos, "embedded field type %s has no name", f.Type)
|
||||
check.invalidAST(f.Type, "embedded field type %s has no name", f.Type)
|
||||
name = ast.NewIdent("_")
|
||||
name.NamePos = pos
|
||||
addInvalid(name, pos)
|
||||
@ -723,19 +723,19 @@ func (check *Checker) structType(styp *Struct, e *ast.StructType) {
|
||||
|
||||
// unsafe.Pointer is treated like a regular pointer
|
||||
if t.kind == UnsafePointer {
|
||||
check.errorf(pos, _InvalidPtrEmbed, "embedded field type cannot be unsafe.Pointer")
|
||||
check.errorf(f.Type, _InvalidPtrEmbed, "embedded field type cannot be unsafe.Pointer")
|
||||
addInvalid(name, pos)
|
||||
continue
|
||||
}
|
||||
|
||||
case *Pointer:
|
||||
check.errorf(pos, _InvalidPtrEmbed, "embedded field type cannot be a pointer")
|
||||
check.errorf(f.Type, _InvalidPtrEmbed, "embedded field type cannot be a pointer")
|
||||
addInvalid(name, pos)
|
||||
continue
|
||||
|
||||
case *Interface:
|
||||
if isPtr {
|
||||
check.errorf(pos, _InvalidPtrEmbed, "embedded field type cannot be a pointer to an interface")
|
||||
check.errorf(f.Type, _InvalidPtrEmbed, "embedded field type cannot be a pointer to an interface")
|
||||
addInvalid(name, pos)
|
||||
continue
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user