// 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)
- if t := rtyp; t != Typ[Invalid] {
+ if rtyp != Typ[Invalid] {
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
// be a pointer or interface type and it must be declared in the same package
// as the method."
err = ""
}
} else {
- switch u := optype(T).(type) {
- case *Basic:
- // unsafe.Pointer is treated like a regular pointer
- if u.kind == UnsafePointer {
- err = "unsafe.Pointer"
+ // The underlying type of a receiver base type can be a type parameter;
+ // e.g. for methods with a generic receiver T[P] with type T[P any] P.
+ underIs(T, func(u Type) bool {
+ switch u := u.(type) {
+ 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:
- err = "pointer or interface type"
- }
+ return true
+ })
}
- } else if T := asBasic(t); T != nil {
+ case *Basic:
err = "basic or unnamed type"
if check.conf.CompilerErrorMessages {
check.errorf(recv.pos, "cannot define new methods on non-local type %s", recv.typ)
err = ""
}
- } else {
+ default:
check.errorf(recv.pos, "invalid receiver type %s", recv.typ)
}
if err != "" {
package p
+import "unsafe"
+
// Parameterized types may have methods.
type T1[A any] struct{ a A }
type T0 struct{}
func (T0) _() {}
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() {}