diff --git a/src/go/types/api.go b/src/go/types/api.go index abe1f9f862..d625959817 100644 --- a/src/go/types/api.go +++ b/src/go/types/api.go @@ -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: diff --git a/src/go/types/assignments.go b/src/go/types/assignments.go index d895c6f099..616564b567 100644 --- a/src/go/types/assignments.go +++ b/src/go/types/assignments.go @@ -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 diff --git a/src/go/types/builtins.go b/src/go/types/builtins.go index 960d1f28bc..fd35f78676 100644 --- a/src/go/types/builtins.go +++ b/src/go/types/builtins.go @@ -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 diff --git a/src/go/types/call.go b/src/go/types/call.go index fd0cfe3b28..992598d08c 100644 --- a/src/go/types/call.go +++ b/src/go/types/call.go @@ -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 } diff --git a/src/go/types/check.go b/src/go/types/check.go index 407faa034f..5e7bd92076 100644 --- a/src/go/types/check.go +++ b/src/go/types/check.go @@ -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 } } diff --git a/src/go/types/conversions.go b/src/go/types/conversions.go index 4f47140aa2..0955391d7b 100644 --- a/src/go/types/conversions.go +++ b/src/go/types/conversions.go @@ -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 } diff --git a/src/go/types/decl.go b/src/go/types/decl.go index 416878d20d..17b66ca387 100644 --- a/src/go/types/decl.go +++ b/src/go/types/decl.go @@ -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()) } }) } diff --git a/src/go/types/errors.go b/src/go/types/errors.go index b721cb1279..c9c475e469 100644 --- a/src/go/types/errors.go +++ b/src/go/types/errors.go @@ -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} + } } diff --git a/src/go/types/expr.go b/src/go/types/expr.go index 5f3415a59d..1f8b946407 100644 --- a/src/go/types/expr.go +++ b/src/go/types/expr.go @@ -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 } } diff --git a/src/go/types/initorder.go b/src/go/types/initorder.go index f770d8b830..77a739c7c1 100644 --- a/src/go/types/initorder.go +++ b/src/go/types/initorder.go @@ -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()) } // ---------------------------------------------------------------------------- diff --git a/src/go/types/labels.go b/src/go/types/labels.go index 5a577c45d4..8cf6e63645 100644 --- a/src/go/types/labels.go +++ b/src/go/types/labels.go @@ -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 } diff --git a/src/go/types/operand.go b/src/go/types/operand.go index 73b3be2655..2d30dbd024 100644 --- a/src/go/types/operand.go +++ b/src/go/types/operand.go @@ -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 diff --git a/src/go/types/resolver.go b/src/go/types/resolver.go index 05d24ef22d..4092d55b4e 100644 --- a/src/go/types/resolver.go +++ b/src/go/types/resolver.go @@ -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) } } } diff --git a/src/go/types/stmt.go b/src/go/types/stmt.go index cc98b07728..b1ccbf0c65 100644 --- a/src/go/types/stmt.go +++ b/src/go/types/stmt.go @@ -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") } } diff --git a/src/go/types/typexpr.go b/src/go/types/typexpr.go index b03870477d..2b398010f4 100644 --- a/src/go/types/typexpr.go +++ b/src/go/types/typexpr.go @@ -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 }