aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkorzhao <korzhao95@gmail.com>2021-09-09 21:51:43 +0800
committerDan Scales <danscales@google.com>2021-09-09 21:28:56 +0000
commitc981874a5a87605b446b3a56abba9907d17e8493 (patch)
tree991256e015b825eb285ba36149f5bc32de759109
parent2c4f389c0298a37f1f3c000ad8b87e65d46c757f (diff)
downloadgo-c981874a5a87605b446b3a56abba9907d17e8493.tar.gz
go-c981874a5a87605b446b3a56abba9907d17e8493.zip
cmd/compile: fix implement for closure in a global assignment
If closure in a global assignment and has a method receiver. We should assign receiver as a global variable, not a local variable. Fixes #48225 Change-Id: I8f65dd6e8baf66a5eff24028d28ad0a594091add Reviewed-on: https://go-review.googlesource.com/c/go/+/348512 Run-TryBot: Dan Scales <danscales@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Dan Scales <danscales@google.com> Reviewed-by: Keith Randall <khr@golang.org> Trust: Dan Scales <danscales@google.com>
-rw-r--r--src/cmd/compile/internal/noder/stencil.go12
-rw-r--r--test/typeparam/issue48225.go37
2 files changed, 46 insertions, 3 deletions
diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go
index a524ddc2a0..5069db9fe1 100644
--- a/src/cmd/compile/internal/noder/stencil.go
+++ b/src/cmd/compile/internal/noder/stencil.go
@@ -396,13 +396,19 @@ func (g *irgen) buildClosure(outer *ir.Func, x ir.Node) ir.Node {
if rcvrValue != nil {
rcvrVar = ir.NewNameAt(pos, typecheck.LookupNum(".rcvr", g.dnum))
g.dnum++
- rcvrVar.Class = ir.PAUTO
typed(rcvrValue.Type(), rcvrVar)
- rcvrVar.Curfn = outer
rcvrAssign = ir.NewAssignStmt(pos, rcvrVar, rcvrValue)
rcvrAssign.SetTypecheck(1)
rcvrVar.Defn = rcvrAssign
- outer.Dcl = append(outer.Dcl, rcvrVar)
+ if outer == nil {
+ rcvrVar.Class = ir.PEXTERN
+ g.target.Decls = append(g.target.Decls, rcvrAssign)
+ g.target.Externs = append(g.target.Externs, rcvrVar)
+ } else {
+ rcvrVar.Class = ir.PAUTO
+ rcvrVar.Curfn = outer
+ outer.Dcl = append(outer.Dcl, rcvrVar)
+ }
}
// Build body of closure. This involves just calling the wrapped function directly
diff --git a/test/typeparam/issue48225.go b/test/typeparam/issue48225.go
new file mode 100644
index 0000000000..887ffd8a84
--- /dev/null
+++ b/test/typeparam/issue48225.go
@@ -0,0 +1,37 @@
+// 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
+
+import "reflect"
+
+type Foo[T any] struct {
+ val int
+}
+
+func (foo Foo[T]) Get() *T {
+ if foo.val != 1 {
+ panic("bad val field in Foo receiver")
+ }
+ return new(T)
+}
+
+var (
+ newInt = Foo[int]{val: 1}.Get
+ newString = Foo[string]{val: 1}.Get
+)
+
+func main() {
+ i := newInt()
+ s := newString()
+
+ if t := reflect.TypeOf(i).String(); t != "*int" {
+ panic(t)
+ }
+ if t := reflect.TypeOf(s).String(); t != "*string" {
+ panic(t)
+ }
+}