]> Cypherpunks.ru repositories - gostls13.git/commitdiff
go/types, types2: complete methods on pointer receivers in missingMethod
authorRobert Findley <rfindley@google.com>
Wed, 17 Nov 2021 14:35:57 +0000 (09:35 -0500)
committerRobert Findley <rfindley@google.com>
Wed, 17 Nov 2021 18:14:23 +0000 (18:14 +0000)
We were not calling objDecl on methods on pointer receivers in
missingMethod. This may not have mattered before, but with lazy
completion of instance methods it is necessary.

Fixes #49579

Change-Id: Icddb1f3b16bef7d8017859734f9879a4f1cc18de
Reviewed-on: https://go-review.googlesource.com/c/go/+/364714
Trust: Robert Findley <rfindley@google.com>
Trust: Dan Scales <danscales@google.com>
Run-TryBot: Robert Findley <rfindley@google.com>
Reviewed-by: Robert Griesemer <gri@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>

src/cmd/compile/internal/types2/lookup.go
src/cmd/compile/internal/types2/testdata/fixedbugs/issue49579.go2 [new file with mode: 0644]
src/go/types/lookup.go
src/go/types/testdata/fixedbugs/issue49579.go2 [new file with mode: 0644]

index 4f50ea54b14140ee743b04a4142cb595f8c18c18..ee764c7d1407ef2fdc1a9c2da41fb00ef461e82e 100644 (file)
@@ -71,6 +71,8 @@ func LookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (o
 // lookupFieldOrMethod should only be called by LookupFieldOrMethod and missingMethod.
 // If checkFold is true, the lookup for methods will include looking for any method
 // which case-folds to the same as 'name' (used for giving helpful error messages).
+//
+// The resulting object may not be fully type-checked.
 func lookupFieldOrMethod(T Type, addressable, checkFold bool, pkg *Package, name string) (obj Object, index []int, indirect bool) {
        // WARNING: The code in this function is extremely subtle - do not modify casually!
 
@@ -352,14 +354,17 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method,
                if obj == nil {
                        ptr := NewPointer(V)
                        obj, _, _ = lookupFieldOrMethod(ptr, false, false, m.pkg, m.name)
-                       if obj != nil {
-                               return m, obj.(*Func)
+                       if obj == nil {
+                               // If we didn't find the exact method (even with pointer
+                               // receiver), look to see if there is a method that
+                               // matches m.name with case-folding.
+                               obj, _, _ = lookupFieldOrMethod(V, false, true, m.pkg, m.name)
                        }
-                       // If we didn't find the exact method (even with pointer
-                       // receiver), look to see if there is a method that
-                       // matches m.name with case-folding.
-                       obj, _, _ := lookupFieldOrMethod(V, false, true, m.pkg, m.name)
                        if obj != nil {
+                               // methods may not have a fully set up signature yet
+                               if check != nil {
+                                       check.objDecl(obj, nil)
+                               }
                                return m, obj.(*Func)
                        }
                }
diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49579.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49579.go2
new file mode 100644 (file)
index 0000000..9e20ae5
--- /dev/null
@@ -0,0 +1,17 @@
+// 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 I[F any] interface {
+       Q(*F)
+}
+
+func G[F any]() I[any] {
+       return g /* ERROR "missing method Q \(Q has pointer receiver\)" */ [F]{}
+}
+
+type g[F any] struct{}
+
+func (*g[F]) Q(*any) {}
index be91d39f50be945296bce9e32ead54cb3bf878fa..6855ccdf27c7114d0f18cf3cb5b81acdd1e935c9 100644 (file)
@@ -69,6 +69,8 @@ func LookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (o
 //           indirectly via different packages.)
 
 // lookupFieldOrMethod should only be called by LookupFieldOrMethod and missingMethod.
+//
+// The resulting object may not be fully type-checked.
 func lookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (obj Object, index []int, indirect bool) {
        // WARNING: The code in this function is extremely subtle - do not modify casually!
 
@@ -346,7 +348,12 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method,
                if obj == nil {
                        ptr := NewPointer(V)
                        obj, _, _ = lookupFieldOrMethod(ptr, false, m.pkg, m.name)
+
                        if obj != nil {
+                               // methods may not have a fully set up signature yet
+                               if check != nil {
+                                       check.objDecl(obj, nil)
+                               }
                                return m, obj.(*Func)
                        }
                }
diff --git a/src/go/types/testdata/fixedbugs/issue49579.go2 b/src/go/types/testdata/fixedbugs/issue49579.go2
new file mode 100644 (file)
index 0000000..9e20ae5
--- /dev/null
@@ -0,0 +1,17 @@
+// 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 I[F any] interface {
+       Q(*F)
+}
+
+func G[F any]() I[any] {
+       return g /* ERROR "missing method Q \(Q has pointer receiver\)" */ [F]{}
+}
+
+type g[F any] struct{}
+
+func (*g[F]) Q(*any) {}