mirror of https://github.com/golang/go.git
x/tools/go/ssa: instantiate sel.Recv() on MethodVal.
When a MethodVal selection receiver is a TypeParam while monomorphizing, use the method value from the substituted type. Fixes golang/go#52835 Change-Id: Iaf174a02b62b0c3ed4aafefdfd2aca195781e9f9 Reviewed-on: https://go-review.googlesource.com/c/tools/+/405594 TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Zvonimir Pavlinovic <zpavlinovic@google.com> Run-TryBot: Tim King <taking@google.com> gopls-CI: kokoro <noreply+kokoro@google.com> Reviewed-by: Robert Findley <rfindley@google.com>
This commit is contained in:
parent
28c754d415
commit
8ec40b5329
|
|
@ -814,6 +814,13 @@ func (b *builder) expr0(fn *Function, e ast.Expr, tv types.TypeAndValue) Value {
|
|||
case types.MethodVal:
|
||||
// e.f where e is an expression and f is a method.
|
||||
// The result is a "bound".
|
||||
|
||||
if base := fn.typ(sel.Recv()); base != sel.Recv() {
|
||||
// instantiate sel as sel.Recv is not equal after substitution.
|
||||
pkg := fn.declaredPackage().Pkg
|
||||
// mv is the instantiated method value.
|
||||
sel = types.NewMethodSet(base).Lookup(pkg, sel.Obj().Name())
|
||||
}
|
||||
obj := sel.Obj().(*types.Func)
|
||||
rt := fn.typ(recvType(obj))
|
||||
wantAddr := isPointer(rt)
|
||||
|
|
|
|||
|
|
@ -129,6 +129,12 @@ var testdataTests = []string{
|
|||
"fixedbugs/issue52342.go",
|
||||
}
|
||||
|
||||
func init() {
|
||||
if typeparams.Enabled {
|
||||
testdataTests = append(testdataTests, "fixedbugs/issue52835.go")
|
||||
}
|
||||
}
|
||||
|
||||
// Specific GOARCH to use for a test case in go.tools/go/ssa/interp/testdata/.
|
||||
// Defaults to amd64 otherwise.
|
||||
var testdataArchs = map[string]string{
|
||||
|
|
@ -233,7 +239,6 @@ func TestTestdataFiles(t *testing.T) {
|
|||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
var failures []string
|
||||
for _, input := range testdataTests {
|
||||
if !run(t, filepath.Join(cwd, "testdata", input)) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,27 @@
|
|||
package main
|
||||
|
||||
var called bool
|
||||
|
||||
type I interface {
|
||||
Foo()
|
||||
}
|
||||
|
||||
type A struct{}
|
||||
|
||||
func (a A) Foo() {
|
||||
called = true
|
||||
}
|
||||
|
||||
func lambda[X I]() func() func() {
|
||||
return func() func() {
|
||||
var x X
|
||||
return x.Foo
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
lambda[A]()()()
|
||||
if !called {
|
||||
panic(called)
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue