]> Cypherpunks.ru repositories - gostls13.git/commitdiff
[dev.typeparams] go/types: don't permit method calls on ptr to type parameter receivers
authorRob Findley <rfindley@google.com>
Fri, 16 Jul 2021 17:15:24 +0000 (13:15 -0400)
committerRobert Findley <rfindley@google.com>
Mon, 19 Jul 2021 15:48:55 +0000 (15:48 +0000)
This is a port of CL 332609 to go/types.

Change-Id: I3482ea1b97bc7101b987ef312cd6cade80a5843f
Reviewed-on: https://go-review.googlesource.com/c/go/+/335112
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>
src/go/types/lookup.go
src/go/types/testdata/check/issues.go2
src/go/types/testdata/fixedbugs/issue47031.go2 [new file with mode: 0644]
src/go/types/type.go

index 70e3b4281d7b401aad3eb704a7154e4e8a510907..304ae6e3c90f53aff4116783f0940a81a7afc5ba 100644 (file)
@@ -75,10 +75,12 @@ func lookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (o
 
        typ, isPtr := deref(T)
 
-       // *typ where typ is an interface has no methods.
-       // Be cautious: typ may be nil (issue 39634, crash #3).
-       if typ == nil || isPtr && IsInterface(typ) {
-               return
+       // *typ where typ is an interface or type parameter has no methods.
+       switch under(typ).(type) {
+       case *Interface, *TypeParam:
+               if isPtr {
+                       return
+               }
        }
 
        // Start with typ as single entry at shallowest depth.
index c655fb99a4f07a1fc0ec01ab87dff1a27938e9db..607da1df19eef90fbe2d38766820c6d58c578b82 100644 (file)
@@ -24,22 +24,20 @@ func _() {
        eql[io.Reader](nil, nil)
 }
 
-// If we have a receiver of pointer type (below: *T) we must ignore
-// the pointer in the implementation of the method lookup because
-// the type bound of T is an interface and pointer to interface types
-// have no methods and then the lookup would fail.
+// If we have a receiver of pointer to type parameter type (below: *T)
+// we don't have any methods, like for interfaces.
 type C[T any] interface {
     m()
 }
 
 // using type bound C
 func _[T C[T]](x *T) {
-       x.m()
+       x.m  /* ERROR x\.m undefined */ ()
 }
 
 // using an interface literal as bound
 func _[T interface{ m() }](x *T) {
-       x.m()
+       x.m  /* ERROR x\.m undefined */ ()
 }
 
 // In a generic function body all method calls will be pointer method calls.
diff --git a/src/go/types/testdata/fixedbugs/issue47031.go2 b/src/go/types/testdata/fixedbugs/issue47031.go2
new file mode 100644 (file)
index 0000000..b184f9b
--- /dev/null
@@ -0,0 +1,20 @@
+// Copyright 2021 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
+
+type Mer interface { M() }
+
+func F[T Mer](p *T) {
+       p.M /* ERROR p\.M undefined */ ()
+}
+
+type MyMer int
+
+func (MyMer) M() {}
+
+func _() {
+       F(new(MyMer))
+       F[Mer](nil)
+}
index 662dd859f091814db3bb0d561508f04a1c65fdc8..0a6fff0dcabcd79171214ee49e67d1d778bfc096 100644 (file)
@@ -113,11 +113,6 @@ func asSignature(t Type) *Signature {
        return op
 }
 
-func asInterface(t Type) *Interface {
-       op, _ := optype(t).(*Interface)
-       return op
-}
-
 func asMap(t Type) *Map {
        op, _ := optype(t).(*Map)
        return op
@@ -128,10 +123,15 @@ func asChan(t Type) *Chan {
        return op
 }
 
-// If the argument to asNamed and asTypeParam is of the respective types
+// If the argument to asInterface, asNamed, or asTypeParam is of the respective type
 // (possibly after expanding an instance type), these methods return that type.
 // Otherwise the result is nil.
 
+func asInterface(t Type) *Interface {
+       op, _ := optype(t).(*Interface)
+       return op
+}
+
 func asNamed(t Type) *Named {
        e, _ := expand(t).(*Named)
        return e