]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile/internal/types2: fix method lookup for type-parameter based types
authorRobert Griesemer <gri@golang.org>
Tue, 17 Aug 2021 18:45:05 +0000 (11:45 -0700)
committerRobert Griesemer <gri@golang.org>
Tue, 17 Aug 2021 20:57:49 +0000 (20:57 +0000)
Pointers to type parameters don't have methods, but pointers to
defined types whose underlying types are type parameters may have
methods. Fix the respective test.

For #47747.

Change-Id: I1de47be094ed9297f0e7782538011657c37c5adc
Reviewed-on: https://go-review.googlesource.com/c/go/+/342990
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/cmd/compile/internal/types2/lookup.go
src/cmd/compile/internal/types2/testdata/fixedbugs/issue47747.go2 [new file with mode: 0644]

index 3779d17b3db033adcf44fff2206ef2127b80bf99..668c5ff3ec643fe81f01d36a69c3e275fd92a7d1 100644 (file)
@@ -74,9 +74,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/cmd/compile/internal/types2/testdata/fixedbugs/issue47747.go2 b/src/cmd/compile/internal/types2/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)
+}