mirror of
https://github.com/golang/go.git
synced 2026-02-07 03:15:05 +03:00
go/types,cmd/compile/internal/types2: better diagnostic for type shadowing
This change causes the "x is not a type" diagnostic to describe x's actual kind, helping to reveal when shadowing is at work. (The kind description could improve other errors too.) Fixes #76877 Change-Id: Ia3484998bb384ff570c20b6792cf8461c60aa38c Reviewed-on: https://go-review.googlesource.com/c/go/+/731180 Reviewed-by: Robert Griesemer <gri@google.com> Auto-Submit: Alan Donovan <adonovan@google.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:
committed by
Gopher Robot
parent
bb7c0c717c
commit
532e320349
@@ -671,3 +671,52 @@ func writeFuncName(buf *bytes.Buffer, f *Func, qf Qualifier) {
|
||||
}
|
||||
buf.WriteString(f.name)
|
||||
}
|
||||
|
||||
// objectKind returns a description of the object's kind.
|
||||
func objectKind(obj Object) string {
|
||||
switch obj := obj.(type) {
|
||||
case *PkgName:
|
||||
return "package name"
|
||||
case *Const:
|
||||
return "constant"
|
||||
case *TypeName:
|
||||
if obj.IsAlias() {
|
||||
return "type alias"
|
||||
} else if _, ok := obj.Type().(*TypeParam); ok {
|
||||
return "type parameter"
|
||||
} else {
|
||||
return "defined type"
|
||||
}
|
||||
case *Var:
|
||||
switch obj.Kind() {
|
||||
case PackageVar:
|
||||
return "package-level variable"
|
||||
case LocalVar:
|
||||
return "local variable"
|
||||
case RecvVar:
|
||||
return "receiver"
|
||||
case ParamVar:
|
||||
return "parameter"
|
||||
case ResultVar:
|
||||
return "result variable"
|
||||
case FieldVar:
|
||||
return "struct field"
|
||||
}
|
||||
case *Func:
|
||||
if obj.Signature().Recv() != nil {
|
||||
return "method"
|
||||
} else {
|
||||
return "function"
|
||||
}
|
||||
case *Label:
|
||||
return "label"
|
||||
case *Builtin:
|
||||
return "built-in function"
|
||||
case *Nil:
|
||||
return "untyped nil"
|
||||
}
|
||||
if debug {
|
||||
panic(fmt.Sprintf("unknown symbol (%T)", obj))
|
||||
}
|
||||
return "unknown symbol"
|
||||
}
|
||||
|
||||
@@ -50,7 +50,8 @@ func (check *Checker) ident(x *operand, e *syntax.Name, wantType bool) {
|
||||
// (see go.dev/issue/65344).
|
||||
_, gotType := obj.(*TypeName)
|
||||
if !gotType && wantType {
|
||||
check.errorf(e, NotAType, "%s is not a type", obj.Name())
|
||||
check.errorf(e, NotAType, "%s (%s) is not a type", obj.Name(), objectKind(obj))
|
||||
|
||||
// avoid "declared but not used" errors
|
||||
// (don't use Checker.use - we don't want to evaluate too much)
|
||||
if v, _ := obj.(*Var); v != nil && v.pkg == check.pkg /* see Checker.use1 */ {
|
||||
|
||||
@@ -674,3 +674,52 @@ func writeFuncName(buf *bytes.Buffer, f *Func, qf Qualifier) {
|
||||
}
|
||||
buf.WriteString(f.name)
|
||||
}
|
||||
|
||||
// objectKind returns a description of the object's kind.
|
||||
func objectKind(obj Object) string {
|
||||
switch obj := obj.(type) {
|
||||
case *PkgName:
|
||||
return "package name"
|
||||
case *Const:
|
||||
return "constant"
|
||||
case *TypeName:
|
||||
if obj.IsAlias() {
|
||||
return "type alias"
|
||||
} else if _, ok := obj.Type().(*TypeParam); ok {
|
||||
return "type parameter"
|
||||
} else {
|
||||
return "defined type"
|
||||
}
|
||||
case *Var:
|
||||
switch obj.Kind() {
|
||||
case PackageVar:
|
||||
return "package-level variable"
|
||||
case LocalVar:
|
||||
return "local variable"
|
||||
case RecvVar:
|
||||
return "receiver"
|
||||
case ParamVar:
|
||||
return "parameter"
|
||||
case ResultVar:
|
||||
return "result variable"
|
||||
case FieldVar:
|
||||
return "struct field"
|
||||
}
|
||||
case *Func:
|
||||
if obj.Signature().Recv() != nil {
|
||||
return "method"
|
||||
} else {
|
||||
return "function"
|
||||
}
|
||||
case *Label:
|
||||
return "label"
|
||||
case *Builtin:
|
||||
return "built-in function"
|
||||
case *Nil:
|
||||
return "untyped nil"
|
||||
}
|
||||
if debug {
|
||||
panic(fmt.Sprintf("unknown symbol (%T)", obj))
|
||||
}
|
||||
return "unknown symbol"
|
||||
}
|
||||
|
||||
@@ -49,7 +49,8 @@ func (check *Checker) ident(x *operand, e *ast.Ident, wantType bool) {
|
||||
// (see go.dev/issue/65344).
|
||||
_, gotType := obj.(*TypeName)
|
||||
if !gotType && wantType {
|
||||
check.errorf(e, NotAType, "%s is not a type", obj.Name())
|
||||
check.errorf(e, NotAType, "%s (%s) is not a type", obj.Name(), objectKind(obj))
|
||||
|
||||
// avoid "declared but not used" errors
|
||||
// (don't use Checker.use - we don't want to evaluate too much)
|
||||
if v, _ := obj.(*Var); v != nil && v.pkg == check.pkg /* see Checker.use1 */ {
|
||||
|
||||
2
src/internal/types/testdata/check/cycles5.go
vendored
2
src/internal/types/testdata/check/cycles5.go
vendored
@@ -162,7 +162,7 @@ func makeArray() (res T12) { return }
|
||||
|
||||
// issue #20770
|
||||
var r = newReader()
|
||||
func newReader() r // ERROR "r is not a type"
|
||||
func newReader() r // ERROR "r (package-level variable) is not a type"
|
||||
|
||||
// variations of the theme of #8699 and #20770
|
||||
var arr /* ERROR "cycle" */ = f()
|
||||
|
||||
@@ -162,7 +162,7 @@ func makeArray() (res T12) { return }
|
||||
|
||||
// issue #20770
|
||||
var r = newReader()
|
||||
func newReader() r // ERROR "r is not a type"
|
||||
func newReader() r // ERROR "r (package-level variable) is not a type"
|
||||
|
||||
// variations of the theme of #8699 and #20770
|
||||
var arr /* ERROR "cycle" */ = f()
|
||||
|
||||
9
src/internal/types/testdata/check/decls1.go
vendored
9
src/internal/types/testdata/check/decls1.go
vendored
@@ -63,7 +63,7 @@ var (
|
||||
t12 complex64 = -(u + *t11) / *&v
|
||||
t13 int = a /* ERROR "shifted operand" */ << d
|
||||
t14 int = i << j
|
||||
t15 math /* ERROR "math is not a type" */
|
||||
t15 math /* ERROR "math (package name) is not a type" */
|
||||
t16 math.xxx /* ERROR "undefined" */
|
||||
t17 math /* ERROR "not a type" */ .Pi
|
||||
t18 float64 = math.Pi * 10.0
|
||||
@@ -144,3 +144,10 @@ func init /* ERROR "no arguments and no return values" */ (int) {}
|
||||
func init /* ERROR "no arguments and no return values" */ () int { return 0 }
|
||||
func init /* ERROR "no arguments and no return values" */ (int) int { return 0 }
|
||||
func (T) init(int) int { return 0 }
|
||||
|
||||
func _() {
|
||||
var error error
|
||||
var _ error /* ERROR "error (local variable) is not a type" */
|
||||
_ = error
|
||||
}
|
||||
|
||||
|
||||
2
src/internal/types/testdata/check/issues0.go
vendored
2
src/internal/types/testdata/check/issues0.go
vendored
@@ -104,7 +104,7 @@ func issue10979() {
|
||||
|
||||
// issue11347
|
||||
// These should not crash.
|
||||
var a1, b1, c1 /* ERROR "cycle" */ b1 /* ERROR "b1 is not a type" */ = 0 > 0<<""[""[c1]]>c1
|
||||
var a1, b1, c1 /* ERROR "cycle" */ b1 /* ERROR "b1 (package-level variable) is not a type" */ = 0 > 0<<""[""[c1]]>c1
|
||||
var a2, b2 /* ERROR "cycle" */ = 0 /* ERROR "assignment mismatch" */ /* ERROR "assignment mismatch" */ > 0<<""[b2]
|
||||
var a3, b3 /* ERROR "cycle" */ = int /* ERROR "assignment mismatch" */ /* ERROR "assignment mismatch" */ (1<<""[b3])
|
||||
|
||||
|
||||
2
src/internal/types/testdata/check/issues1.go
vendored
2
src/internal/types/testdata/check/issues1.go
vendored
@@ -246,5 +246,5 @@ var _ = append[context.CancelFunc, []context.CancelFunc, context.CancelFunc](can
|
||||
func g[T any](T) T { panic(0) }
|
||||
|
||||
var _ = g[int]
|
||||
var _ = g[nil /* ERROR "is not a type" */ ]
|
||||
var _ = g[nil /* ERROR "nil (untyped nil) is not a type" */ ]
|
||||
var _ = g(0)
|
||||
|
||||
@@ -43,7 +43,7 @@ type foo9[A any] interface { foo9 /* ERROR "invalid recursive type" */ [A] }
|
||||
func _() { var _ = new(foo9[int]) }
|
||||
|
||||
// crash 12
|
||||
var u, i [func /* ERROR "used as value" */ /* ERROR "used as value" */ (u /* ERROR "u is not a type" */ /* ERROR "u is not a type" */ , c /* ERROR "undefined" */ /* ERROR "undefined" */ ) {}(0, len /* ERROR "must be called" */ /* ERROR "must be called" */ )]c /* ERROR "undefined" */ /* ERROR "undefined" */
|
||||
var u, i [func /* ERROR "used as value" */ /* ERROR "used as value" */ (u /* ERROR "u (package-level variable) is not a type" */ /* ERROR "u (package-level variable) is not a type" */ , c /* ERROR "undefined" */ /* ERROR "undefined" */ ) {}(0, len /* ERROR "must be called" */ /* ERROR "must be called" */ )]c /* ERROR "undefined" */ /* ERROR "undefined" */
|
||||
|
||||
// crash 15
|
||||
func y15() { var a /* ERROR "declared and not used" */ interface{ p() } = G15[string]{} }
|
||||
|
||||
@@ -4,12 +4,12 @@
|
||||
|
||||
package p
|
||||
|
||||
type T1 C /* ERROR "C is not a type" */
|
||||
type T1 C /* ERROR "C (constant) is not a type" */
|
||||
|
||||
// TODO(gri) try to avoid this follow-on error
|
||||
const C = T1(0 /* ERROR "cannot convert 0 (untyped int constant) to type T1" */)
|
||||
|
||||
type T2 V /* ERROR "V is not a type" */
|
||||
type T2 V /* ERROR "V (package-level variable) is not a type" */
|
||||
|
||||
var V T2
|
||||
|
||||
|
||||
@@ -14,4 +14,3 @@ func main() {
|
||||
var foo bar
|
||||
_ = &foo{} // ERROR "is not a type|expected .;."
|
||||
} // GCCGO_ERROR "expected declaration"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user