mirror of
https://github.com/golang/go
synced 2024-11-25 02:17:57 -07:00
go/types, types2: qualify named types in error messages with type kind
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>
This commit is contained in:
parent
7ad9a2c65f
commit
7d9802ac5e
@ -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}[)]`},
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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}[)]`},
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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)
|
||||
|
2
src/internal/types/testdata/check/errors.go
vendored
2
src/internal/types/testdata/check/errors.go
vendored
@ -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" */ ) {
|
||||
|
2
src/internal/types/testdata/check/issues0.go
vendored
2
src/internal/types/testdata/check/issues0.go
vendored
@ -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) {
|
||||
|
@ -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:
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
42
src/internal/types/testdata/fixedbugs/issue69955.go
vendored
Normal file
42
src/internal/types/testdata/fixedbugs/issue69955.go
vendored
Normal file
@ -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
|
4
src/internal/types/testdata/spec/range.go
vendored
4
src/internal/types/testdata/spec/range.go
vendored
@ -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
|
||||
|
@ -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) {
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user