cmd/compile: always remove receiver type from instantiated method values

If a type T has a method foo, then

var t T
var i interface{} = t.foo

The type of foo is a method type, but the type of t.foo should be a
standard function type. Make sure we always do that conversion.

Fixes #47775

Change-Id: I464ec792196b050aba1914e070a4ede34bfd0bfa
Reviewed-on: https://go-review.googlesource.com/c/go/+/343881
Trust: Keith Randall <khr@golang.org>
Trust: Dan Scales <danscales@google.com>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: Dan Scales <danscales@google.com>
This commit is contained in:
Keith Randall 2021-08-20 16:15:53 -07:00
parent 8486ced8b0
commit 3081f817da
6 changed files with 72 additions and 5 deletions

View file

@ -578,11 +578,7 @@ func transformDot(n *ir.SelectorExpr, isCall bool) ir.Node {
if (n.Op() == ir.ODOTINTER || n.Op() == ir.ODOTMETH) && !isCall {
n.SetOp(ir.OMETHVALUE)
if len(n.X.Type().RParams()) > 0 || n.X.Type().IsPtr() && len(n.X.Type().Elem().RParams()) > 0 {
// TODO: MethodValueWrapper needed for generics?
// Or did we successfully desugar all that at stencil time?
return n
}
// This converts a method type to a function type. See issue 47775.
n.SetType(typecheck.NewMethodType(n.Type(), nil))
}
return n

View file

@ -479,6 +479,12 @@ func autotmpname(n int) string {
// f is method type, with receiver.
// return function type, receiver as first argument (or not).
func NewMethodType(sig *types.Type, recv *types.Type) *types.Type {
if sig.HasTParam() {
base.Fatalf("NewMethodType with type parameters in signature %+v", sig)
}
if recv != nil && recv.HasTParam() {
base.Fatalf("NewMethodType with type parameters in receiver %+v", recv)
}
nrecvs := 0
if recv != nil {
nrecvs++

View file

@ -0,0 +1,19 @@
// 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 b
type C[T any] struct {
}
func (c *C[T]) reset() {
}
func New[T any]() {
c := &C[T]{}
z(c.reset)
}
func z(interface{}) {
}

View file

@ -0,0 +1,11 @@
// 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 main
import "b"
func main() {
b.New[int]()
}

View file

@ -0,0 +1,7 @@
// rundir -G=3
// 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 ignored

View file

@ -0,0 +1,28 @@
// run -gcflags=-G=3
// 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 main
type C[T any] struct {
}
func (c *C[T]) reset() {
}
func New[T any]() {
c := &C[T]{}
i = c.reset
z(c.reset)
}
var i interface{}
func z(interface{}) {
}
func main() {
New[int]()
}