miniExpr
Func *Func `mknode:"-"`
Prealloc *Name
+ IsGoWrap bool // whether this is wrapper closure of a go statement
}
func NewClosureExpr(pos src.XPos, fn *Func) *ClosureExpr {
base.WarnfAt(clo.Pos(), "stack closure, captured vars = %v", clo.Func.ClosureVars)
}
}
- if base.Flag.CompilingRuntime && clo.Esc() == EscHeap {
- base.ErrorfAt(clo.Pos(), "heap-allocated closure, not allowed in runtime")
+ if base.Flag.CompilingRuntime && clo.Esc() == EscHeap && !clo.IsGoWrap {
+ base.ErrorfAt(clo.Pos(), "heap-allocated closure %s, not allowed in runtime", FuncName(clo.Func))
}
}
// only in-register results?
if len(callArgs) == 0 && call.Op() == ir.OCALLFUNC && callX.Type().NumResults() == 0 {
if c, ok := call.(*ir.CallExpr); ok && callX != nil && callX.Op() == ir.OCLOSURE {
- cloFunc := callX.(*ir.ClosureExpr).Func
- cloFunc.SetClosureCalled(false)
+ clo := callX.(*ir.ClosureExpr)
+ clo.Func.SetClosureCalled(false)
+ clo.IsGoWrap = true
c.PreserveClosure = true
}
return
// Set escape properties for closure.
if n.Op() == ir.OGO {
- // For "go", assume that the closure is going to escape
- // (with an exception for the runtime, which doesn't
- // permit heap-allocated closures).
- if base.Ctxt.Pkgpath != "runtime" {
- clo.SetEsc(ir.EscHeap)
- }
+ // For "go", assume that the closure is going to escape.
+ clo.SetEsc(ir.EscHeap)
+ clo.IsGoWrap = true
} else {
// For defer, just use whatever result escape analysis
// has determined for the defer.
package p
func f(x int) func(int) int {
- return func(y int) int { return x + y } // ERROR "heap-allocated closure, not allowed in runtime"
+ return func(y int) int { return x + y } // ERROR "heap-allocated closure f\.func1, not allowed in runtime"
}
func g(x int) func(int) int { // ERROR "x escapes to heap, not allowed in runtime"
- return func(y int) int { // ERROR "heap-allocated closure, not allowed in runtime"
+ return func(y int) int { // ERROR "heap-allocated closure g\.func1, not allowed in runtime"
x += y
return x + y
}