]> Cypherpunks repositories - gostls13.git/commitdiff
go/types, types2: qualify named types in error messages with type kind
authorRobert Griesemer <gri@golang.org>
Tue, 22 Oct 2024 18:48:38 +0000 (11:48 -0700)
committerGopher Robot <gobot@golang.org>
Wed, 23 Oct 2024 04:43:01 +0000 (04:43 +0000)
Change the description of an operand x that has a named type of sorts
by providing a description of the type structure (array, struct, slice,
pointer, etc).

For instance, given a (variable) operand x of a struct type T, the
operand is mentioned as (new):

        x (variable of struct type T)

instead of (old):

        x (variable of type T)

This approach is also used when a basic type is renamed, for instance
as in:

        x (value of uint type big.Word)

which makes it clear that big.Word is a uint.

This change is expected to produce more informative error messages.

Fixes #69955.

Change-Id: I544b0698f753a522c3b6e1800a492a94974fbab7
Reviewed-on: https://go-review.googlesource.com/c/go/+/621458
Reviewed-by: Alan Donovan <adonovan@google.com>
Auto-Submit: Robert Griesemer <gri@google.com>
Reviewed-by: Robert Griesemer <gri@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>

15 files changed:
src/cmd/compile/internal/types2/issues_test.go
src/cmd/compile/internal/types2/operand.go
src/go/types/issues_test.go
src/go/types/operand.go
src/internal/types/testdata/check/builtins0.go
src/internal/types/testdata/check/errors.go
src/internal/types/testdata/check/issues0.go
src/internal/types/testdata/fixedbugs/issue49005.go
src/internal/types/testdata/fixedbugs/issue60377.go
src/internal/types/testdata/fixedbugs/issue62157.go
src/internal/types/testdata/fixedbugs/issue69955.go [new file with mode: 0644]
src/internal/types/testdata/spec/range.go
src/internal/types/testdata/spec/range_int.go
test/alias2.go
test/fixedbugs/issue48471.go

index 57cb3b9257bbebf8dcf5ce7995e76f762f55ac26..317a5f80c83a6652a14828d73c51c8043eb5b708 100644 (file)
@@ -729,7 +729,7 @@ var _ I0 = b.S{}
 type S struct{}
 func (S) M0(struct{ f string }) {}
 `,
-                       `6:12: cannot use b[.]S{} [(]value of type b[.]S[)] as I0 value in variable declaration: b[.]S does not implement I0 [(]wrong type for method M0[)]
+                       `6:12: cannot use b[.]S{} [(]value of struct type b[.]S[)] as I0 value in variable declaration: b[.]S does not implement I0 [(]wrong type for method M0[)]
 .*have M0[(]struct{f string /[*] package b [*]/ }[)]
 .*want M0[(]struct{f string /[*] package main [*]/ }[)]`},
 
@@ -745,7 +745,7 @@ var _ I1 = b.S{}
 type S struct{}
 func (S) M1(struct{ string }) {}
 `,
-                       `6:12: cannot use b[.]S{} [(]value of type b[.]S[)] as I1 value in variable declaration: b[.]S does not implement I1 [(]wrong type for method M1[)]
+                       `6:12: cannot use b[.]S{} [(]value of struct type b[.]S[)] as I1 value in variable declaration: b[.]S does not implement I1 [(]wrong type for method M1[)]
 .*have M1[(]struct{string /[*] package b [*]/ }[)]
 .*want M1[(]struct{string /[*] package main [*]/ }[)]`},
 
@@ -761,7 +761,7 @@ var _ I2 = b.S{}
 type S struct{}
 func (S) M2(struct{ f struct{ f string } }) {}
 `,
-                       `6:12: cannot use b[.]S{} [(]value of type b[.]S[)] as I2 value in variable declaration: b[.]S does not implement I2 [(]wrong type for method M2[)]
+                       `6:12: cannot use b[.]S{} [(]value of struct type b[.]S[)] as I2 value in variable declaration: b[.]S does not implement I2 [(]wrong type for method M2[)]
 .*have M2[(]struct{f struct{f string} /[*] package b [*]/ }[)]
 .*want M2[(]struct{f struct{f string} /[*] package main [*]/ }[)]`},
 
@@ -777,7 +777,7 @@ var _ I3 = b.S{}
 type S struct{}
 func (S) M3(struct{ F struct{ f string } }) {}
 `,
-                       `6:12: cannot use b[.]S{} [(]value of type b[.]S[)] as I3 value in variable declaration: b[.]S does not implement I3 [(]wrong type for method M3[)]
+                       `6:12: cannot use b[.]S{} [(]value of struct type b[.]S[)] as I3 value in variable declaration: b[.]S does not implement I3 [(]wrong type for method M3[)]
 .*have M3[(]struct{F struct{f string /[*] package b [*]/ }}[)]
 .*want M3[(]struct{F struct{f string /[*] package main [*]/ }}[)]`},
 
@@ -793,7 +793,7 @@ var _ I4 = b.S{}
 type S struct{}
 func (S) M4(struct { *string }) {}
 `,
-                       `6:12: cannot use b[.]S{} [(]value of type b[.]S[)] as I4 value in variable declaration: b[.]S does not implement I4 [(]wrong type for method M4[)]
+                       `6:12: cannot use b[.]S{} [(]value of struct type b[.]S[)] as I4 value in variable declaration: b[.]S does not implement I4 [(]wrong type for method M4[)]
 .*have M4[(]struct{[*]string /[*] package b [*]/ }[)]
 .*want M4[(]struct{[*]string /[*] package main [*]/ }[)]`},
 
@@ -811,7 +811,7 @@ type S struct{}
 type t struct{ A int }
 func (S) M5(struct {S;t}) {}
 `,
-                       `7:12: cannot use b[.]S{} [(]value of type b[.]S[)] as I5 value in variable declaration: b[.]S does not implement I5 [(]wrong type for method M5[)]
+                       `7:12: cannot use b[.]S{} [(]value of struct type b[.]S[)] as I5 value in variable declaration: b[.]S does not implement I5 [(]wrong type for method M5[)]
 .*have M5[(]struct{b[.]S; b[.]t}[)]
 .*want M5[(]struct{b[.]S; t}[)]`},
        }
index 1ee0f499f629273913cd5c290965bee32e422ba4..81f46af535152b2dc9460591f1bec25a9ec57541 100644 (file)
@@ -178,15 +178,33 @@ func operandString(x *operand, qf Qualifier) string {
        // <typ>
        if hasType {
                if isValid(x.typ) {
-                       var intro string
+                       var desc string
                        if isGeneric(x.typ) {
-                               intro = " of generic type "
-                       } else {
-                               intro = " of type "
+                               desc = "generic "
                        }
-                       buf.WriteString(intro)
+
+                       // Describe the type structure if it is an *Alias or *Named type.
+                       // If the type is a renamed basic type, describe the basic type,
+                       // as in "int32 type MyInt" for a *Named type MyInt.
+                       // If it is a type parameter, describe the constraint instead.
+                       tpar, _ := Unalias(x.typ).(*TypeParam)
+                       if tpar == nil {
+                               switch x.typ.(type) {
+                               case *Alias, *Named:
+                                       what := compositeKind(x.typ)
+                                       if what == "" {
+                                               // x.typ must be basic type
+                                               what = under(x.typ).(*Basic).name
+                                       }
+                                       desc += what + " "
+                               }
+                       }
+                       // desc is "" or has a trailing space at the end
+
+                       buf.WriteString(" of " + desc + "type ")
                        WriteType(&buf, x.typ, qf)
-                       if tpar, _ := Unalias(x.typ).(*TypeParam); tpar != nil {
+
+                       if tpar != nil {
                                buf.WriteString(" constrained by ")
                                WriteType(&buf, tpar.bound, qf) // do not compute interface type sets here
                                // If we have the type set and it's empty, say so for better error messages.
index 9fc650df7cdd259a3de81329b71a22aad0d23e44..5a55822abad5f3aa5ee67e3dedd153f3fb8f4311 100644 (file)
@@ -737,7 +737,7 @@ var _ I0 = b.S{}
 type S struct{}
 func (S) M0(struct{ f string }) {}
 `,
-                       `6:12: cannot use b[.]S{} [(]value of type b[.]S[)] as I0 value in variable declaration: b[.]S does not implement I0 [(]wrong type for method M0[)]
+                       `6:12: cannot use b[.]S{} [(]value of struct type b[.]S[)] as I0 value in variable declaration: b[.]S does not implement I0 [(]wrong type for method M0[)]
 .*have M0[(]struct{f string /[*] package b [*]/ }[)]
 .*want M0[(]struct{f string /[*] package main [*]/ }[)]`},
 
@@ -753,7 +753,7 @@ var _ I1 = b.S{}
 type S struct{}
 func (S) M1(struct{ string }) {}
 `,
-                       `6:12: cannot use b[.]S{} [(]value of type b[.]S[)] as I1 value in variable declaration: b[.]S does not implement I1 [(]wrong type for method M1[)]
+                       `6:12: cannot use b[.]S{} [(]value of struct type b[.]S[)] as I1 value in variable declaration: b[.]S does not implement I1 [(]wrong type for method M1[)]
 .*have M1[(]struct{string /[*] package b [*]/ }[)]
 .*want M1[(]struct{string /[*] package main [*]/ }[)]`},
 
@@ -769,7 +769,7 @@ var _ I2 = b.S{}
 type S struct{}
 func (S) M2(struct{ f struct{ f string } }) {}
 `,
-                       `6:12: cannot use b[.]S{} [(]value of type b[.]S[)] as I2 value in variable declaration: b[.]S does not implement I2 [(]wrong type for method M2[)]
+                       `6:12: cannot use b[.]S{} [(]value of struct type b[.]S[)] as I2 value in variable declaration: b[.]S does not implement I2 [(]wrong type for method M2[)]
 .*have M2[(]struct{f struct{f string} /[*] package b [*]/ }[)]
 .*want M2[(]struct{f struct{f string} /[*] package main [*]/ }[)]`},
 
@@ -785,7 +785,7 @@ var _ I3 = b.S{}
 type S struct{}
 func (S) M3(struct{ F struct{ f string } }) {}
 `,
-                       `6:12: cannot use b[.]S{} [(]value of type b[.]S[)] as I3 value in variable declaration: b[.]S does not implement I3 [(]wrong type for method M3[)]
+                       `6:12: cannot use b[.]S{} [(]value of struct type b[.]S[)] as I3 value in variable declaration: b[.]S does not implement I3 [(]wrong type for method M3[)]
 .*have M3[(]struct{F struct{f string /[*] package b [*]/ }}[)]
 .*want M3[(]struct{F struct{f string /[*] package main [*]/ }}[)]`},
 
@@ -801,7 +801,7 @@ var _ I4 = b.S{}
 type S struct{}
 func (S) M4(struct { *string }) {}
 `,
-                       `6:12: cannot use b[.]S{} [(]value of type b[.]S[)] as I4 value in variable declaration: b[.]S does not implement I4 [(]wrong type for method M4[)]
+                       `6:12: cannot use b[.]S{} [(]value of struct type b[.]S[)] as I4 value in variable declaration: b[.]S does not implement I4 [(]wrong type for method M4[)]
 .*have M4[(]struct{[*]string /[*] package b [*]/ }[)]
 .*want M4[(]struct{[*]string /[*] package main [*]/ }[)]`},
 
@@ -819,7 +819,7 @@ type S struct{}
 type t struct{ A int }
 func (S) M5(struct {S;t}) {}
 `,
-                       `7:12: cannot use b[.]S{} [(]value of type b[.]S[)] as I5 value in variable declaration: b[.]S does not implement I5 [(]wrong type for method M5[)]
+                       `7:12: cannot use b[.]S{} [(]value of struct type b[.]S[)] as I5 value in variable declaration: b[.]S does not implement I5 [(]wrong type for method M5[)]
 .*have M5[(]struct{b[.]S; b[.]t}[)]
 .*want M5[(]struct{b[.]S; t}[)]`},
        }
index b6e0566b1a4073430f5464419e4d76c747786c5f..d933c173ff60eebc46bf7b045c962c9066d86559 100644 (file)
@@ -182,15 +182,33 @@ func operandString(x *operand, qf Qualifier) string {
        // <typ>
        if hasType {
                if isValid(x.typ) {
-                       var intro string
+                       var desc string
                        if isGeneric(x.typ) {
-                               intro = " of generic type "
-                       } else {
-                               intro = " of type "
+                               desc = "generic "
                        }
-                       buf.WriteString(intro)
+
+                       // Describe the type structure if it is an *Alias or *Named type.
+                       // If the type is a renamed basic type, describe the basic type,
+                       // as in "int32 type MyInt" for a *Named type MyInt.
+                       // If it is a type parameter, describe the constraint instead.
+                       tpar, _ := Unalias(x.typ).(*TypeParam)
+                       if tpar == nil {
+                               switch x.typ.(type) {
+                               case *Alias, *Named:
+                                       what := compositeKind(x.typ)
+                                       if what == "" {
+                                               // x.typ must be basic type
+                                               what = under(x.typ).(*Basic).name
+                                       }
+                                       desc += what + " "
+                               }
+                       }
+                       // desc is "" or has a trailing space at the end
+
+                       buf.WriteString(" of " + desc + "type ")
                        WriteType(&buf, x.typ, qf)
-                       if tpar, _ := Unalias(x.typ).(*TypeParam); tpar != nil {
+
+                       if tpar != nil {
                                buf.WriteString(" constrained by ")
                                WriteType(&buf, tpar.bound, qf) // do not compute interface type sets here
                                // If we have the type set and it's empty, say so for better error messages.
index 1c0e69200eba84737927a6e02698a11ed1ac6232..62759d1e9ce5d8dca3fc399fa68e89baa17f4ac8 100644 (file)
@@ -515,7 +515,7 @@ func max1() {
        _ = max(s)
        _ = max(x, x)
        _ = max(x, x, x, x, x)
-       var _ int = max /* ERROR "cannot use max(m) (value of type myint) as int value" */ (m)
+       var _ int = max /* ERROR "cannot use max(m) (value of int type myint) as int value" */ (m)
        _ = max(x, m /* ERROR "invalid argument: mismatched types int (previous argument) and myint (type of m)" */ , x)
 
        _ = max(1, x)
@@ -569,7 +569,7 @@ func min1() {
        _ = min(s)
        _ = min(x, x)
        _ = min(x, x, x, x, x)
-       var _ int = min /* ERROR "cannot use min(m) (value of type myint) as int value" */ (m)
+       var _ int = min /* ERROR "cannot use min(m) (value of int type myint) as int value" */ (m)
        _ = min(x, m /* ERROR "invalid argument: mismatched types int (previous argument) and myint (type of m)" */ , x)
 
        _ = min(1, x)
index 10b6a22eb1b880fcdaf5b349999ab56ffd44d08d..615cf862d1b89d9e9acd0ef8acd610dc3cba3c9e 100644 (file)
@@ -58,7 +58,7 @@ func _() {
 
 // Use unqualified names for package-local objects.
 type T struct{}
-var _ int = T /* ERROR "value of type T" */ {} // use T in error message rather than errors.T
+var _ int = T /* ERROR "value of struct type T" */ {} // use T in error message rather than errors.T
 
 // Don't report errors containing "invalid type" (issue #24182).
 func _(x *missing /* ERROR "undefined: missing" */ ) {
index d78b65705a9597249e7b41eafccadacbbdfe5705..44a709d66ea8224083f57826ff27e42a7129e72e 100644 (file)
@@ -363,7 +363,7 @@ func issue35895() {
 
        // Because both t1 and t2 have the same global package name (template),
        // qualify packages with full path name in this case.
-       var _ t1.Template = t2 /* ERRORx `cannot use .* \(value of type .html/template.\.Template\) as .text/template.\.Template` */ .Template{}
+       var _ t1.Template = t2 /* ERRORx `cannot use .* \(value of struct type .html/template.\.Template\) as .text/template.\.Template` */ .Template{}
 }
 
 func issue42989(s uint) {
index d91c2078730baa35f5faca996d3c9a4a1b81d506..6ec926ec6163dc9823486281598f090552a15bf3 100644 (file)
@@ -26,6 +26,6 @@ type X2 struct{}
 
 func _() {
        switch F2().(type) {
-       case * /* ERROR "impossible type switch case: *X2\n\tF2() (value of type T2) cannot have dynamic type *X2 (missing method M)" */ X2:
+       case * /* ERROR "impossible type switch case: *X2\n\tF2() (value of interface type T2) cannot have dynamic type *X2 (missing method M)" */ X2:
        }
 }
index b754f89df7321c8c6329c3a6e7d3d99dcc9ec0f8..17a9deb6d170106b067e132887fc64bdf0cfc1b2 100644 (file)
@@ -57,7 +57,7 @@ func _() {
        var x S[int]
        g4(x)      // we can infer int for P
        g4[int](x) // int is the correct type argument
-       g4[string](x /* ERROR "cannot use x (variable of type S[int]) as S[string] value in argument to g4[string]" */)
+       g4[string](x /* ERROR "cannot use x (variable of struct type S[int]) as S[string] value in argument to g4[string]" */)
 }
 
 // This is similar to the first example but here T1 is a component
index c44f921f44bf45c9f4c6faf4f25fc2b425385cf1..67a110df3176049b81ed61eb62c6bb2094949aed 100644 (file)
@@ -90,7 +90,7 @@ func _() {
        B = f(B, b, a)
 
        // verify type error
-       A = f /* ERROR "cannot use f(B, b, a) (value of type namedB) as namedA value in assignment" */ (B, b, a)
+       A = f /* ERROR "cannot use f(B, b, a) (value of chan type namedB) as namedA value in assignment" */ (B, b, a)
 }
 
 // Test case 4: some more combinations
diff --git a/src/internal/types/testdata/fixedbugs/issue69955.go b/src/internal/types/testdata/fixedbugs/issue69955.go
new file mode 100644 (file)
index 0000000..68ddf41
--- /dev/null
@@ -0,0 +1,42 @@
+// -gotypesalias=1
+
+// Copyright 2024 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 file.
+
+package p
+
+import "math/big"
+
+type (
+       S struct{}
+       N int
+
+       A = S
+       B = int
+       C = N
+)
+
+var (
+       i int
+       s S
+       n N
+       a A
+       b B
+       c C
+       w big.Word
+)
+
+const (
+       _ = i // ERROR "i (variable of type int) is not constant"
+       _ = s // ERROR "s (variable of struct type S) is not constant"
+       _ = struct /* ERROR "struct{}{} (value of type struct{}) is not constant" */ {}{}
+       _ = n // ERROR "n (variable of int type N) is not constant"
+
+       _ = a // ERROR "a (variable of struct type A) is not constant"
+       _ = b // ERROR "b (variable of int type B) is not constant"
+       _ = c // ERROR "c (variable of int type C) is not constant"
+       _ = w // ERROR "w (variable of uint type big.Word) is not constant"
+)
+
+var _ int = w /* ERROR "cannot use w + 1 (value of uint type big.Word) as int value in variable declaration" */ + 1
index 9e32256fb748887af2f37a273b6e7f55d938f034..52d1e70382bd2e77f8fbad9ef6b6fe6f6eca597c 100644 (file)
@@ -102,11 +102,11 @@ func test() {
        for mi, ms := range f8 {
                _, _ = mi, ms
        }
-       for i /* ERROR "cannot use i (value of type MyInt) as int value in assignment" */, s /* ERROR "cannot use s (value of type MyString) as string value in assignment" */ = range f8 {
+       for i /* ERROR "cannot use i (value of int32 type MyInt) as int value in assignment" */, s /* ERROR "cannot use s (value of string type MyString) as string value in assignment" */ = range f8 {
                _, _ = mi, ms
        }
        for mi, ms := range f8 {
-               i, s = mi /* ERROR "cannot use mi (variable of type MyInt) as int value in assignment" */, ms /* ERROR "cannot use ms (variable of type MyString) as string value in assignment" */
+               i, s = mi /* ERROR "cannot use mi (variable of int32 type MyInt) as int value in assignment" */, ms /* ERROR "cannot use ms (variable of string type MyString) as string value in assignment" */
        }
        for mi, ms = range f8 {
                _, _ = mi, ms
index 766736cc1556efc904f7a7355286f42e860bb296..db3a78ffadcddcd1ec18ffcdf64f771dc65bc20f 100644 (file)
@@ -44,7 +44,7 @@ func _() {
        for i, j /* ERROR "range over 10 (untyped int constant) permits only one iteration variable" */ := range 10 {
                _, _ = i, j
        }
-       for i = range MyInt /* ERROR "cannot use MyInt(10) (constant 10 of type MyInt) as int value in range clause" */ (10) {
+       for i = range MyInt /* ERROR "cannot use MyInt(10) (constant 10 of int32 type MyInt) as int value in range clause" */ (10) {
                _ = i
        }
        for mi := range MyInt(10) {
index 95eb25a94b5ae27b83672d14c71961f194c9b457..7a926cc482af8f041ad31d47365ba2b61f794fdf 100644 (file)
@@ -46,8 +46,8 @@ var _ A0 = T0{}
 var _ T0 = A0{}
 
 // But aliases and original types cannot be used with new types based on them.
-var _ N0 = T0{} // ERROR "cannot use T0{} \(value of type T0\) as N0 value in variable declaration"
-var _ N0 = A0{} // ERROR "cannot use A0{} \(value of type A0\) as N0 value in variable declaration"
+var _ N0 = T0{} // ERROR "cannot use T0{} \(value of struct type T0\) as N0 value in variable declaration"
+var _ N0 = A0{} // ERROR "cannot use A0{} \(value of struct type A0\) as N0 value in variable declaration"
 
 var _ A5 = Value{}
 
@@ -82,10 +82,10 @@ func _() {
        var _ A0 = T0{}
        var _ T0 = A0{}
 
-       var _ N0 = T0{} // ERROR "cannot use T0{} \(value of type T0\) as N0 value in variable declaration"
-       var _ N0 = A0{} // ERROR "cannot use A0{} \(value of type A0\) as N0 value in variable declaration"
+       var _ N0 = T0{} // ERROR "cannot use T0{} \(value of struct type T0\) as N0 value in variable declaration"
+       var _ N0 = A0{} // ERROR "cannot use A0{} \(value of struct type A0\) as N0 value in variable declaration"
 
-       var _ A5 = Value{} // ERROR "cannot use Value{} \(value of type reflect\.Value\) as A5 value in variable declaration"
+       var _ A5 = Value{} // ERROR "cannot use Value{} \(value of struct type reflect\.Value\) as A5 value in variable declaration"
 }
 
 // Invalid type alias declarations.
index 75875c40041c4d5db4386b09227f575dccac88b6..a834c8067558b4c9d575a95735c8810c9897b8c9 100644 (file)
@@ -51,6 +51,6 @@ func g() {
        _ = i.(T6)  // ERROR "impossible type assertion: i.\(T6\)\n\tT6 does not implement I \(missing method M\)\n\t\thave m\(int\) string\n\t\twant M\(int\)"
 
        var t *T4
-       t = i // ERROR "cannot use i \(variable of type I\) as \*T4 value in assignment: need type assertion"
+       t = i // ERROR "cannot use i \(variable of interface type I\) as \*T4 value in assignment: need type assertion"
        _ = t
 }