]> Cypherpunks.ru repositories - gostls13.git/commitdiff
go/types, types2: better error message for some invalid receiver errors (cleanup)
authorRobert Griesemer <gri@golang.org>
Mon, 28 Mar 2022 23:22:22 +0000 (16:22 -0700)
committerRobert Griesemer <gri@golang.org>
Tue, 29 Mar 2022 22:09:32 +0000 (22:09 +0000)
Use the 1.17 compiler error message together with the receiver base type.
Also, simplify and flatten the receive testing logic for clarity.

Change-Id: I71e58f261900dd7a85d2eb89a310c36b68d1b0b0
Reviewed-on: https://go-review.googlesource.com/c/go/+/396298
Trust: Robert Griesemer <gri@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
src/cmd/compile/internal/types2/signature.go
src/cmd/compile/internal/types2/testdata/check/decls2/decls2a.go
src/cmd/compile/internal/types2/testdata/check/decls4.go
src/cmd/compile/internal/types2/testdata/fixedbugs/issue47968.go
src/go/types/signature.go
src/go/types/testdata/check/decls2/decls2a.go
src/go/types/testdata/check/decls4.go
src/go/types/testdata/fixedbugs/issue47968.go

index c98024f92482e0e46891298bbce1b1b6e27d1bab..2dc4dd43f37a4e7026661b1c9f689edf40d699ea 100644 (file)
@@ -199,62 +199,48 @@ func (check *Checker) funcType(sig *Signature, recvPar *syntax.Field, tparams []
                // Delay validation of receiver type as it may cause premature expansion
                // of types the receiver type is dependent on (see issues #51232, #51233).
                check.later(func() {
-                       rtyp, _ := deref(recv.typ)
-
                        // 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 rtyp != Typ[Invalid] {
-                               var err string
-                               switch T := rtyp.(type) {
-                               case *Named:
-                                       T.resolve(check.bestContext(nil))
-                                       // The receiver type may be an instantiated type referred to
-                                       // by an alias (which cannot have receiver parameters for now).
-                                       if T.TypeArgs() != nil && sig.RecvTypeParams() == nil {
-                                               check.errorf(recv.pos, "cannot define methods on instantiated type %s", recv.typ)
-                                               break
-                                       }
-                                       // 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."
-                                       if T.obj.pkg != check.pkg {
-                                               err = "type not defined in this package"
-                                               if check.conf.CompilerErrorMessages {
-                                                       check.errorf(recv.pos, "cannot define new methods on non-local type %s", recv.typ)
-                                                       err = ""
-                                               }
-                                       } else {
-                                               // 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.
-                                               // TODO(gri) Such declarations are currently disallowed.
-                                               //           Revisit the need for underIs.
-                                               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
-                                                       }
-                                                       return true
-                                               })
-                                       }
+                       rtyp, _ := deref(recv.typ)
+                       if rtyp == Typ[Invalid] {
+                               return // error was reported before
+                       }
+                       // 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."
+                       switch T := rtyp.(type) {
+                       case *Named:
+                               T.resolve(check.bestContext(nil))
+                               // The receiver type may be an instantiated type referred to
+                               // by an alias (which cannot have receiver parameters for now).
+                               if T.TypeArgs() != nil && sig.RecvTypeParams() == nil {
+                                       check.errorf(recv, "cannot define new methods on instantiated type %s", rtyp)
+                                       break
+                               }
+                               if T.obj.pkg != check.pkg {
+                                       check.errorf(recv, "cannot define new methods on non-local type %s", rtyp)
+                                       break
+                               }
+                               var cause string
+                               switch u := T.under().(type) {
                                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 = ""
+                                       // unsafe.Pointer is treated like a regular pointer
+                                       if u.kind == UnsafePointer {
+                                               cause = "unsafe.Pointer"
                                        }
-                               default:
-                                       check.errorf(recv.pos, "invalid receiver type %s", recv.typ)
+                               case *Pointer, *Interface:
+                                       cause = "pointer or interface type"
+                               case *TypeParam:
+                                       // The underlying type of a receiver base type cannot be a
+                                       // type parameter: "type T[P any] P" is not a valid declaration.
+                                       unreachable()
                                }
-                               if err != "" {
-                                       check.errorf(recv.pos, "invalid receiver type %s (%s)", recv.typ, err)
+                               if cause != "" {
+                                       check.errorf(recv, "invalid receiver type %s (%s)", rtyp, cause)
                                }
+                       case *Basic:
+                               check.errorf(recv, "cannot define new methods on non-local type %s", rtyp)
+                       default:
+                               check.errorf(recv, "invalid receiver type %s", recv.typ)
                        }
                }).describef(recv, "validate receiver %s", recv)
        }
index d077db55dd3e4d8a847d0ecf70a792c1a174a0ac..66ca6ee515dec4558b96416564106ee4a55b1e60 100644 (file)
@@ -93,10 +93,10 @@ func (a, b /* ERROR "multiple receivers" */ T3) _() {}
 func (a, b, c /* ERROR "multiple receivers" */ T3) _() {}
 
 // Methods associated with non-local or unnamed types.
-func (int /* ERROR "invalid receiver" */ ) m() {}
+func (int /* ERROR "cannot define new methods on non-local type int" */ ) m() {}
 func ([ /* ERROR "invalid receiver" */ ]int) m() {}
-func (time /* ERROR "invalid receiver" */ .Time) m() {}
-func (* /* ERROR "invalid receiver" */ time.Time) m() {}
+func (time /* ERROR "cannot define new methods on non-local type time\.Time" */ .Time) m() {}
+func (* /* ERROR "cannot define new methods on non-local type time\.Time" */ time.Time) m() {}
 func (x /* ERROR "invalid receiver" */ interface{}) m() {}
 
 // Unsafe.Pointer is treated like a pointer when used as receiver type.
index eb08421beee0011f7064f735c6c7417dc5d73c64..384bcd9b89a966fb719f9640e6f7a1163b71b701 100644 (file)
@@ -59,7 +59,7 @@ var (
 )
 
 // alias receiver types
-func (Ai /* ERROR "invalid receiver" */) m1() {}
+func (Ai /* ERROR "cannot define new methods on non-local type int" */) m1() {}
 func (T0) m1() {}
 func (A0) m1 /* ERROR already declared */ () {}
 func (A0) m2 () {}
@@ -115,8 +115,8 @@ type (
        B2 = int
 )
 
-func (B0 /* ERROR invalid receiver */ ) m() {}
-func (B1 /* ERROR invalid receiver */ ) n() {}
+func (B0 /* ERROR cannot define new methods on non-local type int */ ) m() {}
+func (B1 /* ERROR cannot define new methods on non-local type int */ ) n() {}
 
 // cycles
 type (
index 711e50a55a1d5eeb9661ff259a03ea78618dd82e..3dd303957ca81624ca6221beca5140404ee061fa 100644 (file)
@@ -14,8 +14,8 @@ func (A1[P]) m2() {}
 
 type A2 = T[int]
 
-func (A2 /* ERROR cannot define methods on instantiated type T\[int\] */) m3()   {}
-func (_ /* ERROR cannot define methods on instantiated type T\[int\] */ A2) m4() {}
+func (A2 /* ERROR cannot define new methods on instantiated type T\[int\] */) m3()   {}
+func (_ /* ERROR cannot define new methods on instantiated type T\[int\] */ A2) m4() {}
 
 func (T[int]) m5()                                     {} // int is the type parameter name, not an instantiation
 func (T[* /* ERROR must be an identifier */ int]) m6() {} // syntax error
index a340ac701eaa53d535bcdb4dbd64b8793791efa0..9e7b63b4513e291d775bd5d0303be6c5494da7c5 100644 (file)
@@ -206,62 +206,48 @@ func (check *Checker) funcType(sig *Signature, recvPar *ast.FieldList, ftyp *ast
                // Delay validation of receiver type as it may cause premature expansion
                // of types the receiver type is dependent on (see issues #51232, #51233).
                check.later(func() {
-                       rtyp, _ := deref(recv.typ)
-
                        // 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 rtyp != Typ[Invalid] {
-                               var err string
-                               switch T := rtyp.(type) {
-                               case *Named:
-                                       T.resolve(check.bestContext(nil))
-                                       // The receiver type may be an instantiated type referred to
-                                       // by an alias (which cannot have receiver parameters for now).
-                                       if T.TypeArgs() != nil && sig.RecvTypeParams() == nil {
-                                               check.errorf(recv, _InvalidRecv, "cannot define methods on instantiated type %s", recv.typ)
-                                               break
-                                       }
-                                       // 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."
-                                       if T.obj.pkg != check.pkg {
-                                               err = "type not defined in this package"
-                                               if compilerErrorMessages {
-                                                       check.errorf(recv, _InvalidRecv, "cannot define new methods on non-local type %s", recv.typ)
-                                                       err = ""
-                                               }
-                                       } else {
-                                               // 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.
-                                               // TODO(gri) Such declarations are currently disallowed.
-                                               //           Revisit the need for underIs.
-                                               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
-                                                       }
-                                                       return true
-                                               })
-                                       }
+                       rtyp, _ := deref(recv.typ)
+                       if rtyp == Typ[Invalid] {
+                               return // error was reported before
+                       }
+                       // 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."
+                       switch T := rtyp.(type) {
+                       case *Named:
+                               T.resolve(check.bestContext(nil))
+                               // The receiver type may be an instantiated type referred to
+                               // by an alias (which cannot have receiver parameters for now).
+                               if T.TypeArgs() != nil && sig.RecvTypeParams() == nil {
+                                       check.errorf(recv, _InvalidRecv, "cannot define new methods on instantiated type %s", rtyp)
+                                       break
+                               }
+                               if T.obj.pkg != check.pkg {
+                                       check.errorf(recv, _InvalidRecv, "cannot define new methods on non-local type %s", rtyp)
+                                       break
+                               }
+                               var cause string
+                               switch u := T.under().(type) {
                                case *Basic:
-                                       err = "basic or unnamed type"
-                                       if compilerErrorMessages {
-                                               check.errorf(recv, _InvalidRecv, "cannot define new methods on non-local type %s", recv.typ)
-                                               err = ""
+                                       // unsafe.Pointer is treated like a regular pointer
+                                       if u.kind == UnsafePointer {
+                                               cause = "unsafe.Pointer"
                                        }
-                               default:
-                                       check.errorf(recv, _InvalidRecv, "invalid receiver type %s", recv.typ)
+                               case *Pointer, *Interface:
+                                       cause = "pointer or interface type"
+                               case *TypeParam:
+                                       // The underlying type of a receiver base type cannot be a
+                                       // type parameter: "type T[P any] P" is not a valid declaration.
+                                       unreachable()
                                }
-                               if err != "" {
-                                       check.errorf(recv, _InvalidRecv, "invalid receiver type %s (%s)", recv.typ, err)
+                               if cause != "" {
+                                       check.errorf(recv, _InvalidRecv, "invalid receiver type %s (%s)", rtyp, cause)
                                }
+                       case *Basic:
+                               check.errorf(recv, _InvalidRecv, "cannot define new methods on non-local type %s", rtyp)
+                       default:
+                               check.errorf(recv, _InvalidRecv, "invalid receiver type %s", recv.typ)
                        }
                }).describef(recv, "validate receiver %s", recv)
        }
index bdbecd9dbb6358a38b9d535c461624562d66b51d..9dff17349c0d0e5a20ec742a37e81b5e8f578f13 100644 (file)
@@ -93,10 +93,10 @@ func (a, b /* ERROR "exactly one receiver" */ T3) _() {}
 func (a, b, c /* ERROR "exactly one receiver" */ T3) _() {}
 
 // Methods associated with non-local or unnamed types.
-func (int /* ERROR "invalid receiver" */ ) m() {}
+func (int /* ERROR "cannot define new methods on non-local type int" */ ) m() {}
 func ([ /* ERROR "invalid receiver" */ ]int) m() {}
-func (time /* ERROR "invalid receiver" */ .Time) m() {}
-func (* /* ERROR "invalid receiver" */ time.Time) m() {}
+func (time /* ERROR "cannot define new methods on non-local type time\.Time" */ .Time) m() {}
+func (* /* ERROR "cannot define new methods on non-local type time\.Time" */ time.Time) m() {}
 func (x /* ERROR "invalid receiver" */ interface{}) m() {}
 
 // Unsafe.Pointer is treated like a pointer when used as receiver type.
index 140bbfd31fdf1cd09e7515d1a2af326acb6e3e10..8a9a6ffba7d5b445363e734011ef556d2de76a55 100644 (file)
@@ -59,7 +59,7 @@ var (
 )
 
 // alias receiver types
-func (Ai /* ERROR "invalid receiver" */) m1() {}
+func (Ai /* ERROR "cannot define new methods on non-local type int" */) m1() {}
 func (T0) m1() {}
 func (A0) m1 /* ERROR already declared */ () {}
 func (A0) m2 () {}
@@ -115,8 +115,8 @@ type (
        B2 = int
 )
 
-func (B0 /* ERROR invalid receiver */ ) m() {}
-func (B1 /* ERROR invalid receiver */ ) n() {}
+func (B0 /* ERROR cannot define new methods on non-local type int */ ) m() {}
+func (B1 /* ERROR cannot define new methods on non-local type int */ ) n() {}
 
 // cycles
 type (
index 711e50a55a1d5eeb9661ff259a03ea78618dd82e..3dd303957ca81624ca6221beca5140404ee061fa 100644 (file)
@@ -14,8 +14,8 @@ func (A1[P]) m2() {}
 
 type A2 = T[int]
 
-func (A2 /* ERROR cannot define methods on instantiated type T\[int\] */) m3()   {}
-func (_ /* ERROR cannot define methods on instantiated type T\[int\] */ A2) m4() {}
+func (A2 /* ERROR cannot define new methods on instantiated type T\[int\] */) m3()   {}
+func (_ /* ERROR cannot define new methods on instantiated type T\[int\] */ A2) m4() {}
 
 func (T[int]) m5()                                     {} // int is the type parameter name, not an instantiation
 func (T[* /* ERROR must be an identifier */ int]) m6() {} // syntax error