1
0
mirror of https://github.com/golang/go synced 2024-09-29 18:24:29 -06:00

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>
This commit is contained in:
korzhao 2021-09-09 21:51:43 +08:00 committed by Dan Scales
parent 2c4f389c02
commit c981874a5a
2 changed files with 46 additions and 3 deletions

View 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

View File

@ -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)
}
}