Skip to content

Commit 7a336f1

Browse files
committed
modify last use to take into account cap clause, add new test
1 parent 106385c commit 7a336f1

File tree

4 files changed

+68
-10
lines changed

4 files changed

+68
-10
lines changed

src/comp/middle/last_use.rs

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,16 @@ fn visit_expr(ex: @expr, cx: ctx, v: visit::vt<ctx>) {
136136
v.visit_expr(dest, cx, v);
137137
clear_if_path(cx, dest, v, true);
138138
}
139+
expr_fn(_, _, _, cap_clause) {
140+
// n.b.: safe to ignore copies, as if they are unused
141+
// then they are ignored, otherwise they will show up
142+
// as freevars in the body.
143+
144+
vec::iter(cap_clause.moves) {|ci|
145+
clear_def_if_path(cx, cx.def_map.get(ci.id), true);
146+
}
147+
visit::visit_expr(ex, cx, v);
148+
}
139149
expr_call(f, args, _) {
140150
v.visit_expr(f, cx, v);
141151
let i = 0u, fns = [];
@@ -263,18 +273,25 @@ fn clear_in_current(cx: ctx, my_def: node_id, to: bool) {
263273
}
264274
}
265275

276+
fn clear_def_if_path(cx: ctx, d: def, to: bool)
277+
-> option<node_id> {
278+
alt d {
279+
def_local(def_id, let_copy.) | def_arg(def_id, by_copy.) |
280+
def_arg(def_id, by_move.) {
281+
clear_in_current(cx, def_id.node, to);
282+
some(def_id.node)
283+
}
284+
_ {
285+
none
286+
}
287+
}
288+
}
289+
266290
fn clear_if_path(cx: ctx, ex: @expr, v: visit::vt<ctx>, to: bool)
267291
-> option::t<node_id> {
268292
alt ex.node {
269293
expr_path(_) {
270-
alt cx.def_map.get(ex.id) {
271-
def_local(def_id, let_copy.) | def_arg(def_id, by_copy.) |
272-
def_arg(def_id, by_move.) {
273-
clear_in_current(cx, def_id.node, to);
274-
ret option::some(def_id.node);
275-
}
276-
_ {}
277-
}
294+
ret clear_def_if_path(cx, cx.def_map.get(ex.id), to);
278295
}
279296
_ { v.visit_expr(ex, cx, v); }
280297
}

src/comp/middle/trans_closure.rs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import middle::freevars::{get_freevars, freevar_info};
99
import option::{some, none};
1010
import back::abi;
1111
import syntax::codemap::span;
12+
import syntax::print::pprust::expr_to_str;
1213
import back::link::{
1314
mangle_internal_name_by_path,
1415
mangle_internal_name_by_path_and_seq};
@@ -121,6 +122,18 @@ tag environment_value {
121122
env_ref(ValueRef, ty::t, lval_kind);
122123
}
123124

125+
fn ev_to_str(ccx: @crate_ctxt, ev: environment_value) -> str {
126+
alt ev {
127+
env_expr(ex) { expr_to_str(ex) }
128+
env_copy(v, t, lk) { #fmt("copy(%s,%s)", val_str(ccx.tn, v),
129+
ty_to_str(ccx.tcx, t)) }
130+
env_move(v, t, lk) { #fmt("move(%s,%s)", val_str(ccx.tn, v),
131+
ty_to_str(ccx.tcx, t)) }
132+
env_ref(v, t, lk) { #fmt("ref(%s,%s)", val_str(ccx.tn, v),
133+
ty_to_str(ccx.tcx, t)) }
134+
}
135+
}
136+
124137
fn mk_tydesc_ty(tcx: ty::ctxt, ck: ty::closure_kind) -> ty::t {
125138
ret alt ck {
126139
ty::closure_block. | ty::closure_shared. { ty::mk_type(tcx) }
@@ -284,7 +297,7 @@ fn store_environment(
284297
};
285298
}
286299

287-
//let ccx = bcx_ccx(bcx);
300+
let ccx = bcx_ccx(bcx);
288301
let tcx = bcx_tcx(bcx);
289302

290303
// compute the shape of the closure
@@ -351,6 +364,11 @@ fn store_environment(
351364
let {bcx: bcx, val:bindings_slot} =
352365
GEP_tup_like_1(bcx, cboxptr_ty, llbox, [0, abi::cbox_elt_bindings]);
353366
vec::iteri(bound_values) { |i, bv|
367+
if (!ccx.sess.get_opts().no_asm_comments) {
368+
add_comment(bcx, #fmt("Copy %s into closure",
369+
ev_to_str(ccx, bv)));
370+
}
371+
354372
let bound_data = GEPi(bcx, bindings_slot, [0, i as int]);
355373
alt bv {
356374
env_expr(e) {

src/test/run-pass/cap-clause-move.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
// error-pattern: warning: Captured variable 'y' not used in closure
21
fn main() {
32
let x = ~1;
43
let y = ptr::addr_of(*x) as uint;
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
fn main() {
2+
let p = comm::port::<uint>();
3+
let ch = comm::chan(p);
4+
5+
let x = ~1;
6+
let x_in_parent = ptr::addr_of(*x) as uint;
7+
8+
let y = ~2;
9+
let y_in_parent = ptr::addr_of(*y) as uint;
10+
11+
task::spawn(sendfn[copy ch, y; move x]() {
12+
let x_in_child = ptr::addr_of(*x) as uint;
13+
comm::send(ch, x_in_child);
14+
15+
let y_in_child = ptr::addr_of(*y) as uint;
16+
comm::send(ch, y_in_child);
17+
});
18+
19+
let x_in_child = comm::recv(p);
20+
assert x_in_parent == x_in_child;
21+
22+
let y_in_child = comm::recv(p);
23+
assert y_in_parent != y_in_child;
24+
}

0 commit comments

Comments
 (0)