// 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:
// 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
}
code = ierr.go116code
}
}
- check.error(x.pos(), code, msg)
+ check.error(x, code, msg)
x.mode = invalid
return
}
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
}
// 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]
}
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
}
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
}
}
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
}
}
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
}
}
}
-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
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 {
}
} 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
// 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
}
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
}
}
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
}
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
}
// 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
}
// 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
}
}
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
}
// 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
}
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
}
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
}
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}
}
}
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
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
}
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
}
// 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
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
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 {
}
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
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
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
}
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
}
}
}
}
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 {
}
}
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)
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
}
}
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.
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
}
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
}
// 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
// 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
if name != "_" {
pkg.name = name
} else {
- check.errorf(file.Name.Pos(), _BlankPkgName, "invalid package name _")
+ check.errorf(file.Name, _BlankPkgName, "invalid package name _")
}
fallthrough
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
}
}
}
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
}
// 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
}
}
// 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
}
// 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"
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)
}
}
// 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
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()
}
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
}
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())
}
})
}
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})
+func (check *Checker) newError(at positioner, code errorCode, soft bool, msg string) error {
+ ext := spanOf(at)
+ return Error{
+ Fset: check.fset,
+ Pos: ext.pos,
+ Msg: msg,
+ Soft: soft,
+ go116code: code,
+ go116start: ext.start,
+ go116end: ext.end,
+ }
}
// newErrorf creates a new Error, but does not handle it.
-func (check *Checker) newErrorf(pos token.Pos, code errorCode, format string, args ...interface{}) error {
- return Error{
- Fset: check.fset,
- Pos: pos,
- Msg: check.sprintf(format, args...),
- Soft: false,
- go116code: code,
- }
+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) error(at positioner, code errorCode, msg string) {
+ check.err(check.newError(at, code, false, msg))
+}
+
+func (check *Checker) errorf(at positioner, code errorCode, format string, args ...interface{}) {
+ check.error(at, code, check.sprintf(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) 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) errorf(pos token.Pos, code errorCode, format string, args ...interface{}) {
- check.error(pos, code, check.sprintf(format, args...))
+func (check *Checker) invalidOp(at positioner, code errorCode, format string, args ...interface{}) {
+ check.errorf(at, code, "invalid operation: "+format, args...)
}
-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,
- })
+// The positioner interface is used to extract the position of type-checker
+// errors.
+type positioner interface {
+ Pos() token.Pos
}
-func (check *Checker) invalidAST(pos token.Pos, format string, args ...interface{}) {
- check.errorf(pos, 0, "invalid AST: "+format, args...)
+// 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 (check *Checker) invalidArg(pos token.Pos, code errorCode, format string, args ...interface{}) {
- check.errorf(pos, code, "invalid argument: "+format, args...)
+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}
}
-func (check *Checker) invalidOp(pos token.Pos, code errorCode, format string, args ...interface{}) {
- check.errorf(pos, code, "invalid operation: "+format, args...)
+// 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}
+ }
}
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
// 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
}
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
}
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
}
// 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
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
}
} 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
}
}
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
}
// 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
}
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
}
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
}
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
}
// 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
}
// 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
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
}
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
}
// 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
}
// 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
}
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
}
// 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
}
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
}
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
}
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
}
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)
// 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]
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
// 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
}
}
// 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)
// 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)
// 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)
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
}
}
}
// 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
}
}
}
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
}
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
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}
}
if !valid {
- check.invalidOp(x.pos(), _NonSliceableOperand, "cannot slice %s", x)
+ check.invalidOp(x, _NonSliceableOperand, "cannot slice %s", x)
goto Error
}
// 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
}
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
}
}
}
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
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
}
}
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,
}
// 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
} 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) {
// 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
}
}
msg = "%s is not an expression"
code = _NotAnExpr
}
- check.errorf(x.pos(), code, msg, x)
+ check.errorf(x, code, msg, x)
x.mode = invalid
}
msg = "%s is not an expression"
code = _NotAnExpr
}
- check.errorf(x.pos(), code, msg, x)
+ check.errorf(x, code, msg, x)
x.mode = invalid
}
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
}
}
// 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())
}
// ----------------------------------------------------------------------------
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)
}
}
}
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 {
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,
}
}
if !valid {
- check.errorf(s.Label.Pos(), _MisplacedLabel, "invalid break label %s", name)
+ check.errorf(s.Label, _MisplacedLabel, "invalid break label %s", name)
return
}
}
}
if !valid {
- check.errorf(s.Label.Pos(), _MisplacedLabel, "invalid continue label %s", name)
+ check.errorf(s.Label, _MisplacedLabel, "invalid continue label %s", name)
return
}
}
default:
- check.invalidAST(s.Pos(), "branch statement: %s %s", s.Tok, name)
+ check.invalidAST(s, "branch statement: %s %s", s.Tok, name)
return
}
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
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)
}
}
// 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
}
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)
// 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
}
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
}
}
// 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)
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)
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)
}
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)
}
}
}
}
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
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 {
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
}
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.
// (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)
}
// 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
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
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
}
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
}
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
}
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)
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
// 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
}
}
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...)
}
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 {
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:
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
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:
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)
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
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
}
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.
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)
}
}
}
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
}
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.
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
}
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
}
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
check.stmt(inner, s.Body)
default:
- check.invalidAST(s.Pos(), "invalid statement")
+ check.invalidAST(s, "invalid statement")
}
}
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
}
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:
}
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
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]
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
}
}
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:
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:
// 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)
}
})
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
}
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]
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:
}
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]
}
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
}
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
}
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
}
}
// 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)
}
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
}
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
}
// 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
}
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
}
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
}
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
}
})
}
return val
}
}
- check.invalidAST(t.Pos(), "incorrect tag syntax: %q", t.Value)
+ check.invalidAST(t, "incorrect tag syntax: %q", t.Value)
}
return ""
}
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)
// 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
}