]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: always remove receiver type from instantiated method values
authorKeith Randall <khr@golang.org>
Fri, 20 Aug 2021 23:15:53 +0000 (16:15 -0700)
committerKeith Randall <khr@golang.org>
Mon, 23 Aug 2021 19:27:46 +0000 (19:27 +0000)
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>
src/cmd/compile/internal/noder/transform.go
src/cmd/compile/internal/typecheck/dcl.go
test/typeparam/issue47775.dir/b.go [new file with mode: 0644]
test/typeparam/issue47775.dir/main.go [new file with mode: 0644]
test/typeparam/issue47775.go [new file with mode: 0644]
test/typeparam/issue47775b.go [new file with mode: 0644]

index e1eeb8e73940fa1b9adb98b3c5db043e764c082a..140bb33234d6368ea3600b6d273895cf2f1a89f4 100644 (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
index 11e20f0f0762e96c2f7919cd3ec9220b912ad6d0..472d8d2b8ad832ca08aa97e7a035efbd3bdcefae 100644 (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++
diff --git a/test/typeparam/issue47775.dir/b.go b/test/typeparam/issue47775.dir/b.go
new file mode 100644 (file)
index 0000000..b6d7ba9
--- /dev/null
@@ -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{}) {
+}
diff --git a/test/typeparam/issue47775.dir/main.go b/test/typeparam/issue47775.dir/main.go
new file mode 100644 (file)
index 0000000..ed284dd
--- /dev/null
@@ -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]()
+}
diff --git a/test/typeparam/issue47775.go b/test/typeparam/issue47775.go
new file mode 100644 (file)
index 0000000..76930e5
--- /dev/null
@@ -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
diff --git a/test/typeparam/issue47775b.go b/test/typeparam/issue47775b.go
new file mode 100644 (file)
index 0000000..6d3fc8d
--- /dev/null
@@ -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]()
+}