diff --git a/src/cmd/compile/internal/escape/escape.go b/src/cmd/compile/internal/escape/escape.go index 5df82d8cdc..9b9b8f6a58 100644 --- a/src/cmd/compile/internal/escape/escape.go +++ b/src/cmd/compile/internal/escape/escape.go @@ -583,6 +583,9 @@ func (e *escape) exprSkipInit(k hole, n ir.Node) { if n.Class == ir.PFUNC || n.Class == ir.PEXTERN { return } + if n.IsClosureVar() && n.Defn == nil { + return // ".this" from method value wrapper + } e.flow(k, e.oldLoc(n)) case ir.ONAMEOFFSET: diff --git a/src/cmd/compile/internal/ir/name.go b/src/cmd/compile/internal/ir/name.go index a51cf79929..cfb481e31c 100644 --- a/src/cmd/compile/internal/ir/name.go +++ b/src/cmd/compile/internal/ir/name.go @@ -264,7 +264,7 @@ const ( nameNeedzero // if it contains pointers, needs to be zeroed on function entry nameAutoTemp // is the variable a temporary (implies no dwarf info. reset if escapes to heap) nameUsed // for variable declared and not used error - nameIsClosureVar // PAUTOHEAP closure pseudo-variable; original at n.Name.Defn + nameIsClosureVar // PAUTOHEAP closure pseudo-variable; original (if any) at n.Defn nameIsOutputParamHeapAddr // pointer to a result parameter's heap copy nameAddrtaken // address taken, even if not moved to heap nameInlFormal // PAUTO created by inliner, derived from callee formal @@ -332,7 +332,7 @@ func (n *Name) SetVal(v constant.Value) { // it appears in the function that immediately contains the // declaration. Otherwise, Canonical simply returns n itself. func (n *Name) Canonical() *Name { - if n.IsClosureVar() { + if n.IsClosureVar() && n.Defn != nil { n = n.Defn.(*Name) } return n diff --git a/src/cmd/compile/internal/typecheck/func.go b/src/cmd/compile/internal/typecheck/func.go index 8789395ffb..12762f7ee8 100644 --- a/src/cmd/compile/internal/typecheck/func.go +++ b/src/cmd/compile/internal/typecheck/func.go @@ -246,29 +246,26 @@ func MethodValueWrapper(dot *ir.SelectorExpr) *ir.Func { fn.SetWrapper(true) // Declare and initialize variable holding receiver. - cr := ir.NewClosureRead(rcvrtype, types.Rnd(int64(types.PtrSize), int64(rcvrtype.Align))) - var ptr *ir.Name - var body []ir.Node - if rcvrtype.IsPtr() || rcvrtype.IsInterface() { - ptr = Temp(rcvrtype) - body = append(body, ir.NewAssignStmt(base.Pos, ptr, cr)) - } else { - ptr = Temp(types.NewPtr(rcvrtype)) - body = append(body, ir.NewAssignStmt(base.Pos, ptr, NodAddr(cr))) - } + ptr := ir.NewNameAt(base.Pos, Lookup(".this")) + ptr.Class = ir.PAUTOHEAP + ptr.SetType(rcvrtype) + ptr.Curfn = fn + ptr.SetIsClosureVar(true) + ptr.SetByval(true) + fn.ClosureVars = append(fn.ClosureVars, ptr) call := ir.NewCallExpr(base.Pos, ir.OCALL, ir.NewSelectorExpr(base.Pos, ir.OXDOT, ptr, meth), nil) call.Args = ir.ParamNames(tfn.Type()) call.IsDDD = tfn.Type().IsVariadic() + + var body ir.Node = call if t0.NumResults() != 0 { ret := ir.NewReturnStmt(base.Pos, nil) ret.Results = []ir.Node{call} - body = append(body, ret) - } else { - body = append(body, call) + body = ret } - fn.Body = body + fn.Body = []ir.Node{body} FinishFuncBody() Func(fn)