]> Cypherpunks repositories - gostls13.git/commitdiff
go/types,cmd/compile/internal/types2: better diagnostic for type shadowing
authorAlan Donovan <adonovan@google.com>
Thu, 18 Dec 2025 17:27:11 +0000 (12:27 -0500)
committerGopher Robot <gobot@golang.org>
Thu, 15 Jan 2026 23:10:27 +0000 (15:10 -0800)
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>

12 files changed:
src/cmd/compile/internal/types2/object.go
src/cmd/compile/internal/types2/typexpr.go
src/go/types/object.go
src/go/types/typexpr.go
src/internal/types/testdata/check/cycles5.go
src/internal/types/testdata/check/cycles5a.go
src/internal/types/testdata/check/decls1.go
src/internal/types/testdata/check/issues0.go
src/internal/types/testdata/check/issues1.go
src/internal/types/testdata/fixedbugs/issue39634.go
src/internal/types/testdata/fixedbugs/issue65344.go
test/fixedbugs/issue4610.go

index dd2d41579086e4aff9d46743f6142cce3f05a324..5d284ee61bf968b3664cc38c5b871bf353067b57 100644 (file)
@@ -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"
+}
index a79b54eaccf8a86fb657448e707d66e28a901808..7d5932eec17f91c85e38a5e0145eda4475989d3b 100644 (file)
@@ -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 */ {
index 57158c1595fa8a835dcf2be1e7cb56ffe2c55474..e12bf7285afc8fcf7ad497d5786528e8c605e6f0 100644 (file)
@@ -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"
+}
index 346ff18e9ad7de195ab20761b15366f03c970971..549c30748701ee0ddccad2ec2e6265fc2997911b 100644 (file)
@@ -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 */ {
index de85c03d8a3d9f4324455d9048bb85bc2af34746..9605f8ded4489a595ffaaa2c1ba6e54ade46071f 100644 (file)
@@ -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()
index e10f554e5c0120fe5d307c5ccfbe329aa0d96631..a8cad50243a727af9670b534fb54c3a7995f583e 100644 (file)
@@ -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()
index 6cdbf27f4c2c18c4ffffd30c2fe9fecdd7ffa189..5e4ba86cb080d6ff1ee1b661b81e41da4b5724de 100644 (file)
@@ -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
+}
+
index 6117f7a8b9c80a8c50e0bc0e0f2ff00f7f27f8ba..fb4e1282f920afed68eebd5faa9174755406efe8 100644 (file)
@@ -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])
 
index 72c6cf775746ed968ae5af68db95f3087303dfac..482bdb08e1c11a74c76cc4274271ee52040cc4b0 100644 (file)
@@ -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)
index 58fc43eea647e163b0aaf6e554e60df8e63e19a8..5392f903c2b8686e9d43ffb786139e72c8631586 100644 (file)
@@ -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]{} }
index 9f8337cf2b96fc3870bf8e85bcd8204a835de371..4db97c04ffb372c89a3879500698c0dde5bf81c0 100644 (file)
@@ -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
 
index d56c6d3e8cd899ffd8ad167f2b50815c7ef09545..8993f9882bd841d97caddfc7f4c85f536306ecf4 100644 (file)
@@ -14,4 +14,3 @@ func main() {
        var foo bar
        _ = &foo{} // ERROR "is not a type|expected .;."
 } // GCCGO_ERROR "expected declaration"
-