mirror of
https://github.com/golang/go
synced 2024-10-01 13:44:47 +00:00
go/types, types2: quote user-supplied names in error messages
Use `' quotes (as in `foo') to differentiate from Go quotes. Quoting prevents confusion when user-supplied names alter the meaning of the error message. For instance, report duplicate method `wanted' rather than duplicate method wanted Exceptions: - don't quote _: `_' is ugly and not necessary - don't quote after a ":": undefined name: foo - don't quote if the name is used correctly in a statement: goto L jumps over variable declaration Quoting is done with a helper function and can be centrally adjusted and fine-tuned as needed. Adjusted some test cases to explicitly include the quoted names. Fixes #65790. Change-Id: Icce667215f303ab8685d3e5cb00d540a2fd372ca Reviewed-on: https://go-review.googlesource.com/c/go/+/571396 TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Robert Griesemer <gri@google.com> Reviewed-by: Robert Findley <rfindley@google.com> Run-TryBot: Emmanuel Odeke <emmanuel@orijtech.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Auto-Submit: Robert Griesemer <gri@google.com>
This commit is contained in:
parent
2e8d84f148
commit
dc6a5cfca1
|
@ -25,7 +25,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) (
|
|||
if hasDots(call) && id != _Append {
|
||||
check.errorf(dddErrPos(call),
|
||||
InvalidDotDotDot,
|
||||
invalidOp+"invalid use of ... with built-in %s", bin.name)
|
||||
invalidOp+"invalid use of ... with built-in %s", quote(bin.name))
|
||||
check.use(argList...)
|
||||
return
|
||||
}
|
||||
|
@ -210,7 +210,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) (
|
|||
if id == _Len {
|
||||
code = InvalidLen
|
||||
}
|
||||
check.errorf(x, code, invalidArg+"%s for %s", x, bin.name)
|
||||
check.errorf(x, code, invalidArg+"%s for %s", x, quote(bin.name))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
@ -533,7 +533,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) (
|
|||
case _Max, _Min:
|
||||
// max(x, ...)
|
||||
// min(x, ...)
|
||||
check.verifyVersionf(call.Fun, go1_21, bin.name)
|
||||
check.verifyVersionf(call.Fun, go1_21, quote(bin.name))
|
||||
|
||||
op := token.LSS
|
||||
if id == _Max {
|
||||
|
@ -576,7 +576,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) (
|
|||
if x.mode != constant_ {
|
||||
x.mode = value
|
||||
// A value must not be untyped.
|
||||
check.assignment(x, &emptyInterface, "argument to "+bin.name)
|
||||
check.assignment(x, &emptyInterface, "argument to "+quote(bin.name))
|
||||
if x.mode == invalid {
|
||||
return
|
||||
}
|
||||
|
@ -641,7 +641,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) (
|
|||
if nargs > 0 {
|
||||
params = make([]Type, nargs)
|
||||
for i, a := range args {
|
||||
check.assignment(a, nil, "argument to "+predeclaredFuncs[id].name)
|
||||
check.assignment(a, nil, "argument to "+quote(predeclaredFuncs[id].name))
|
||||
if a.mode == invalid {
|
||||
return
|
||||
}
|
||||
|
@ -992,7 +992,7 @@ func (check *Checker) applyTypeFunc(f func(Type) Type, x *operand, id builtinId)
|
|||
default:
|
||||
panic("unreachable")
|
||||
}
|
||||
check.softErrorf(x, code, "%s not supported as argument to %s for go1.18 (see go.dev/issue/50937)", x, predeclaredFuncs[id].name)
|
||||
check.softErrorf(x, code, "%s not supported as argument to %s for go1.18 (see go.dev/issue/50937)", x, quote(predeclaredFuncs[id].name))
|
||||
|
||||
// Construct a suitable new type parameter for the result type.
|
||||
// The type parameter is placed in the current package so export/import
|
||||
|
|
|
@ -719,7 +719,7 @@ func (check *Checker) selector(x *operand, e *syntax.SelectorExpr, def *TypeName
|
|||
goto Error
|
||||
}
|
||||
if !exp.Exported() {
|
||||
check.errorf(e.Sel, UnexportedName, "%s not exported by package %s", sel, pkg.name)
|
||||
check.errorf(e.Sel, UnexportedName, "%s not exported by package %s", quote(sel), quote(pkg.name))
|
||||
// ok to continue
|
||||
}
|
||||
}
|
||||
|
|
|
@ -298,7 +298,7 @@ func (check *Checker) initFiles(files []*syntax.File) {
|
|||
check.files = append(check.files, file)
|
||||
|
||||
default:
|
||||
check.errorf(file, MismatchedPkgName, "package %s; expected %s", name, pkg.name)
|
||||
check.errorf(file, MismatchedPkgName, "package %s; expected %s", quote(name), quote(pkg.name))
|
||||
// ignore this file
|
||||
}
|
||||
}
|
||||
|
|
|
@ -733,7 +733,7 @@ func (check *Checker) checkFieldUniqueness(base *Named) {
|
|||
// For historical consistency, we report the primary error on the
|
||||
// method, and the alt decl on the field.
|
||||
err := check.newError(DuplicateFieldAndMethod)
|
||||
err.addf(alt, "field and method with the same name %s", fld.name)
|
||||
err.addf(alt, "field and method with the same name %s", quote(fld.name))
|
||||
err.addAltDecl(fld)
|
||||
err.report()
|
||||
}
|
||||
|
|
|
@ -14,6 +14,39 @@ import (
|
|||
"strings"
|
||||
)
|
||||
|
||||
// quote encloses s in `' quotes, as in `foo', except for _,
|
||||
// which is left alone.
|
||||
//
|
||||
// Use to prevent confusion when user supplied names alter the
|
||||
// meaning of an error message.
|
||||
//
|
||||
// For instance, report
|
||||
//
|
||||
// duplicate method `wanted'
|
||||
//
|
||||
// rather than
|
||||
//
|
||||
// duplicate method wanted
|
||||
//
|
||||
// Exceptions:
|
||||
//
|
||||
// - don't quote _:
|
||||
// `_' is ugly and not necessary
|
||||
// - don't quote after a ":" as there's no need for it:
|
||||
// undefined name: foo
|
||||
// - don't quote if the name is used correctly in a statement:
|
||||
// goto L jumps over variable declaration
|
||||
//
|
||||
// quote encloses s in `' quotes, as in `foo',
|
||||
// except for _ which is left alone.
|
||||
func quote(s string) string {
|
||||
if s == "_" {
|
||||
// `_' is ugly and not necessary
|
||||
return s
|
||||
}
|
||||
return "`" + s + "'"
|
||||
}
|
||||
|
||||
func sprintf(qf Qualifier, tpSubscripts bool, format string, args ...any) string {
|
||||
for i, arg := range args {
|
||||
switch a := arg.(type) {
|
||||
|
|
|
@ -257,13 +257,12 @@ func TestIssue22525(t *testing.T) {
|
|||
got := "\n"
|
||||
conf := Config{Error: func(err error) { got += err.Error() + "\n" }}
|
||||
typecheck(src, &conf, nil) // do not crash
|
||||
want := `
|
||||
p:1:27: a declared and not used
|
||||
p:1:30: b declared and not used
|
||||
p:1:33: c declared and not used
|
||||
p:1:36: d declared and not used
|
||||
p:1:39: e declared and not used
|
||||
`
|
||||
want := "\n" +
|
||||
"p:1:27: `a' declared and not used\n" +
|
||||
"p:1:30: `b' declared and not used\n" +
|
||||
"p:1:33: `c' declared and not used\n" +
|
||||
"p:1:36: `d' declared and not used\n" +
|
||||
"p:1:39: `e' declared and not used\n"
|
||||
if got != want {
|
||||
t.Errorf("got: %swant: %s", got, want)
|
||||
}
|
||||
|
|
|
@ -28,9 +28,11 @@ func (check *Checker) labels(body *syntax.BlockStmt) {
|
|||
msg = "goto %s jumps into block"
|
||||
alt.(*Label).used = true // avoid another error
|
||||
code = JumpIntoBlock
|
||||
// don't quote name here because "goto L" matches the code
|
||||
} else {
|
||||
msg = "label %s not declared"
|
||||
code = UndeclaredLabel
|
||||
name = quote(name)
|
||||
}
|
||||
check.errorf(jmp.Label, code, msg, name)
|
||||
}
|
||||
|
@ -39,7 +41,7 @@ func (check *Checker) labels(body *syntax.BlockStmt) {
|
|||
for name, obj := range all.elems {
|
||||
obj = resolve(name, obj)
|
||||
if lbl := obj.(*Label); !lbl.used {
|
||||
check.softErrorf(lbl.pos, UnusedLabel, "label %s declared and not used", lbl.name)
|
||||
check.softErrorf(lbl.pos, UnusedLabel, "label %s declared and not used", quote(lbl.name))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -135,7 +137,7 @@ func (check *Checker) blockBranches(all *Scope, parent *block, lstmt *syntax.Lab
|
|||
if alt := all.Insert(lbl); alt != nil {
|
||||
err := check.newError(DuplicateLabel)
|
||||
err.soft = true
|
||||
err.addf(lbl.pos, "label %s already declared", name)
|
||||
err.addf(lbl.pos, "label %s already declared", quote(name))
|
||||
err.addAltDecl(alt)
|
||||
err.report()
|
||||
// ok to continue
|
||||
|
@ -191,7 +193,7 @@ func (check *Checker) blockBranches(all *Scope, parent *block, lstmt *syntax.Lab
|
|||
}
|
||||
}
|
||||
if !valid {
|
||||
check.errorf(s.Label, MisplacedLabel, "invalid break label %s", name)
|
||||
check.errorf(s.Label, MisplacedLabel, "invalid break label %s", quote(name))
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -206,7 +208,7 @@ func (check *Checker) blockBranches(all *Scope, parent *block, lstmt *syntax.Lab
|
|||
}
|
||||
}
|
||||
if !valid {
|
||||
check.errorf(s.Label, MisplacedLabel, "invalid continue label %s", name)
|
||||
check.errorf(s.Label, MisplacedLabel, "invalid continue label %s", quote(name))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
@ -64,7 +64,7 @@ func (check *Checker) usage(scope *Scope) {
|
|||
return cmpPos(unused[i].pos, unused[j].pos) < 0
|
||||
})
|
||||
for _, v := range unused {
|
||||
check.softErrorf(v.pos, UnusedVar, "%s declared and not used", v.name)
|
||||
check.softErrorf(v.pos, UnusedVar, "%s declared and not used", quote(v.name))
|
||||
}
|
||||
|
||||
for _, scope := range scope.children {
|
||||
|
@ -496,7 +496,7 @@ func (check *Checker) stmt(ctxt stmtContext, s syntax.Stmt) {
|
|||
for _, obj := range res.vars {
|
||||
if alt := check.lookup(obj.name); alt != nil && alt != obj {
|
||||
err := check.newError(OutOfScopeResult)
|
||||
err.addf(s, "result parameter %s not in scope at return", obj.name)
|
||||
err.addf(s, "result parameter %s not in scope at return", quote(obj.name))
|
||||
err.addf(alt, "inner declaration of %s", obj)
|
||||
err.report()
|
||||
// ok to continue
|
||||
|
|
|
@ -226,8 +226,8 @@ func computeInterfaceTypeSet(check *Checker, pos syntax.Pos, ityp *Interface) *_
|
|||
case explicit:
|
||||
if check != nil {
|
||||
err := check.newError(DuplicateDecl)
|
||||
err.addf(atPos(pos), "duplicate method %s", m.name)
|
||||
err.addf(atPos(mpos[other.(*Func)]), "other declaration of %s", m.name)
|
||||
err.addf(atPos(pos), "duplicate method %s", quote(m.name))
|
||||
err.addf(atPos(mpos[other.(*Func)]), "other declaration of %s", quote(m.name))
|
||||
err.report()
|
||||
}
|
||||
default:
|
||||
|
@ -240,8 +240,8 @@ func computeInterfaceTypeSet(check *Checker, pos syntax.Pos, ityp *Interface) *_
|
|||
check.later(func() {
|
||||
if pos.IsKnown() && !check.allowVersion(atPos(pos), go1_14) || !Identical(m.typ, other.Type()) {
|
||||
err := check.newError(DuplicateDecl)
|
||||
err.addf(atPos(pos), "duplicate method %s", m.name)
|
||||
err.addf(atPos(mpos[other.(*Func)]), "other declaration of %s", m.name)
|
||||
err.addf(atPos(pos), "duplicate method %s", quote(m.name))
|
||||
err.addf(atPos(mpos[other.(*Func)]), "other declaration of %s", quote(m.name))
|
||||
err.report()
|
||||
}
|
||||
}).describef(atPos(pos), "duplicate method check for %s", m.name)
|
||||
|
|
|
@ -87,7 +87,7 @@ func (check *Checker) ident(x *operand, e *syntax.Name, def *TypeName, wantType
|
|||
|
||||
switch obj := obj.(type) {
|
||||
case *PkgName:
|
||||
check.errorf(e, InvalidPkgUse, "use of package %s not in selector", obj.name)
|
||||
check.errorf(e, InvalidPkgUse, "use of package %s not in selector", quote(obj.name))
|
||||
return
|
||||
|
||||
case *Const:
|
||||
|
@ -109,7 +109,7 @@ func (check *Checker) ident(x *operand, e *syntax.Name, def *TypeName, wantType
|
|||
|
||||
case *TypeName:
|
||||
if !check.enableAlias && check.isBrokenAlias(obj) {
|
||||
check.errorf(e, InvalidDeclCycle, "invalid use of type alias %s in recursive type (see go.dev/issue/50729)", obj.name)
|
||||
check.errorf(e, InvalidDeclCycle, "invalid use of type alias %s in recursive type (see go.dev/issue/50729)", quote(obj.name))
|
||||
return
|
||||
}
|
||||
x.mode = typexpr
|
||||
|
|
|
@ -27,7 +27,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
|
|||
if hasDots(call) && id != _Append {
|
||||
check.errorf(dddErrPos(call),
|
||||
InvalidDotDotDot,
|
||||
invalidOp+"invalid use of ... with built-in %s", bin.name)
|
||||
invalidOp+"invalid use of ... with built-in %s", quote(bin.name))
|
||||
check.use(argList...)
|
||||
return
|
||||
}
|
||||
|
@ -212,7 +212,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
|
|||
if id == _Len {
|
||||
code = InvalidLen
|
||||
}
|
||||
check.errorf(x, code, invalidArg+"%s for %s", x, bin.name)
|
||||
check.errorf(x, code, invalidArg+"%s for %s", x, quote(bin.name))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
@ -535,7 +535,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
|
|||
case _Max, _Min:
|
||||
// max(x, ...)
|
||||
// min(x, ...)
|
||||
check.verifyVersionf(call.Fun, go1_21, bin.name)
|
||||
check.verifyVersionf(call.Fun, go1_21, quote(bin.name))
|
||||
|
||||
op := token.LSS
|
||||
if id == _Max {
|
||||
|
@ -578,7 +578,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
|
|||
if x.mode != constant_ {
|
||||
x.mode = value
|
||||
// A value must not be untyped.
|
||||
check.assignment(x, &emptyInterface, "argument to "+bin.name)
|
||||
check.assignment(x, &emptyInterface, "argument to "+quote(bin.name))
|
||||
if x.mode == invalid {
|
||||
return
|
||||
}
|
||||
|
@ -643,7 +643,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
|
|||
if nargs > 0 {
|
||||
params = make([]Type, nargs)
|
||||
for i, a := range args {
|
||||
check.assignment(a, nil, "argument to "+predeclaredFuncs[id].name)
|
||||
check.assignment(a, nil, "argument to "+quote(predeclaredFuncs[id].name))
|
||||
if a.mode == invalid {
|
||||
return
|
||||
}
|
||||
|
@ -994,7 +994,7 @@ func (check *Checker) applyTypeFunc(f func(Type) Type, x *operand, id builtinId)
|
|||
default:
|
||||
panic("unreachable")
|
||||
}
|
||||
check.softErrorf(x, code, "%s not supported as argument to %s for go1.18 (see go.dev/issue/50937)", x, predeclaredFuncs[id].name)
|
||||
check.softErrorf(x, code, "%s not supported as argument to %s for go1.18 (see go.dev/issue/50937)", x, quote(predeclaredFuncs[id].name))
|
||||
|
||||
// Construct a suitable new type parameter for the result type.
|
||||
// The type parameter is placed in the current package so export/import
|
||||
|
|
|
@ -722,7 +722,7 @@ func (check *Checker) selector(x *operand, e *ast.SelectorExpr, def *TypeName, w
|
|||
goto Error
|
||||
}
|
||||
if !exp.Exported() {
|
||||
check.errorf(e.Sel, UnexportedName, "%s not exported by package %s", sel, pkg.name)
|
||||
check.errorf(e.Sel, UnexportedName, "%s not exported by package %s", quote(sel), quote(pkg.name))
|
||||
// ok to continue
|
||||
}
|
||||
}
|
||||
|
|
|
@ -303,7 +303,7 @@ func (check *Checker) initFiles(files []*ast.File) {
|
|||
check.files = append(check.files, file)
|
||||
|
||||
default:
|
||||
check.errorf(atPos(file.Package), MismatchedPkgName, "package %s; expected %s", name, pkg.name)
|
||||
check.errorf(atPos(file.Package), MismatchedPkgName, "package %s; expected %s", quote(name), quote(pkg.name))
|
||||
// ignore this file
|
||||
}
|
||||
}
|
||||
|
|
|
@ -825,7 +825,7 @@ func (check *Checker) checkFieldUniqueness(base *Named) {
|
|||
// For historical consistency, we report the primary error on the
|
||||
// method, and the alt decl on the field.
|
||||
err := check.newError(DuplicateFieldAndMethod)
|
||||
err.addf(alt, "field and method with the same name %s", fld.name)
|
||||
err.addf(alt, "field and method with the same name %s", quote(fld.name))
|
||||
err.addAltDecl(fld)
|
||||
err.report()
|
||||
}
|
||||
|
|
|
@ -15,6 +15,39 @@ import (
|
|||
"strings"
|
||||
)
|
||||
|
||||
// quote encloses s in `' quotes, as in `foo', except for _,
|
||||
// which is left alone.
|
||||
//
|
||||
// Use to prevent confusion when user supplied names alter the
|
||||
// meaning of an error message.
|
||||
//
|
||||
// For instance, report
|
||||
//
|
||||
// duplicate method `wanted'
|
||||
//
|
||||
// rather than
|
||||
//
|
||||
// duplicate method wanted
|
||||
//
|
||||
// Exceptions:
|
||||
//
|
||||
// - don't quote _:
|
||||
// `_' is ugly and not necessary
|
||||
// - don't quote after a ":" as there's no need for it:
|
||||
// undefined name: foo
|
||||
// - don't quote if the name is used correctly in a statement:
|
||||
// goto L jumps over variable declaration
|
||||
//
|
||||
// quote encloses s in `' quotes, as in `foo',
|
||||
// except for _ which is left alone.
|
||||
func quote(s string) string {
|
||||
if s == "_" {
|
||||
// `_' is ugly and not necessary
|
||||
return s
|
||||
}
|
||||
return "`" + s + "'"
|
||||
}
|
||||
|
||||
func sprintf(fset *token.FileSet, qf Qualifier, tpSubscripts bool, format string, args ...any) string {
|
||||
for i, arg := range args {
|
||||
switch a := arg.(type) {
|
||||
|
|
|
@ -265,13 +265,12 @@ func TestIssue22525(t *testing.T) {
|
|||
got := "\n"
|
||||
conf := Config{Error: func(err error) { got += err.Error() + "\n" }}
|
||||
typecheck(src, &conf, nil) // do not crash
|
||||
want := `
|
||||
p:1:27: a declared and not used
|
||||
p:1:30: b declared and not used
|
||||
p:1:33: c declared and not used
|
||||
p:1:36: d declared and not used
|
||||
p:1:39: e declared and not used
|
||||
`
|
||||
want := "\n" +
|
||||
"p:1:27: `a' declared and not used\n" +
|
||||
"p:1:30: `b' declared and not used\n" +
|
||||
"p:1:33: `c' declared and not used\n" +
|
||||
"p:1:36: `d' declared and not used\n" +
|
||||
"p:1:39: `e' declared and not used\n"
|
||||
if got != want {
|
||||
t.Errorf("got: %swant: %s", got, want)
|
||||
}
|
||||
|
|
|
@ -29,9 +29,11 @@ func (check *Checker) labels(body *ast.BlockStmt) {
|
|||
msg = "goto %s jumps into block"
|
||||
alt.(*Label).used = true // avoid another error
|
||||
code = JumpIntoBlock
|
||||
// don't quote name here because "goto L" matches the code
|
||||
} else {
|
||||
msg = "label %s not declared"
|
||||
code = UndeclaredLabel
|
||||
name = quote(name)
|
||||
}
|
||||
check.errorf(jmp.Label, code, msg, name)
|
||||
}
|
||||
|
@ -40,7 +42,7 @@ func (check *Checker) labels(body *ast.BlockStmt) {
|
|||
for name, obj := range all.elems {
|
||||
obj = resolve(name, obj)
|
||||
if lbl := obj.(*Label); !lbl.used {
|
||||
check.softErrorf(lbl, UnusedLabel, "label %s declared and not used", lbl.name)
|
||||
check.softErrorf(lbl, UnusedLabel, "label %s declared and not used", quote(lbl.name))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -140,7 +142,7 @@ func (check *Checker) blockBranches(all *Scope, parent *block, lstmt *ast.Labele
|
|||
if alt := all.Insert(lbl); alt != nil {
|
||||
err := check.newError(DuplicateLabel)
|
||||
err.soft = true
|
||||
err.addf(lbl, "label %s already declared", name)
|
||||
err.addf(lbl, "label %s already declared", quote(name))
|
||||
err.addAltDecl(alt)
|
||||
err.report()
|
||||
// ok to continue
|
||||
|
@ -196,7 +198,7 @@ func (check *Checker) blockBranches(all *Scope, parent *block, lstmt *ast.Labele
|
|||
}
|
||||
}
|
||||
if !valid {
|
||||
check.errorf(s.Label, MisplacedLabel, "invalid break label %s", name)
|
||||
check.errorf(s.Label, MisplacedLabel, "invalid break label %s", quote(name))
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -211,7 +213,7 @@ func (check *Checker) blockBranches(all *Scope, parent *block, lstmt *ast.Labele
|
|||
}
|
||||
}
|
||||
if !valid {
|
||||
check.errorf(s.Label, MisplacedLabel, "invalid continue label %s", name)
|
||||
check.errorf(s.Label, MisplacedLabel, "invalid continue label %s", quote(name))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
@ -65,7 +65,7 @@ func (check *Checker) usage(scope *Scope) {
|
|||
return cmpPos(unused[i].pos, unused[j].pos) < 0
|
||||
})
|
||||
for _, v := range unused {
|
||||
check.softErrorf(v, UnusedVar, "%s declared and not used", v.name)
|
||||
check.softErrorf(v, UnusedVar, "%s declared and not used", quote(v.name))
|
||||
}
|
||||
|
||||
for _, scope := range scope.children {
|
||||
|
@ -515,7 +515,7 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) {
|
|||
for _, obj := range res.vars {
|
||||
if alt := check.lookup(obj.name); alt != nil && alt != obj {
|
||||
err := check.newError(OutOfScopeResult)
|
||||
err.addf(s, "result parameter %s not in scope at return", obj.name)
|
||||
err.addf(s, "result parameter %s not in scope at return", quote(obj.name))
|
||||
err.addf(alt, "inner declaration of %s", obj)
|
||||
err.report()
|
||||
// ok to continue
|
||||
|
|
|
@ -228,8 +228,8 @@ func computeInterfaceTypeSet(check *Checker, pos token.Pos, ityp *Interface) *_T
|
|||
case explicit:
|
||||
if check != nil {
|
||||
err := check.newError(DuplicateDecl)
|
||||
err.addf(atPos(pos), "duplicate method %s", m.name)
|
||||
err.addf(atPos(mpos[other.(*Func)]), "other declaration of %s", m.name)
|
||||
err.addf(atPos(pos), "duplicate method %s", quote(m.name))
|
||||
err.addf(atPos(mpos[other.(*Func)]), "other declaration of %s", quote(m.name))
|
||||
err.report()
|
||||
}
|
||||
default:
|
||||
|
@ -242,8 +242,8 @@ func computeInterfaceTypeSet(check *Checker, pos token.Pos, ityp *Interface) *_T
|
|||
check.later(func() {
|
||||
if pos.IsValid() && !check.allowVersion(atPos(pos), go1_14) || !Identical(m.typ, other.Type()) {
|
||||
err := check.newError(DuplicateDecl)
|
||||
err.addf(atPos(pos), "duplicate method %s", m.name)
|
||||
err.addf(atPos(mpos[other.(*Func)]), "other declaration of %s", m.name)
|
||||
err.addf(atPos(pos), "duplicate method %s", quote(m.name))
|
||||
err.addf(atPos(mpos[other.(*Func)]), "other declaration of %s", quote(m.name))
|
||||
err.report()
|
||||
}
|
||||
}).describef(atPos(pos), "duplicate method check for %s", m.name)
|
||||
|
|
|
@ -88,7 +88,7 @@ func (check *Checker) ident(x *operand, e *ast.Ident, def *TypeName, wantType bo
|
|||
|
||||
switch obj := obj.(type) {
|
||||
case *PkgName:
|
||||
check.errorf(e, InvalidPkgUse, "use of package %s not in selector", obj.name)
|
||||
check.errorf(e, InvalidPkgUse, "use of package %s not in selector", quote(obj.name))
|
||||
return
|
||||
|
||||
case *Const:
|
||||
|
@ -110,7 +110,7 @@ func (check *Checker) ident(x *operand, e *ast.Ident, def *TypeName, wantType bo
|
|||
|
||||
case *TypeName:
|
||||
if !check.enableAlias && check.isBrokenAlias(obj) {
|
||||
check.errorf(e, InvalidDeclCycle, "invalid use of type alias %s in recursive type (see go.dev/issue/50729)", obj.name)
|
||||
check.errorf(e, InvalidDeclCycle, "invalid use of type alias %s in recursive type (see go.dev/issue/50729)", quote(obj.name))
|
||||
return
|
||||
}
|
||||
x.mode = typexpr
|
||||
|
|
|
@ -100,7 +100,10 @@ func cap1() {
|
|||
|
||||
var s [][]byte
|
||||
_ = cap(s)
|
||||
_ = cap(s... /* ERROR "invalid use of ..." */ )
|
||||
_ = cap(s... /* ERROR "invalid use of ... with built-in `cap'" */ )
|
||||
|
||||
var x int
|
||||
_ = cap(x /* ERROR "invalid argument: x (variable of type int) for `cap'" */ )
|
||||
}
|
||||
|
||||
func cap2() {
|
||||
|
|
2
src/internal/types/testdata/check/decls0.go
vendored
2
src/internal/types/testdata/check/decls0.go
vendored
|
@ -137,7 +137,7 @@ type (
|
|||
}
|
||||
I3 interface {
|
||||
m1()
|
||||
m1 /* ERROR "duplicate method" */ ()
|
||||
m1 /* ERROR "duplicate method `m1'" */ ()
|
||||
}
|
||||
I4 interface {
|
||||
m1(x, y, x /* ERROR "redeclared" */ float32)
|
||||
|
|
|
@ -16,7 +16,7 @@ type T1 struct{
|
|||
|
||||
func (T1) m() {}
|
||||
func (T1) m /* ERROR "already declared" */ () {}
|
||||
func (x *T1) f /* ERROR "field and method" */ () {}
|
||||
func (x *T1) f /* ERROR "field and method with the same name `f'" */ () {}
|
||||
|
||||
// Conflict between embedded field and method name,
|
||||
// with the embedded field being a basic type.
|
||||
|
@ -30,7 +30,7 @@ type T1c struct {
|
|||
time.Time
|
||||
}
|
||||
|
||||
func (T1c) Time /* ERROR "field and method" */ () int { return 0 }
|
||||
func (T1c) Time /* ERROR "field and method with the same name `Time'" */ () int { return 0 }
|
||||
|
||||
// Disabled for now: LookupFieldOrMethod will find Pointer even though
|
||||
// it's double-declared (it would cost extra in the common case to verify
|
||||
|
|
4
src/internal/types/testdata/check/go1_13.go
vendored
4
src/internal/types/testdata/check/go1_13.go
vendored
|
@ -14,10 +14,10 @@ type I interface { m() }
|
|||
|
||||
type _ interface {
|
||||
m()
|
||||
I // ERROR "duplicate method m"
|
||||
I // ERROR "duplicate method `m'"
|
||||
}
|
||||
|
||||
type _ interface {
|
||||
I
|
||||
I // ERROR "duplicate method m"
|
||||
I // ERROR "duplicate method `m'"
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ import f2 "fmt"
|
|||
|
||||
// reflect.flag must not be visible in this package
|
||||
type flag int
|
||||
type _ reflect.flag /* ERROR "not exported" */
|
||||
type _ reflect.flag /* ERROR "`flag' not exported by package `reflect'" */
|
||||
|
||||
// imported package name may conflict with local objects
|
||||
type reflect /* ERROR "reflect already declared" */ int
|
||||
|
|
56
src/internal/types/testdata/check/labels.go
vendored
56
src/internal/types/testdata/check/labels.go
vendored
|
@ -10,23 +10,23 @@ package labels
|
|||
var x int
|
||||
|
||||
func f0() {
|
||||
L1 /* ERROR "label L1 declared and not used" */ :
|
||||
L1 /* ERROR "label `L1' declared and not used" */ :
|
||||
for {
|
||||
}
|
||||
L2 /* ERROR "label L2 declared and not used" */ :
|
||||
L2 /* ERROR "label `L2' declared and not used" */ :
|
||||
select {
|
||||
}
|
||||
L3 /* ERROR "label L3 declared and not used" */ :
|
||||
L3 /* ERROR "label `L3' declared and not used" */ :
|
||||
switch {
|
||||
}
|
||||
L4 /* ERROR "label L4 declared and not used" */ :
|
||||
L4 /* ERROR "label `L4' declared and not used" */ :
|
||||
if true {
|
||||
}
|
||||
L5 /* ERROR "label L5 declared and not used" */ :
|
||||
L5 /* ERROR "label `L5' declared and not used" */ :
|
||||
f0()
|
||||
L6:
|
||||
f0()
|
||||
L6 /* ERROR "label L6 already declared" */ :
|
||||
L6 /* ERROR "label `L6' already declared" */ :
|
||||
f0()
|
||||
if x == 20 {
|
||||
goto L6
|
||||
|
@ -35,7 +35,7 @@ L6 /* ERROR "label L6 already declared" */ :
|
|||
L7:
|
||||
for {
|
||||
break L7
|
||||
break L8 /* ERROR "invalid break label L8" */
|
||||
break L8 /* ERROR "invalid break label `L8'" */
|
||||
}
|
||||
|
||||
// A label must be directly associated with a switch, select, or
|
||||
|
@ -43,8 +43,8 @@ L7:
|
|||
|
||||
L7a /* ERROR "declared and not used" */ : L7b:
|
||||
for {
|
||||
break L7a /* ERROR "invalid break label L7a" */
|
||||
continue L7a /* ERROR "invalid continue label L7a" */
|
||||
break L7a /* ERROR "invalid break label `L7a'" */
|
||||
continue L7a /* ERROR "invalid continue label `L7a'" */
|
||||
continue L7b
|
||||
}
|
||||
|
||||
|
@ -52,7 +52,7 @@ L8:
|
|||
for {
|
||||
if x == 21 {
|
||||
continue L8
|
||||
continue L7 /* ERROR "invalid continue label L7" */
|
||||
continue L7 /* ERROR "invalid continue label `L7'" */
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -60,23 +60,23 @@ L9:
|
|||
switch {
|
||||
case true:
|
||||
break L9
|
||||
defalt /* ERROR "label defalt declared and not used" */ :
|
||||
defalt /* ERROR "label `defalt' declared and not used" */ :
|
||||
}
|
||||
|
||||
L10:
|
||||
select {
|
||||
default:
|
||||
break L10
|
||||
break L9 /* ERROR "invalid break label L9" */
|
||||
break L9 /* ERROR "invalid break label `L9'" */
|
||||
}
|
||||
|
||||
goto L10a
|
||||
L10a: L10b:
|
||||
select {
|
||||
default:
|
||||
break L10a /* ERROR "invalid break label L10a" */
|
||||
break L10a /* ERROR "invalid break label `L10a'" */
|
||||
break L10b
|
||||
continue L10b /* ERROR "invalid continue label L10b" */
|
||||
continue L10b /* ERROR "invalid continue label `L10b'" */
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -99,7 +99,7 @@ L2:
|
|||
break L2
|
||||
}
|
||||
if x == 1 {
|
||||
continue L2 /* ERROR "invalid continue label L2" */
|
||||
continue L2 /* ERROR "invalid continue label `L2'" */
|
||||
}
|
||||
goto L2
|
||||
}
|
||||
|
@ -111,7 +111,7 @@ L3:
|
|||
break L3
|
||||
}
|
||||
if x == 12 {
|
||||
continue L3 /* ERROR "invalid continue label L3" */
|
||||
continue L3 /* ERROR "invalid continue label `L3'" */
|
||||
}
|
||||
goto L3
|
||||
}
|
||||
|
@ -119,10 +119,10 @@ L3:
|
|||
L4:
|
||||
if true {
|
||||
if x == 13 {
|
||||
break L4 /* ERROR "invalid break label L4" */
|
||||
break L4 /* ERROR "invalid break label `L4'" */
|
||||
}
|
||||
if x == 14 {
|
||||
continue L4 /* ERROR "invalid continue label L4" */
|
||||
continue L4 /* ERROR "invalid continue label `L4'" */
|
||||
}
|
||||
if x == 15 {
|
||||
goto L4
|
||||
|
@ -132,10 +132,10 @@ L4:
|
|||
L5:
|
||||
f1()
|
||||
if x == 16 {
|
||||
break L5 /* ERROR "invalid break label L5" */
|
||||
break L5 /* ERROR "invalid break label `L5'" */
|
||||
}
|
||||
if x == 17 {
|
||||
continue L5 /* ERROR "invalid continue label L5" */
|
||||
continue L5 /* ERROR "invalid continue label `L5'" */
|
||||
}
|
||||
if x == 18 {
|
||||
goto L5
|
||||
|
@ -143,10 +143,10 @@ L5:
|
|||
|
||||
for {
|
||||
if x == 19 {
|
||||
break L1 /* ERROR "invalid break label L1" */
|
||||
break L1 /* ERROR "invalid break label `L1'" */
|
||||
}
|
||||
if x == 20 {
|
||||
continue L1 /* ERROR "invalid continue label L1" */
|
||||
continue L1 /* ERROR "invalid continue label `L1'" */
|
||||
}
|
||||
if x == 21 {
|
||||
goto L1
|
||||
|
@ -157,10 +157,10 @@ L5:
|
|||
// Additional tests not in the original files.
|
||||
|
||||
func f2() {
|
||||
L1 /* ERROR "label L1 declared and not used" */ :
|
||||
L1 /* ERROR "label `L1' declared and not used" */ :
|
||||
if x == 0 {
|
||||
for {
|
||||
continue L1 /* ERROR "invalid continue label L1" */
|
||||
continue L1 /* ERROR "invalid continue label `L1'" */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -170,11 +170,11 @@ L1:
|
|||
L2:
|
||||
L3:
|
||||
for {
|
||||
break L1 /* ERROR "invalid break label L1" */
|
||||
break L2 /* ERROR "invalid break label L2" */
|
||||
break L1 /* ERROR "invalid break label `L1'" */
|
||||
break L2 /* ERROR "invalid break label `L2'" */
|
||||
break L3
|
||||
continue L1 /* ERROR "invalid continue label L1" */
|
||||
continue L2 /* ERROR "invalid continue label L2" */
|
||||
continue L1 /* ERROR "invalid continue label `L1'" */
|
||||
continue L2 /* ERROR "invalid continue label `L2'" */
|
||||
continue L3
|
||||
goto L1
|
||||
goto L2
|
||||
|
|
4
src/internal/types/testdata/check/stmt0.go
vendored
4
src/internal/types/testdata/check/stmt0.go
vendored
|
@ -222,7 +222,7 @@ func selects() {
|
|||
ch2 := make(chan int)
|
||||
select {
|
||||
case <-ch1:
|
||||
var ch2 /* ERROR "ch2 declared and not used" */ chan bool
|
||||
var ch2 /* ERROR "`ch2' declared and not used" */ chan bool
|
||||
case i := <-ch2:
|
||||
print(i + 1)
|
||||
}
|
||||
|
@ -394,7 +394,7 @@ func returns2() (a, b int) {
|
|||
{
|
||||
type a int
|
||||
return 1, 2
|
||||
return /* ERROR "a not in scope at return" */
|
||||
return /* ERROR "`a' not in scope at return" */
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ type R[S any, P any] struct{}
|
|||
type SR = R[SS, ST]
|
||||
|
||||
type SS interface {
|
||||
NSR(any) *SR // ERROR "invalid use of type alias SR in recursive type"
|
||||
NSR(any) *SR // ERROR "invalid use of type alias `SR' in recursive type"
|
||||
}
|
||||
|
||||
type C interface {
|
||||
|
|
|
@ -19,7 +19,7 @@ import "io"
|
|||
|
||||
type _ interface {
|
||||
Reader
|
||||
Reader // ERROR "duplicate method Read"
|
||||
Reader // ERROR "duplicate method `Read'"
|
||||
}
|
||||
|
||||
type Reader interface {
|
||||
|
@ -28,10 +28,10 @@ type Reader interface {
|
|||
|
||||
type _ interface {
|
||||
io.Reader
|
||||
Reader // ERROR "duplicate method Read"
|
||||
Reader // ERROR "duplicate method `Read'"
|
||||
}
|
||||
|
||||
type _ interface {
|
||||
io.Reader
|
||||
io /* ERROR "duplicate method Read" */ .Reader
|
||||
io /* ERROR "duplicate method `Read'" */ .Reader
|
||||
}
|
||||
|
|
|
@ -8,4 +8,4 @@ package a
|
|||
|
||||
import "fmt" // GC_ERROR "imported and not used"
|
||||
|
||||
const n = fmt // ERROR "fmt without selector|unexpected reference to package|use of package fmt not in selector"
|
||||
const n = fmt // ERROR "fmt without selector|unexpected reference to package|use of package `fmt' not in selector"
|
||||
|
|
|
@ -45,8 +45,8 @@ func main() {
|
|||
log.Fatalf("expected cmd/compile to fail")
|
||||
}
|
||||
wantErrs := []string{
|
||||
"7:9: n declared and not used",
|
||||
"7:12: err declared and not used",
|
||||
"7:9: `n' declared and not used",
|
||||
"7:12: `err' declared and not used",
|
||||
}
|
||||
outStr := string(out)
|
||||
for _, want := range wantErrs {
|
||||
|
|
|
@ -16,8 +16,8 @@ type T struct {
|
|||
|
||||
type E struct{}
|
||||
|
||||
func (T) b() {} // ERROR "field and method named b|redeclares struct field name|field and method with the same name b"
|
||||
func (*T) E() {} // ERROR "field and method named E|redeclares struct field name|field and method with the same name E"
|
||||
func (T) b() {} // ERROR "field and method named b|redeclares struct field name|field and method with the same name `b'"
|
||||
func (*T) E() {} // ERROR "field and method named E|redeclares struct field name|field and method with the same name `E'"
|
||||
|
||||
func _() {
|
||||
var x T
|
||||
|
|
|
@ -10,5 +10,5 @@ type I interface { M() }
|
|||
|
||||
type _ interface {
|
||||
I
|
||||
I // ERROR "duplicate method M"
|
||||
I // ERROR "duplicate method `M'"
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue