mirror of
https://github.com/golang/go
synced 2024-09-04 23:44:16 +00:00
[dev.typeparams] go/types: cleanups around receiver type checks
This is a port of CL 333770 to go/types, adjusted for the error reporting API and to not support compiler error messages. An error message changed (to 'invalid receiver type' from just 'invalid receiver'), so a test had to be adjusted. Change-Id: I166e8831d8c9f98ebfb0270fe5221586fc112825 Reviewed-on: https://go-review.googlesource.com/c/go/+/335079 Trust: Robert Findley <rfindley@google.com> Run-TryBot: Robert Findley <rfindley@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Robert Griesemer <gri@golang.org>
This commit is contained in:
parent
b3d91e3a24
commit
baeabf3b36
|
@ -199,30 +199,40 @@ func (check *Checker) funcType(sig *Signature, recvPar *ast.FieldList, ftyp *ast
|
||||||
|
|
||||||
// spec: "The receiver type must be of the form T or *T where T is a type name."
|
// spec: "The receiver type must be of the form T or *T where T is a type name."
|
||||||
// (ignore invalid types - error was reported before)
|
// (ignore invalid types - error was reported before)
|
||||||
if t := rtyp; t != Typ[Invalid] {
|
if rtyp != Typ[Invalid] {
|
||||||
var err string
|
var err string
|
||||||
if T := asNamed(t); T != nil {
|
switch T := rtyp.(type) {
|
||||||
|
case *Named:
|
||||||
// spec: "The type denoted by T is called the receiver base type; it must not
|
// spec: "The type denoted by T is called the receiver base type; it must not
|
||||||
// be a pointer or interface type and it must be declared in the same package
|
// be a pointer or interface type and it must be declared in the same package
|
||||||
// as the method."
|
// as the method."
|
||||||
if T.obj.pkg != check.pkg {
|
if T.obj.pkg != check.pkg {
|
||||||
err = "type not defined in this package"
|
err = "type not defined in this package"
|
||||||
} else {
|
} else {
|
||||||
switch u := optype(T).(type) {
|
// The underlying type of a receiver base type can be a type parameter;
|
||||||
case *Basic:
|
// e.g. for methods with a generic receiver T[P] with type T[P any] P.
|
||||||
// unsafe.Pointer is treated like a regular pointer
|
underIs(T, func(u Type) bool {
|
||||||
if u.kind == UnsafePointer {
|
switch u := u.(type) {
|
||||||
err = "unsafe.Pointer"
|
case *Basic:
|
||||||
|
// unsafe.Pointer is treated like a regular pointer
|
||||||
|
if u.kind == UnsafePointer {
|
||||||
|
err = "unsafe.Pointer"
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
case *Pointer, *Interface:
|
||||||
|
err = "pointer or interface type"
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
case *Pointer, *Interface:
|
return true
|
||||||
err = "pointer or interface type"
|
})
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
case *Basic:
|
||||||
err = "basic or unnamed type"
|
err = "basic or unnamed type"
|
||||||
|
default:
|
||||||
|
check.errorf(recv, _InvalidRecv, "invalid receiver type %s", recv.typ)
|
||||||
}
|
}
|
||||||
if err != "" {
|
if err != "" {
|
||||||
check.errorf(recv, _InvalidRecv, "invalid receiver %s (%s)", recv.typ, err)
|
check.errorf(recv, _InvalidRecv, "invalid receiver type %s (%s)", recv.typ, err)
|
||||||
// ok to continue
|
// ok to continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
17
src/go/types/testdata/examples/methods.go2
vendored
17
src/go/types/testdata/examples/methods.go2
vendored
|
@ -6,6 +6,8 @@
|
||||||
|
|
||||||
package p
|
package p
|
||||||
|
|
||||||
|
import "unsafe"
|
||||||
|
|
||||||
// Parameterized types may have methods.
|
// Parameterized types may have methods.
|
||||||
type T1[A any] struct{ a A }
|
type T1[A any] struct{ a A }
|
||||||
|
|
||||||
|
@ -94,3 +96,18 @@ func (_ T2[_, _, _]) _() int { return 42 }
|
||||||
type T0 struct{}
|
type T0 struct{}
|
||||||
func (T0) _() {}
|
func (T0) _() {}
|
||||||
func (T1[A]) _() {}
|
func (T1[A]) _() {}
|
||||||
|
|
||||||
|
// A generic receiver type may constrain its type parameter such
|
||||||
|
// that it must be a pointer type. Such receiver types are not
|
||||||
|
// permitted.
|
||||||
|
type T3a[P interface{ ~int | ~string | ~float64 }] P
|
||||||
|
|
||||||
|
func (T3a[_]) m() {} // this is ok
|
||||||
|
|
||||||
|
type T3b[P interface{ ~unsafe.Pointer }] P
|
||||||
|
|
||||||
|
func (T3b /* ERROR invalid receiver */ [_]) m() {}
|
||||||
|
|
||||||
|
type T3c[P interface{ *int | *string }] P
|
||||||
|
|
||||||
|
func (T3c /* ERROR invalid receiver */ [_]) m() {}
|
||||||
|
|
|
@ -60,6 +60,6 @@ type (
|
||||||
T11 = T
|
T11 = T
|
||||||
)
|
)
|
||||||
|
|
||||||
func (T9 /* ERROR invalid receiver \*\*T */ ) m9() {}
|
func (T9 /* ERROR invalid receiver type \*\*T */ ) m9() {}
|
||||||
func _() { (T{}).m9 /* ERROR has no field or method m9 */ () }
|
func _() { (T{}).m9 /* ERROR has no field or method m9 */ () }
|
||||||
func _() { (&T{}).m9 /* ERROR has no field or method m9 */ () }
|
func _() { (&T{}).m9 /* ERROR has no field or method m9 */ () }
|
||||||
|
|
Loading…
Reference in a new issue