return walkexpr(clos, init)
}
+
+// callpartMethod returns the *types.Field representing the method
+// referenced by method value n.
+func callpartMethod(n *Node) *types.Field {
+ if n.Op != OCALLPART {
+ Fatalf("expected OCALLPART, got %v", n)
+ }
+
+ // TODO(mdempsky): Optimize this. If necessary,
+ // makepartialcall could save m for us somewhere.
+ var m *types.Field
+ if lookdot0(n.Right.Sym, n.Left.Type, &m, false) != 1 {
+ Fatalf("failed to find field for OCALLPART")
+ }
+
+ return m
+}
// nop
case OCALLPART:
- e.spill(k, n)
+ // Flow the receiver argument to both the closure and
+ // to the receiver parameter.
+
+ closureK := e.spill(k, n)
+
+ m := callpartMethod(n)
+
+ // We don't know how the method value will be called
+ // later, so conservatively assume the result
+ // parameters all flow to the heap.
+ //
+ // TODO(mdempsky): Change ks into a callback, so that
+ // we don't have to create this dummy slice?
+ var ks []EscHole
+ for i := m.Type.NumResults(); i > 0; i-- {
+ ks = append(ks, e.heapHole())
+ }
+ paramK := e.tagHole(ks, asNode(m.Type.Nname()), m.Type.Recv())
- // TODO(mdempsky): We can do better here. See #27557.
- e.assignHeap(n.Left, "call part", n)
+ e.expr(e.teeHole(paramK, closureK), n.Left)
case OPTRLIT:
e.expr(e.spill(k, n), n.Left)
min = m
}
}
+ case OCALLPART:
+ fn := asNode(callpartMethod(n).Type.Nname())
+ if fn != nil && fn.Op == ONAME && fn.Class() == PFUNC && fn.Name.Defn != nil {
+ if m := v.visit(fn.Name.Defn); m < min {
+ min = m
+ }
+ }
case OCLOSURE:
if m := v.visit(n.Func.Closure); m < min {
min = m
func foo141() {
var f func()
- // BAD: new(Tm) should not escape
- t := new(Tm) // ERROR "new\(Tm\) escapes to heap$"
+ t := new(Tm) // ERROR "new\(Tm\) does not escape$"
f = t.M // ERROR "t.M does not escape$"
_ = f
}
func foo141() {
var f func()
- // BAD: new(Tm) should not escape
- t := new(Tm) // ERROR "new\(Tm\) escapes to heap$"
+ t := new(Tm) // ERROR "new\(Tm\) does not escape$"
f = t.M // ERROR "t.M does not escape$"
_ = f
}
var N int
func F1() {
- // BAD: s should not escape
- var s S // ERROR "moved to heap: s"
+ var s S
for i := 0; i < N; i++ {
fs := []func(){ // ERROR "\[\]func\(\) literal does not escape"
s.Inc, // ERROR "s.Inc does not escape"
}
func F2() {
- // BAD: s should not escape
- var s S // ERROR "moved to heap: s"
+ var s S
for i := 0; i < N; i++ {
for _, f := range []func(){ // ERROR "\[\]func\(\) literal does not escape"
s.Inc, // ERROR "s.Inc does not escape"
var sink interface{}
func _() {
- // BAD: t should not escape
- var t T // ERROR "moved to heap"
+ var t T
f := t.noescape // ERROR "t.noescape does not escape"
f()
}