]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: fix implement for closure in a global assignment
authorkorzhao <korzhao95@gmail.com>
Thu, 9 Sep 2021 13:51:43 +0000 (21:51 +0800)
committerDan Scales <danscales@google.com>
Thu, 9 Sep 2021 21:28:56 +0000 (21:28 +0000)
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>

src/cmd/compile/internal/noder/stencil.go
test/typeparam/issue48225.go [new file with mode: 0644]

index a524ddc2a086f38ad1fa046abcfcde3efe1a24f0..5069db9fe1b888f6267d69919a9727b7609f8e8d 100644 (file)
@@ -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 (file)
index 0000000..887ffd8
--- /dev/null
@@ -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)
+       }
+}