From: Robert Findley Date: Wed, 17 Nov 2021 14:35:57 +0000 (-0500) Subject: go/types, types2: complete methods on pointer receivers in missingMethod X-Git-Tag: go1.18beta1~267 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=9bdbed1d963a840d8c23640bbd20bd4cb9776859;p=gostls13.git go/types, types2: complete methods on pointer receivers in missingMethod 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 Trust: Dan Scales Run-TryBot: Robert Findley Reviewed-by: Robert Griesemer TryBot-Result: Go Bot --- diff --git a/src/cmd/compile/internal/types2/lookup.go b/src/cmd/compile/internal/types2/lookup.go index 4f50ea54b1..ee764c7d14 100644 --- a/src/cmd/compile/internal/types2/lookup.go +++ b/src/cmd/compile/internal/types2/lookup.go @@ -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 index 0000000000..9e20ae5468 --- /dev/null +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49579.go2 @@ -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) {} diff --git a/src/go/types/lookup.go b/src/go/types/lookup.go index be91d39f50..6855ccdf27 100644 --- a/src/go/types/lookup.go +++ b/src/go/types/lookup.go @@ -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 index 0000000000..9e20ae5468 --- /dev/null +++ b/src/go/types/testdata/fixedbugs/issue49579.go2 @@ -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) {}