cmd/compile/internal/types2: simplify error reporting API (cleanup)

- Remove specialized errorf functions for invalid AST/argument/operation.
  Instead use prefix constants with the error message.

- Replace several calls to Checker.errorf with calls to Checker.error
  if there are no arguments to format.

- Replace a handful of %s format verbs with %v to satisfy vet check.

- Add a basic test that checks that we're not using Checker.errorf when
  we should be using Checker.error.

Change-Id: I7bc7c14f3cf774689ec8cd5782ea31b6e30dbcd6
Reviewed-on: https://go-review.googlesource.com/c/go/+/300995
Trust: Robert Griesemer <gri@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
This commit is contained in:
Robert Griesemer 2021-03-11 16:34:01 -08:00
parent 7b47f9a5f2
commit 16ad1ea841
13 changed files with 162 additions and 117 deletions

View file

@ -194,7 +194,7 @@ func (check *Checker) assignVar(lhs syntax.Expr, x *operand) Type {
case variable, mapindex: case variable, mapindex:
// ok // ok
case nilvalue: case nilvalue:
check.errorf(&z, "cannot assign to nil") // default would print "untyped nil" check.error(&z, "cannot assign to nil") // default would print "untyped nil"
return nil return nil
default: default:
if sel, ok := z.expr.(*syntax.SelectorExpr); ok { if sel, ok := z.expr.(*syntax.SelectorExpr); ok {

View file

@ -21,8 +21,8 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) (
// append is the only built-in that permits the use of ... for the last argument // append is the only built-in that permits the use of ... for the last argument
bin := predeclaredFuncs[id] bin := predeclaredFuncs[id]
if call.HasDots && id != _Append { if call.HasDots && id != _Append {
//check.invalidOpf(call.Ellipsis, "invalid use of ... with built-in %s", bin.name) //check.errorf(call.Ellipsis, invalidOp + "invalid use of ... with built-in %s", bin.name)
check.invalidOpf(call, "invalid use of ... with built-in %s", bin.name) check.errorf(call, invalidOp+"invalid use of ... with built-in %s", bin.name)
check.use(call.ArgList...) check.use(call.ArgList...)
return return
} }
@ -68,7 +68,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) (
msg = "too many" msg = "too many"
} }
if msg != "" { if msg != "" {
check.invalidOpf(call, "%s arguments for %s (expected %d, found %d)", msg, call, bin.nargs, nargs) check.errorf(call, invalidOp+"%s arguments for %v (expected %d, found %d)", msg, call, bin.nargs, nargs)
return return
} }
} }
@ -85,7 +85,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) (
if s := asSlice(S); s != nil { if s := asSlice(S); s != nil {
T = s.elem T = s.elem
} else { } else {
check.invalidArgf(x, "%s is not a slice", x) check.errorf(x, invalidArg+"%s is not a slice", x)
return return
} }
@ -197,7 +197,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) (
} }
if mode == invalid && typ != Typ[Invalid] { if mode == invalid && typ != Typ[Invalid] {
check.invalidArgf(x, "%s for %s", x, bin.name) check.errorf(x, invalidArg+"%s for %s", x, bin.name)
return return
} }
@ -212,11 +212,11 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) (
// close(c) // close(c)
c := asChan(x.typ) c := asChan(x.typ)
if c == nil { if c == nil {
check.invalidArgf(x, "%s is not a channel", x) check.errorf(x, invalidArg+"%s is not a channel", x)
return return
} }
if c.dir == RecvOnly { if c.dir == RecvOnly {
check.invalidArgf(x, "%s must not be a receive-only channel", x) check.errorf(x, invalidArg+"%s must not be a receive-only channel", x)
return return
} }
@ -280,7 +280,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) (
// both argument types must be identical // both argument types must be identical
if !check.identical(x.typ, y.typ) { if !check.identical(x.typ, y.typ) {
check.invalidOpf(x, "%s (mismatched types %s and %s)", call, x.typ, y.typ) check.errorf(x, invalidOp+"%v (mismatched types %s and %s)", call, x.typ, y.typ)
return return
} }
@ -300,7 +300,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) (
} }
resTyp := check.applyTypeFunc(f, x.typ) resTyp := check.applyTypeFunc(f, x.typ)
if resTyp == nil { if resTyp == nil {
check.invalidArgf(x, "arguments have type %s, expected floating-point", x.typ) check.errorf(x, invalidArg+"arguments have type %s, expected floating-point", x.typ)
return return
} }
@ -340,12 +340,12 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) (
} }
if dst == nil || src == nil { if dst == nil || src == nil {
check.invalidArgf(x, "copy expects slice arguments; found %s and %s", x, &y) check.errorf(x, invalidArg+"copy expects slice arguments; found %s and %s", x, &y)
return return
} }
if !check.identical(dst, src) { if !check.identical(dst, src) {
check.invalidArgf(x, "arguments to copy %s and %s have different element types %s and %s", x, &y, dst, src) check.errorf(x, invalidArg+"arguments to copy %s and %s have different element types %s and %s", x, &y, dst, src)
return return
} }
@ -359,7 +359,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) (
// delete(m, k) // delete(m, k)
m := asMap(x.typ) m := asMap(x.typ)
if m == nil { if m == nil {
check.invalidArgf(x, "%s is not a map", x) check.errorf(x, invalidArg+"%s is not a map", x)
return return
} }
arg(x, 1) // k arg(x, 1) // k
@ -418,7 +418,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) (
} }
resTyp := check.applyTypeFunc(f, x.typ) resTyp := check.applyTypeFunc(f, x.typ)
if resTyp == nil { if resTyp == nil {
check.invalidArgf(x, "argument has type %s, expected complex type", x.typ) check.errorf(x, invalidArg+"argument has type %s, expected complex type", x.typ)
return return
} }
@ -473,7 +473,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) (
} }
if !valid(T) { if !valid(T) {
check.invalidArgf(arg0, "cannot make %s; type must be slice, map, or channel", arg0) check.errorf(arg0, invalidArg+"cannot make %s; type must be slice, map, or channel", arg0)
return return
} }
if nargs < min || max < nargs { if nargs < min || max < nargs {
@ -495,7 +495,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) (
} }
} }
if len(sizes) == 2 && sizes[0] > sizes[1] { if len(sizes) == 2 && sizes[0] > sizes[1] {
check.invalidArgf(call.ArgList[1], "length and capacity swapped") check.error(call.ArgList[1], invalidArg+"length and capacity swapped")
// safe to continue // safe to continue
} }
x.mode = value x.mode = value
@ -578,7 +578,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) (
case _Alignof: case _Alignof:
// unsafe.Alignof(x T) uintptr // unsafe.Alignof(x T) uintptr
if asTypeParam(x.typ) != nil { if asTypeParam(x.typ) != nil {
check.invalidOpf(call, "unsafe.Alignof undefined for %s", x) check.errorf(call, invalidOp+"unsafe.Alignof undefined for %s", x)
return return
} }
check.assignment(x, nil, "argument to unsafe.Alignof") check.assignment(x, nil, "argument to unsafe.Alignof")
@ -597,7 +597,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) (
arg0 := call.ArgList[0] arg0 := call.ArgList[0]
selx, _ := unparen(arg0).(*syntax.SelectorExpr) selx, _ := unparen(arg0).(*syntax.SelectorExpr)
if selx == nil { if selx == nil {
check.invalidArgf(arg0, "%s is not a selector expression", arg0) check.errorf(arg0, invalidArg+"%s is not a selector expression", arg0)
check.use(arg0) check.use(arg0)
return return
} }
@ -612,18 +612,18 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) (
obj, index, indirect := check.lookupFieldOrMethod(base, false, check.pkg, sel) obj, index, indirect := check.lookupFieldOrMethod(base, false, check.pkg, sel)
switch obj.(type) { switch obj.(type) {
case nil: case nil:
check.invalidArgf(x, "%s has no single field %s", base, sel) check.errorf(x, invalidArg+"%s has no single field %s", base, sel)
return return
case *Func: case *Func:
// TODO(gri) Using derefStructPtr may result in methods being found // TODO(gri) Using derefStructPtr may result in methods being found
// that don't actually exist. An error either way, but the error // that don't actually exist. An error either way, but the error
// message is confusing. See: https://play.golang.org/p/al75v23kUy , // message is confusing. See: https://play.golang.org/p/al75v23kUy ,
// but go/types reports: "invalid argument: x.m is a method value". // but go/types reports: "invalid argument: x.m is a method value".
check.invalidArgf(arg0, "%s is a method value", arg0) check.errorf(arg0, invalidArg+"%s is a method value", arg0)
return return
} }
if indirect { if indirect {
check.invalidArgf(x, "field %s is embedded via a pointer in %s", sel, base) check.errorf(x, invalidArg+"field %s is embedded via a pointer in %s", sel, base)
return return
} }
@ -639,7 +639,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) (
case _Sizeof: case _Sizeof:
// unsafe.Sizeof(x T) uintptr // unsafe.Sizeof(x T) uintptr
if asTypeParam(x.typ) != nil { if asTypeParam(x.typ) != nil {
check.invalidOpf(call, "unsafe.Sizeof undefined for %s", x) check.errorf(call, invalidOp+"unsafe.Sizeof undefined for %s", x)
return return
} }
check.assignment(x, nil, "argument to unsafe.Sizeof") check.assignment(x, nil, "argument to unsafe.Sizeof")
@ -657,7 +657,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) (
// The result of assert is the value of pred if there is no error. // The result of assert is the value of pred if there is no error.
// Note: assert is only available in self-test mode. // Note: assert is only available in self-test mode.
if x.mode != constant_ || !isBoolean(x.typ) { if x.mode != constant_ || !isBoolean(x.typ) {
check.invalidArgf(x, "%s is not a boolean constant", x) check.errorf(x, invalidArg+"%s is not a boolean constant", x)
return return
} }
if x.val.Kind() != constant.Bool { if x.val.Kind() != constant.Bool {

View file

@ -158,7 +158,7 @@ func (check *Checker) call(x *operand, call *syntax.CallExpr) exprKind {
sig := asSignature(x.typ) sig := asSignature(x.typ)
if sig == nil { if sig == nil {
check.invalidOpf(x, "cannot call non-function %s", x) check.errorf(x, invalidOp+"cannot call non-function %s", x)
x.mode = invalid x.mode = invalid
x.expr = call x.expr = call
return statement return statement
@ -248,7 +248,7 @@ func (check *Checker) exprOrTypeList(elist []syntax.Expr) (xlist []*operand, ok
} }
} }
if 0 < ntypes && ntypes < len(xlist) { if 0 < ntypes && ntypes < len(xlist) {
check.errorf(xlist[0], "mix of value and type expressions") check.error(xlist[0], "mix of value and type expressions")
ok = false ok = false
} }
} }

View file

@ -214,7 +214,7 @@ func (check *Checker) initFiles(files []*syntax.File) {
if name != "_" { if name != "_" {
pkg.name = name pkg.name = name
} else { } else {
check.errorf(file.PkgName, "invalid package name _") check.error(file.PkgName, "invalid package name _")
} }
fallthrough fallthrough

View file

@ -629,14 +629,14 @@ func (check *Checker) typeDecl(obj *TypeName, tdecl *syntax.TypeDecl, def *Named
if alias && tdecl.TParamList != nil { if alias && tdecl.TParamList != nil {
// The parser will ensure this but we may still get an invalid AST. // The parser will ensure this but we may still get an invalid AST.
// Complain and continue as regular type definition. // Complain and continue as regular type definition.
check.errorf(tdecl, "generic type cannot be alias") check.error(tdecl, "generic type cannot be alias")
alias = false alias = false
} }
if alias { if alias {
// type alias declaration // type alias declaration
if !check.allowVersion(obj.pkg, 1, 9) { if !check.allowVersion(obj.pkg, 1, 9) {
check.errorf(tdecl, "type aliases requires go1.9 or later") check.error(tdecl, "type aliases requires go1.9 or later")
} }
obj.typ = Typ[Invalid] obj.typ = Typ[Invalid]
@ -978,7 +978,7 @@ func (check *Checker) declStmt(list []syntax.Decl) {
check.pop().setColor(black) check.pop().setColor(black)
default: default:
check.invalidASTf(s, "unknown syntax.Decl node %T", s) check.errorf(s, invalidAST+"unknown syntax.Decl node %T", s)
} }
} }
} }

View file

@ -0,0 +1,49 @@
// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE ast.
package types2_test
import (
"cmd/compile/internal/syntax"
"testing"
)
// TestErrorCalls makes sure that check.errorf calls have at
// least 3 arguments (otherwise we should be using check.error).
func TestErrorCalls(t *testing.T) {
files, err := pkgFiles(".")
if err != nil {
t.Fatal(err)
}
for _, file := range files {
syntax.Walk(file, func(n syntax.Node) bool {
call, _ := n.(*syntax.CallExpr)
if call == nil {
return false
}
selx, _ := call.Fun.(*syntax.SelectorExpr)
if selx == nil {
return false
}
if !(isName(selx.X, "check") && isName(selx.Sel, "errorf")) {
return false
}
// check.errorf calls should have more than 2 arguments:
// position, format string, and arguments to format
if n := len(call.ArgList); n <= 2 {
t.Errorf("%s: got %d arguments, want > 2", call.Pos(), n)
return true
}
return false
})
}
}
func isName(n syntax.Node, name string) bool {
if n, ok := n.(*syntax.Name); ok {
return n.Value == name
}
return false
}

View file

@ -142,7 +142,7 @@ func (check *Checker) dump(format string, args ...interface{}) {
fmt.Println(check.sprintf(format, args...)) fmt.Println(check.sprintf(format, args...))
} }
func (check *Checker) err(pos syntax.Pos, msg string, soft bool) { func (check *Checker) err(at poser, msg string, soft bool) {
// Cheap trick: Don't report errors with messages containing // Cheap trick: Don't report errors with messages containing
// "invalid operand" or "invalid type" as those tend to be // "invalid operand" or "invalid type" as those tend to be
// follow-on errors which don't add useful information. Only // follow-on errors which don't add useful information. Only
@ -152,6 +152,8 @@ func (check *Checker) err(pos syntax.Pos, msg string, soft bool) {
return return
} }
pos := posFor(at)
// If we are encountering an error while evaluating an inherited // If we are encountering an error while evaluating an inherited
// constant initialization expression, pos is the position of in // constant initialization expression, pos is the position of in
// the original expression, and not of the currently declared // the original expression, and not of the currently declared
@ -179,32 +181,26 @@ func (check *Checker) err(pos syntax.Pos, msg string, soft bool) {
f(err) f(err)
} }
const (
invalidAST = "invalid AST: "
invalidArg = "invalid argument: "
invalidOp = "invalid operation: "
)
type poser interface { type poser interface {
Pos() syntax.Pos Pos() syntax.Pos
} }
func (check *Checker) error(at poser, msg string) { func (check *Checker) error(at poser, msg string) {
check.err(posFor(at), msg, false) check.err(at, msg, false)
} }
func (check *Checker) errorf(at poser, format string, args ...interface{}) { func (check *Checker) errorf(at poser, format string, args ...interface{}) {
check.err(posFor(at), check.sprintf(format, args...), false) check.err(at, check.sprintf(format, args...), false)
} }
func (check *Checker) softErrorf(at poser, format string, args ...interface{}) { func (check *Checker) softErrorf(at poser, format string, args ...interface{}) {
check.err(posFor(at), check.sprintf(format, args...), true) check.err(at, check.sprintf(format, args...), true)
}
func (check *Checker) invalidASTf(at poser, format string, args ...interface{}) {
check.errorf(at, "invalid AST: "+format, args...)
}
func (check *Checker) invalidArgf(at poser, format string, args ...interface{}) {
check.errorf(at, "invalid argument: "+format, args...)
}
func (check *Checker) invalidOpf(at poser, format string, args ...interface{}) {
check.errorf(at, "invalid operation: "+format, args...)
} }
// posFor reports the left (= start) position of at. // posFor reports the left (= start) position of at.

View file

@ -75,14 +75,14 @@ func (check *Checker) op(m opPredicates, x *operand, op syntax.Operator) bool {
if pred := m[op]; pred != nil { if pred := m[op]; pred != nil {
if !pred(x.typ) { if !pred(x.typ) {
if check.conf.CompilerErrorMessages { if check.conf.CompilerErrorMessages {
check.invalidOpf(x, "operator %s not defined on %s", op, x) check.errorf(x, invalidOp+"operator %s not defined on %s", op, x)
} else { } else {
check.invalidOpf(x, "operator %s not defined for %s", op, x) check.errorf(x, invalidOp+"operator %s not defined for %s", op, x)
} }
return false return false
} }
} else { } else {
check.invalidASTf(x, "unknown operator %s", op) check.errorf(x, invalidAST+"unknown operator %s", op)
return false return false
} }
return true return true
@ -108,7 +108,7 @@ func (check *Checker) overflow(x *operand) {
// TODO(gri) We should report exactly what went wrong. At the // TODO(gri) We should report exactly what went wrong. At the
// moment we don't have the (go/constant) API for that. // moment we don't have the (go/constant) API for that.
// See also TODO in go/constant/value.go. // See also TODO in go/constant/value.go.
check.errorf(pos, "constant result is not representable") check.error(pos, "constant result is not representable")
return return
} }
@ -169,7 +169,7 @@ func (check *Checker) unary(x *operand, e *syntax.Operation) {
// spec: "As an exception to the addressability // spec: "As an exception to the addressability
// requirement x may also be a composite literal." // requirement x may also be a composite literal."
if _, ok := unparen(e.X).(*syntax.CompositeLit); !ok && x.mode != variable { if _, ok := unparen(e.X).(*syntax.CompositeLit); !ok && x.mode != variable {
check.invalidOpf(x, "cannot take address of %s", x) check.errorf(x, invalidOp+"cannot take address of %s", x)
x.mode = invalid x.mode = invalid
return return
} }
@ -180,12 +180,12 @@ func (check *Checker) unary(x *operand, e *syntax.Operation) {
case syntax.Recv: case syntax.Recv:
typ := asChan(x.typ) typ := asChan(x.typ)
if typ == nil { if typ == nil {
check.invalidOpf(x, "cannot receive from non-channel %s", x) check.errorf(x, invalidOp+"cannot receive from non-channel %s", x)
x.mode = invalid x.mode = invalid
return return
} }
if typ.dir == SendOnly { if typ.dir == SendOnly {
check.invalidOpf(x, "cannot receive from send-only channel %s", x) check.errorf(x, invalidOp+"cannot receive from send-only channel %s", x)
x.mode = invalid x.mode = invalid
return return
} }
@ -562,7 +562,7 @@ func (check *Checker) updateExprType(x syntax.Expr, typ Type, final bool) {
// We already know from the shift check that it is representable // We already know from the shift check that it is representable
// as an integer if it is a constant. // as an integer if it is a constant.
if !isInteger(typ) { if !isInteger(typ) {
check.invalidOpf(x, "shifted operand %s (type %s) must be integer", x, typ) check.errorf(x, invalidOp+"shifted operand %s (type %s) must be integer", x, typ)
return return
} }
// Even if we have an integer, if the value is a constant we // Even if we have an integer, if the value is a constant we
@ -753,7 +753,7 @@ func (check *Checker) comparison(x, y *operand, op syntax.Operator) {
if err != "" { if err != "" {
// TODO(gri) better error message for cases where one can only compare against nil // TODO(gri) better error message for cases where one can only compare against nil
check.invalidOpf(x, "cannot compare %s %s %s (%s)", x.expr, op, y.expr, err) check.errorf(x, invalidOp+"cannot compare %s %s %s (%s)", x.expr, op, y.expr, err)
x.mode = invalid x.mode = invalid
return return
} }
@ -791,7 +791,7 @@ func (check *Checker) shift(x, y *operand, e syntax.Expr, op syntax.Operator) {
// as an integer. Nothing to do. // as an integer. Nothing to do.
} else { } else {
// shift has no chance // shift has no chance
check.invalidOpf(x, "shifted operand %s must be integer", x) check.errorf(x, invalidOp+"shifted operand %s must be integer", x)
x.mode = invalid x.mode = invalid
return return
} }
@ -803,7 +803,7 @@ func (check *Checker) shift(x, y *operand, e syntax.Expr, op syntax.Operator) {
if y.mode == constant_ { if y.mode == constant_ {
yval := constant.ToInt(y.val) // consider -1, 1.0, but not -1.1 yval := constant.ToInt(y.val) // consider -1, 1.0, but not -1.1
if yval.Kind() == constant.Int && constant.Sign(yval) < 0 { if yval.Kind() == constant.Int && constant.Sign(yval) < 0 {
check.invalidOpf(y, "negative shift count %s", y) check.errorf(y, invalidOp+"negative shift count %s", y)
x.mode = invalid x.mode = invalid
return return
} }
@ -818,11 +818,11 @@ func (check *Checker) shift(x, y *operand, e syntax.Expr, op syntax.Operator) {
return return
} }
} else if !isInteger(y.typ) { } else if !isInteger(y.typ) {
check.invalidOpf(y, "shift count %s must be integer", y) check.errorf(y, invalidOp+"shift count %s must be integer", y)
x.mode = invalid x.mode = invalid
return return
} else if !isUnsigned(y.typ) && !check.allowVersion(check.pkg, 1, 13) { } else if !isUnsigned(y.typ) && !check.allowVersion(check.pkg, 1, 13) {
check.invalidOpf(y, "signed shift count %s requires go1.13 or later", y) check.errorf(y, invalidOp+"signed shift count %s requires go1.13 or later", y)
x.mode = invalid x.mode = invalid
return return
} }
@ -842,7 +842,7 @@ func (check *Checker) shift(x, y *operand, e syntax.Expr, op syntax.Operator) {
const shiftBound = 1023 - 1 + 52 // so we can express smallestFloat64 (see issue #44057) const shiftBound = 1023 - 1 + 52 // so we can express smallestFloat64 (see issue #44057)
s, ok := constant.Uint64Val(y.val) s, ok := constant.Uint64Val(y.val)
if !ok || s > shiftBound { if !ok || s > shiftBound {
check.invalidOpf(y, "invalid shift count %s", y) check.errorf(y, invalidOp+"invalid shift count %s", y)
x.mode = invalid x.mode = invalid
return return
} }
@ -893,7 +893,7 @@ func (check *Checker) shift(x, y *operand, e syntax.Expr, op syntax.Operator) {
// non-constant shift - lhs must be an integer // non-constant shift - lhs must be an integer
if !isInteger(x.typ) { if !isInteger(x.typ) {
check.invalidOpf(x, "shifted operand %s must be integer", x) check.errorf(x, invalidOp+"shifted operand %s must be integer", x)
x.mode = invalid x.mode = invalid
return return
} }
@ -963,7 +963,7 @@ func (check *Checker) binary(x *operand, e syntax.Expr, lhs, rhs syntax.Expr, op
// only report an error if we have valid types // only report an error if we have valid types
// (otherwise we had an error reported elsewhere already) // (otherwise we had an error reported elsewhere already)
if x.typ != Typ[Invalid] && y.typ != Typ[Invalid] { if x.typ != Typ[Invalid] && y.typ != Typ[Invalid] {
check.invalidOpf(x, "mismatched types %s and %s", x.typ, y.typ) check.errorf(x, invalidOp+"mismatched types %s and %s", x.typ, y.typ)
} }
x.mode = invalid x.mode = invalid
return return
@ -977,7 +977,7 @@ func (check *Checker) binary(x *operand, e syntax.Expr, lhs, rhs syntax.Expr, op
if op == syntax.Div || op == syntax.Rem { if op == syntax.Div || op == syntax.Rem {
// check for zero divisor // check for zero divisor
if (x.mode == constant_ || isInteger(x.typ)) && y.mode == constant_ && constant.Sign(y.val) == 0 { if (x.mode == constant_ || isInteger(x.typ)) && y.mode == constant_ && constant.Sign(y.val) == 0 {
check.invalidOpf(&y, "division by zero") check.error(&y, invalidOp+"division by zero")
x.mode = invalid x.mode = invalid
return return
} }
@ -987,7 +987,7 @@ func (check *Checker) binary(x *operand, e syntax.Expr, lhs, rhs syntax.Expr, op
re, im := constant.Real(y.val), constant.Imag(y.val) re, im := constant.Real(y.val), constant.Imag(y.val)
re2, im2 := constant.BinaryOp(re, token.MUL, re), constant.BinaryOp(im, token.MUL, im) re2, im2 := constant.BinaryOp(re, token.MUL, re), constant.BinaryOp(im, token.MUL, im)
if constant.Sign(re2) == 0 && constant.Sign(im2) == 0 { if constant.Sign(re2) == 0 && constant.Sign(im2) == 0 {
check.invalidOpf(&y, "division by zero") check.error(&y, invalidOp+"division by zero")
x.mode = invalid x.mode = invalid
return return
} }
@ -1038,7 +1038,7 @@ func (check *Checker) index(index syntax.Expr, max int64) (typ Type, val int64)
// the index must be of integer type // the index must be of integer type
if !isInteger(x.typ) { if !isInteger(x.typ) {
check.invalidArgf(&x, "index %s must be integer", &x) check.errorf(&x, invalidArg+"index %s must be integer", &x)
return return
} }
@ -1048,7 +1048,7 @@ func (check *Checker) index(index syntax.Expr, max int64) (typ Type, val int64)
// a constant index i must be in bounds // a constant index i must be in bounds
if constant.Sign(x.val) < 0 { if constant.Sign(x.val) < 0 {
check.invalidArgf(&x, "index %s must not be negative", &x) check.errorf(&x, invalidArg+"index %s must not be negative", &x)
return return
} }
@ -1242,7 +1242,7 @@ func (check *Checker) exprInternal(x *operand, e syntax.Expr, hint Type) exprKin
x.mode = value x.mode = value
x.typ = sig x.typ = sig
} else { } else {
check.invalidASTf(e, "invalid function literal %s", e) check.errorf(e, invalidAST+"invalid function literal %v", e)
goto Error goto Error
} }
@ -1608,23 +1608,23 @@ func (check *Checker) exprInternal(x *operand, e syntax.Expr, hint Type) exprKin
} }
if !valid { if !valid {
check.invalidOpf(x, "cannot index %s", x) check.errorf(x, invalidOp+"cannot index %s", x)
goto Error goto Error
} }
if e.Index == nil { if e.Index == nil {
check.invalidASTf(e, "missing index for %s", x) check.errorf(e, invalidAST+"missing index for %s", x)
goto Error goto Error
} }
index := e.Index index := e.Index
if l, _ := index.(*syntax.ListExpr); l != nil { if l, _ := index.(*syntax.ListExpr); l != nil {
if n := len(l.ElemList); n <= 1 { if n := len(l.ElemList); n <= 1 {
check.invalidASTf(e, "invalid use of ListExpr for index expression %s with %d indices", e, n) check.errorf(e, invalidAST+"invalid use of ListExpr for index expression %v with %d indices", e, n)
goto Error goto Error
} }
// len(l.ElemList) > 1 // len(l.ElemList) > 1
check.invalidOpf(l.ElemList[1], "more than one index") check.error(l.ElemList[1], invalidOp+"more than one index")
index = l.ElemList[0] // continue with first index index = l.ElemList[0] // continue with first index
} }
@ -1651,7 +1651,7 @@ func (check *Checker) exprInternal(x *operand, e syntax.Expr, hint Type) exprKin
case *Basic: case *Basic:
if isString(typ) { if isString(typ) {
if e.Full { if e.Full {
check.invalidOpf(x, "3-index slice of string") check.error(x, invalidOp+"3-index slice of string")
goto Error goto Error
} }
valid = true valid = true
@ -1669,7 +1669,7 @@ func (check *Checker) exprInternal(x *operand, e syntax.Expr, hint Type) exprKin
valid = true valid = true
length = typ.len length = typ.len
if x.mode != variable { if x.mode != variable {
check.invalidOpf(x, "%s (slice of unaddressable value)", x) check.errorf(x, invalidOp+"%s (slice of unaddressable value)", x)
goto Error goto Error
} }
x.typ = &Slice{elem: typ.elem} x.typ = &Slice{elem: typ.elem}
@ -1686,12 +1686,12 @@ func (check *Checker) exprInternal(x *operand, e syntax.Expr, hint Type) exprKin
// x.typ doesn't change // x.typ doesn't change
case *Sum, *TypeParam: case *Sum, *TypeParam:
check.errorf(x, "generic slice expressions not yet implemented") check.error(x, "generic slice expressions not yet implemented")
goto Error goto Error
} }
if !valid { if !valid {
check.invalidOpf(x, "cannot slice %s", x) check.errorf(x, invalidOp+"cannot slice %s", x)
goto Error goto Error
} }
@ -1699,7 +1699,7 @@ func (check *Checker) exprInternal(x *operand, e syntax.Expr, hint Type) exprKin
// spec: "Only the first index may be omitted; it defaults to 0." // spec: "Only the first index may be omitted; it defaults to 0."
if e.Full && (e.Index[1] == nil || e.Index[2] == nil) { if e.Full && (e.Index[1] == nil || e.Index[2] == nil) {
check.invalidASTf(e, "2nd and 3rd index required in 3-index slice") check.error(e, invalidAST+"2nd and 3rd index required in 3-index slice")
goto Error goto Error
} }
@ -1756,7 +1756,7 @@ func (check *Checker) exprInternal(x *operand, e syntax.Expr, hint Type) exprKin
check.ordinaryType(x.Pos(), xtyp) check.ordinaryType(x.Pos(), xtyp)
// x.(type) expressions are encoded via TypeSwitchGuards // x.(type) expressions are encoded via TypeSwitchGuards
if e.Type == nil { if e.Type == nil {
check.invalidASTf(e, "invalid use of AssertExpr") check.error(e, invalidAST+"invalid use of AssertExpr")
goto Error goto Error
} }
T := check.varType(e.Type) T := check.varType(e.Type)
@ -1769,7 +1769,7 @@ func (check *Checker) exprInternal(x *operand, e syntax.Expr, hint Type) exprKin
case *syntax.TypeSwitchGuard: case *syntax.TypeSwitchGuard:
// x.(type) expressions are handled explicitly in type switches // x.(type) expressions are handled explicitly in type switches
check.invalidASTf(e, "use of .(type) outside type switch") check.error(e, invalidAST+"use of .(type) outside type switch")
goto Error goto Error
case *syntax.CallExpr: case *syntax.CallExpr:
@ -1811,7 +1811,7 @@ func (check *Checker) exprInternal(x *operand, e syntax.Expr, hint Type) exprKin
x.mode = variable x.mode = variable
x.typ = typ.base x.typ = typ.base
} else { } else {
check.invalidOpf(x, "cannot indirect %s", x) check.errorf(x, invalidOp+"cannot indirect %s", x)
goto Error goto Error
} }
} }
@ -1837,7 +1837,7 @@ func (check *Checker) exprInternal(x *operand, e syntax.Expr, hint Type) exprKin
case *syntax.KeyValueExpr: case *syntax.KeyValueExpr:
// key:value expressions are handled in composite literals // key:value expressions are handled in composite literals
check.invalidASTf(e, "no key:value expected") check.error(e, invalidAST+"no key:value expected")
goto Error goto Error
case *syntax.ArrayType, *syntax.SliceType, *syntax.StructType, *syntax.FuncType, case *syntax.ArrayType, *syntax.SliceType, *syntax.StructType, *syntax.FuncType,

View file

@ -212,7 +212,7 @@ func (check *Checker) blockBranches(all *Scope, parent *block, lstmt *syntax.Lab
} }
default: default:
check.invalidASTf(s, "branch statement: %s %s", s.Tok, name) check.errorf(s, invalidAST+"branch statement: %s %s", s.Tok, name)
return return
} }

View file

@ -92,14 +92,14 @@ func (check *Checker) declarePkgObj(ident *syntax.Name, obj Object, d *declInfo)
// spec: "A package-scope or file-scope identifier with name init // spec: "A package-scope or file-scope identifier with name init
// may only be declared to be a function with this (func()) signature." // may only be declared to be a function with this (func()) signature."
if ident.Value == "init" { if ident.Value == "init" {
check.errorf(ident, "cannot declare init - must be func") check.error(ident, "cannot declare init - must be func")
return return
} }
// spec: "The main package must have package name main and declare // spec: "The main package must have package name main and declare
// a function main that takes no arguments and returns no value." // a function main that takes no arguments and returns no value."
if ident.Value == "main" && check.pkg.name == "main" { if ident.Value == "main" && check.pkg.name == "main" {
check.errorf(ident, "cannot declare main - must be func") check.error(ident, "cannot declare main - must be func")
return return
} }
@ -256,13 +256,13 @@ func (check *Checker) collectObjects() {
name = s.LocalPkgName.Value name = s.LocalPkgName.Value
if path == "C" { if path == "C" {
// match cmd/compile (not prescribed by spec) // match cmd/compile (not prescribed by spec)
check.errorf(s.LocalPkgName, `cannot rename import "C"`) check.error(s.LocalPkgName, `cannot rename import "C"`)
continue continue
} }
} }
if name == "init" { if name == "init" {
check.errorf(s.LocalPkgName, "cannot import package as init - init must be a func") check.error(s.LocalPkgName, "cannot import package as init - init must be a func")
continue continue
} }
@ -428,8 +428,8 @@ func (check *Checker) collectObjects() {
// method // method
// d.Recv != nil // d.Recv != nil
if !methodTypeParamsOk && len(d.TParamList) != 0 { if !methodTypeParamsOk && len(d.TParamList) != 0 {
//check.invalidASTf(d.TParamList.Pos(), "method must have no type parameters") //check.error(d.TParamList.Pos(), invalidAST + "method must have no type parameters")
check.invalidASTf(d, "method must have no type parameters") check.error(d, invalidAST+"method must have no type parameters")
} }
ptr, recv, _ := check.unpackRecv(d.Recv.Type, false) ptr, recv, _ := check.unpackRecv(d.Recv.Type, false)
// (Methods with invalid receiver cannot be associated to a type, and // (Methods with invalid receiver cannot be associated to a type, and
@ -449,7 +449,7 @@ func (check *Checker) collectObjects() {
obj.setOrder(uint32(len(check.objMap))) obj.setOrder(uint32(len(check.objMap)))
default: default:
check.invalidASTf(s, "unknown syntax.Decl node %T", s) check.errorf(s, invalidAST+"unknown syntax.Decl node %T", s)
} }
} }
} }
@ -530,7 +530,7 @@ L: // unpack receiver type
case *syntax.BadExpr: case *syntax.BadExpr:
// ignore - error already reported by parser // ignore - error already reported by parser
case nil: case nil:
check.invalidASTf(ptyp, "parameterized receiver contains nil parameters") check.error(ptyp, invalidAST+"parameterized receiver contains nil parameters")
default: default:
check.errorf(arg, "receiver type parameter %s must be an identifier", arg) check.errorf(arg, "receiver type parameter %s must be an identifier", arg)
} }

View file

@ -357,12 +357,12 @@ func (check *Checker) stmt(ctxt stmtContext, s syntax.Stmt) {
tch := asChan(ch.typ) tch := asChan(ch.typ)
if tch == nil { if tch == nil {
check.invalidOpf(s, "cannot send to non-chan type %s", ch.typ) check.errorf(s, invalidOp+"cannot send to non-chan type %s", ch.typ)
return return
} }
if tch.dir == RecvOnly { if tch.dir == RecvOnly {
check.invalidOpf(s, "cannot send to receive-only type %s", tch) check.errorf(s, invalidOp+"cannot send to receive-only type %s", tch)
return return
} }
@ -373,7 +373,7 @@ func (check *Checker) stmt(ctxt stmtContext, s syntax.Stmt) {
if s.Rhs == nil { if s.Rhs == nil {
// x++ or x-- // x++ or x--
if len(lhs) != 1 { if len(lhs) != 1 {
check.invalidASTf(s, "%s%s requires one operand", s.Op, s.Op) check.errorf(s, invalidAST+"%s%s requires one operand", s.Op, s.Op)
return return
} }
var x operand var x operand
@ -382,7 +382,7 @@ func (check *Checker) stmt(ctxt stmtContext, s syntax.Stmt) {
return return
} }
if !isNumeric(x.typ) { if !isNumeric(x.typ) {
check.invalidOpf(lhs[0], "%s%s%s (non-numeric type %s)", lhs[0], s.Op, s.Op, x.typ) check.errorf(lhs[0], invalidOp+"%s%s%s (non-numeric type %s)", lhs[0], s.Op, s.Op, x.typ)
return return
} }
check.assignVar(lhs[0], &x) check.assignVar(lhs[0], &x)
@ -484,7 +484,7 @@ func (check *Checker) stmt(ctxt stmtContext, s syntax.Stmt) {
// goto's must have labels, should have been caught above // goto's must have labels, should have been caught above
fallthrough fallthrough
default: default:
check.invalidASTf(s, "branch statement: %s", s.Tok) check.errorf(s, invalidAST+"branch statement: %s", s.Tok)
} }
case *syntax.BlockStmt: case *syntax.BlockStmt:
@ -642,7 +642,7 @@ func (check *Checker) switchStmt(inner stmtContext, s *syntax.SwitchStmt) {
seen := make(valueMap) // map of seen case values to positions and types seen := make(valueMap) // map of seen case values to positions and types
for i, clause := range s.Body { for i, clause := range s.Body {
if clause == nil { if clause == nil {
check.invalidASTf(clause, "incorrect expression switch case") check.error(clause, invalidAST+"incorrect expression switch case")
continue continue
} }
end := s.Rbrace end := s.Rbrace
@ -699,7 +699,7 @@ func (check *Checker) typeSwitchStmt(inner stmtContext, s *syntax.SwitchStmt, gu
seen := make(map[Type]syntax.Pos) // map of seen types to positions seen := make(map[Type]syntax.Pos) // map of seen types to positions
for i, clause := range s.Body { for i, clause := range s.Body {
if clause == nil { if clause == nil {
check.invalidASTf(s, "incorrect type switch case") check.error(s, invalidAST+"incorrect type switch case")
continue continue
} }
end := s.Rbrace end := s.Rbrace
@ -765,7 +765,7 @@ func (check *Checker) rangeStmt(inner stmtContext, s *syntax.ForStmt, rclause *s
var sValue syntax.Expr var sValue syntax.Expr
if p, _ := sKey.(*syntax.ListExpr); p != nil { if p, _ := sKey.(*syntax.ListExpr); p != nil {
if len(p.ElemList) != 2 { if len(p.ElemList) != 2 {
check.invalidASTf(s, "invalid lhs in range clause") check.error(s, invalidAST+"invalid lhs in range clause")
return return
} }
sKey = p.ElemList[0] sKey = p.ElemList[0]

View file

@ -29,7 +29,7 @@ func (check *Checker) ident(x *operand, e *syntax.Name, def *Named, wantType boo
scope, obj := check.scope.LookupParent(e.Value, check.pos) scope, obj := check.scope.LookupParent(e.Value, check.pos)
if obj == nil { if obj == nil {
if e.Value == "_" { if e.Value == "_" {
check.errorf(e, "cannot use _ as value or type") check.error(e, "cannot use _ as value or type")
} else { } else {
if check.conf.CompilerErrorMessages { if check.conf.CompilerErrorMessages {
check.errorf(e, "undefined: %s", e.Value) check.errorf(e, "undefined: %s", e.Value)
@ -76,7 +76,7 @@ func (check *Checker) ident(x *operand, e *syntax.Name, def *Named, wantType boo
} }
if obj == universeIota { if obj == universeIota {
if check.iota == nil { if check.iota == nil {
check.errorf(e, "cannot use iota outside constant declaration") check.error(e, "cannot use iota outside constant declaration")
return return
} }
x.val = check.iota x.val = check.iota
@ -337,7 +337,7 @@ func (check *Checker) funcType(sig *Signature, recvPar *syntax.Field, tparams []
// (A separate check is needed when type-checking interface method signatures because // (A separate check is needed when type-checking interface method signatures because
// they don't have a receiver specification.) // they don't have a receiver specification.)
if recvPar != nil && !check.conf.AcceptMethodTypeParams { if recvPar != nil && !check.conf.AcceptMethodTypeParams {
check.errorf(ftyp, "methods cannot have type parameters") check.error(ftyp, "methods cannot have type parameters")
} }
} }
@ -511,7 +511,7 @@ func (check *Checker) typInternal(e0 syntax.Expr, def *Named) (T Type) {
typ.len = check.arrayLength(e.Len) typ.len = check.arrayLength(e.Len)
} else { } else {
// [...]array // [...]array
check.errorf(e, "invalid use of [...] array (outside a composite literal)") check.error(e, "invalid use of [...] array (outside a composite literal)")
typ.len = -1 typ.len = -1
} }
typ.elem = check.varType(e.Elem) typ.elem = check.varType(e.Elem)
@ -599,7 +599,7 @@ func (check *Checker) typInternal(e0 syntax.Expr, def *Named) (T Type) {
case syntax.RecvOnly: case syntax.RecvOnly:
dir = RecvOnly dir = RecvOnly
default: default:
check.invalidASTf(e, "unknown channel direction %d", e.Dir) check.errorf(e, invalidAST+"unknown channel direction %d", e.Dir)
// ok to continue // ok to continue
} }
@ -763,7 +763,7 @@ func (check *Checker) collectParams(scope *Scope, list []*syntax.Field, type0 sy
// named parameter // named parameter
name := field.Name.Value name := field.Name.Value
if name == "" { if name == "" {
check.invalidASTf(field.Name, "anonymous parameter") check.error(field.Name, invalidAST+"anonymous parameter")
// ok to continue // ok to continue
} }
par := NewParam(field.Name.Pos(), check.pkg, name, typ) par := NewParam(field.Name.Pos(), check.pkg, name, typ)
@ -780,7 +780,7 @@ func (check *Checker) collectParams(scope *Scope, list []*syntax.Field, type0 sy
} }
if named && anonymous { if named && anonymous {
check.invalidASTf(list[0], "list contains both named and anonymous parameters") check.error(list[0], invalidAST+"list contains both named and anonymous parameters")
// ok to continue // ok to continue
} }
@ -817,9 +817,9 @@ func (check *Checker) interfaceType(ityp *Interface, iface *syntax.InterfaceType
name := f.Name.Value name := f.Name.Value
if name == "_" { if name == "_" {
if check.conf.CompilerErrorMessages { if check.conf.CompilerErrorMessages {
check.errorf(f.Name, "methods must have a unique non-blank name") check.error(f.Name, "methods must have a unique non-blank name")
} else { } else {
check.errorf(f.Name, "invalid method name _") check.error(f.Name, "invalid method name _")
} }
continue // ignore continue // ignore
} }
@ -830,7 +830,7 @@ func (check *Checker) interfaceType(ityp *Interface, iface *syntax.InterfaceType
// the author intended to include all types. // the author intended to include all types.
types = append(types, f.Type) types = append(types, f.Type)
if tname != nil && tname != f.Name { if tname != nil && tname != f.Name {
check.errorf(f.Name, "cannot have multiple type lists in an interface") check.error(f.Name, "cannot have multiple type lists in an interface")
} }
tname = f.Name tname = f.Name
continue continue
@ -840,7 +840,7 @@ func (check *Checker) interfaceType(ityp *Interface, iface *syntax.InterfaceType
sig, _ := typ.(*Signature) sig, _ := typ.(*Signature)
if sig == nil { if sig == nil {
if typ != Typ[Invalid] { if typ != Typ[Invalid] {
check.invalidASTf(f.Type, "%s is not a method signature", typ) check.errorf(f.Type, invalidAST+"%s is not a method signature", typ)
} }
continue // ignore continue // ignore
} }
@ -849,7 +849,7 @@ func (check *Checker) interfaceType(ityp *Interface, iface *syntax.InterfaceType
// (This extra check is needed here because interface method signatures don't have // (This extra check is needed here because interface method signatures don't have
// a receiver specification.) // a receiver specification.)
if sig.tparams != nil && !check.conf.AcceptMethodTypeParams { if sig.tparams != nil && !check.conf.AcceptMethodTypeParams {
check.errorf(f.Type, "methods cannot have type parameters") check.error(f.Type, "methods cannot have type parameters")
} }
// use named receiver type if available (for better error messages) // use named receiver type if available (for better error messages)
@ -1087,7 +1087,7 @@ func (check *Checker) tag(t *syntax.BasicLit) string {
return val return val
} }
} }
check.invalidASTf(t, "incorrect tag syntax: %q", t.Value) check.errorf(t, invalidAST+"incorrect tag syntax: %q", t.Value)
} }
return "" return ""
} }
@ -1180,13 +1180,13 @@ func (check *Checker) structType(styp *Struct, e *syntax.StructType) {
} }
// unsafe.Pointer is treated like a regular pointer // unsafe.Pointer is treated like a regular pointer
if t.kind == UnsafePointer { if t.kind == UnsafePointer {
check.errorf(embeddedPos, "embedded field type cannot be unsafe.Pointer") check.error(embeddedPos, "embedded field type cannot be unsafe.Pointer")
} }
case *Pointer: case *Pointer:
check.errorf(embeddedPos, "embedded field type cannot be a pointer") check.error(embeddedPos, "embedded field type cannot be a pointer")
case *Interface: case *Interface:
if isPtr { if isPtr {
check.errorf(embeddedPos, "embedded field type cannot be a pointer to an interface") check.error(embeddedPos, "embedded field type cannot be a pointer to an interface")
} }
} }
}) })
@ -1220,7 +1220,7 @@ func (check *Checker) collectTypeConstraints(pos syntax.Pos, types []syntax.Expr
list := make([]Type, 0, len(types)) // assume all types are correct list := make([]Type, 0, len(types)) // assume all types are correct
for _, texpr := range types { for _, texpr := range types {
if texpr == nil { if texpr == nil {
check.invalidASTf(pos, "missing type constraint") check.error(pos, invalidAST+"missing type constraint")
continue continue
} }
list = append(list, check.varType(texpr)) list = append(list, check.varType(texpr))

View file

@ -21,7 +21,7 @@ func (check *Checker) langCompat(lit *syntax.BasicLit) {
} }
// len(s) > 2 // len(s) > 2
if strings.Contains(s, "_") { if strings.Contains(s, "_") {
check.errorf(lit, "underscores in numeric literals requires go1.13 or later") check.error(lit, "underscores in numeric literals requires go1.13 or later")
return return
} }
if s[0] != '0' { if s[0] != '0' {
@ -29,15 +29,15 @@ func (check *Checker) langCompat(lit *syntax.BasicLit) {
} }
radix := s[1] radix := s[1]
if radix == 'b' || radix == 'B' { if radix == 'b' || radix == 'B' {
check.errorf(lit, "binary literals requires go1.13 or later") check.error(lit, "binary literals requires go1.13 or later")
return return
} }
if radix == 'o' || radix == 'O' { if radix == 'o' || radix == 'O' {
check.errorf(lit, "0o/0O-style octal literals requires go1.13 or later") check.error(lit, "0o/0O-style octal literals requires go1.13 or later")
return return
} }
if lit.Kind != syntax.IntLit && (radix == 'x' || radix == 'X') { if lit.Kind != syntax.IntLit && (radix == 'x' || radix == 'X') {
check.errorf(lit, "hexadecimal floating-point literals requires go1.13 or later") check.error(lit, "hexadecimal floating-point literals requires go1.13 or later")
} }
} }