]> Cypherpunks repositories - gostls13.git/commitdiff
go/types: fix method lookup for type-parameter based types
authorRobert Griesemer <gri@golang.org>
Tue, 17 Aug 2021 18:55:39 +0000 (11:55 -0700)
committerRobert Griesemer <gri@golang.org>
Tue, 17 Aug 2021 20:57:50 +0000 (20:57 +0000)
This is a clean port of CL 342990.

Fixes #47747.

Change-Id: I2e86fb8b70d42a220ac1ba25798d9e58227ba5f6
Reviewed-on: https://go-review.googlesource.com/c/go/+/342991
Trust: Robert Griesemer <gri@golang.org>
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
src/go/types/lookup.go
src/go/types/testdata/fixedbugs/issue47747.go2 [new file with mode: 0644]

index 186e421edb7ebd14be5dda2c51bf1f68059a4339..20a24cab734e1d8f7780f1388b9bee6daa9636f8 100644 (file)
@@ -76,9 +76,12 @@ func lookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (o
        typ, isPtr := deref(T)
 
        // *typ where typ is an interface or type parameter has no methods.
-       switch under(typ).(type) {
-       case *Interface, *TypeParam:
-               if isPtr {
+       if isPtr {
+               // don't look at under(typ) here - was bug (issue #47747)
+               if _, ok := typ.(*TypeParam); ok {
+                       return
+               }
+               if _, ok := under(typ).(*Interface); ok {
                        return
                }
        }
diff --git a/src/go/types/testdata/fixedbugs/issue47747.go2 b/src/go/types/testdata/fixedbugs/issue47747.go2
new file mode 100644 (file)
index 0000000..af52056
--- /dev/null
@@ -0,0 +1,68 @@
+// 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 T1[P any] P
+
+func (T1[_]) m() {}
+
+func _[P any](x *T1[P]) {
+        // x.m exists because x is of type *T1 where T1 is a defined type
+        // (even though under(T1) is a type parameter)
+        x.m()
+}
+
+
+func _[P interface{ m() }](x P) {
+        x.m()
+        // (&x).m doesn't exist because &x is of type *P
+        // and pointers to type parameters don't have methods
+        (&x).m /* ERROR \*P has no field or method m */ ()
+}
+
+
+type T2 interface{ m() }
+
+func _(x *T2) {
+        // x.m doesn't exists because x is of type *T2
+        // and pointers to interfaces don't have methods
+        x.m /* ERROR \*T2 has no field or method m */()
+}
+
+// Test case 1 from issue
+
+type Fooer1[t any] interface {
+       Foo(Barer[t])
+}
+type Barer[t any] interface {
+       Bar(t)
+}
+
+type Foo1[t any] t
+type Bar[t any] t
+
+func (l Foo1[t]) Foo(v Barer[t]) { v.Bar(t(l)) }
+func (b *Bar[t]) Bar(l t)        { *b = Bar[t](l) }
+
+func _[t any](f Fooer1[t]) t {
+       var b Bar[t]
+       f.Foo(&b)
+       return t(b)
+}
+
+// Test case 2 from issue
+
+type Fooer2[t any] interface {
+       Foo()
+}
+
+type Foo2[t any] t
+
+func (f *Foo2[t]) Foo() {}
+
+func _[t any](v t) {
+       var f = Foo2[t](v)
+       _ = Fooer2[t](&f)
+}