From: Niko Matsakis Date: Sun, 8 Jan 2012 21:32:40 +0000 (-0800) Subject: modify last use to take into account cap clause, add new test X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=7a336f1e7c7c34bb81f80150fb3b04ec0aae14fd;p=rust.git modify last use to take into account cap clause, add new test --- diff --git a/src/comp/middle/last_use.rs b/src/comp/middle/last_use.rs index f783943c0dc..075c40ccfa5 100644 --- a/src/comp/middle/last_use.rs +++ b/src/comp/middle/last_use.rs @@ -136,6 +136,16 @@ fn visit_expr(ex: @expr, cx: ctx, v: visit::vt) { v.visit_expr(dest, cx, v); clear_if_path(cx, dest, v, true); } + expr_fn(_, _, _, cap_clause) { + // n.b.: safe to ignore copies, as if they are unused + // then they are ignored, otherwise they will show up + // as freevars in the body. + + vec::iter(cap_clause.moves) {|ci| + clear_def_if_path(cx, cx.def_map.get(ci.id), true); + } + visit::visit_expr(ex, cx, v); + } expr_call(f, args, _) { v.visit_expr(f, cx, v); let i = 0u, fns = []; @@ -263,18 +273,25 @@ fn clear_in_current(cx: ctx, my_def: node_id, to: bool) { } } +fn clear_def_if_path(cx: ctx, d: def, to: bool) + -> option { + alt d { + def_local(def_id, let_copy.) | def_arg(def_id, by_copy.) | + def_arg(def_id, by_move.) { + clear_in_current(cx, def_id.node, to); + some(def_id.node) + } + _ { + none + } + } +} + fn clear_if_path(cx: ctx, ex: @expr, v: visit::vt, to: bool) -> option::t { alt ex.node { expr_path(_) { - alt cx.def_map.get(ex.id) { - def_local(def_id, let_copy.) | def_arg(def_id, by_copy.) | - def_arg(def_id, by_move.) { - clear_in_current(cx, def_id.node, to); - ret option::some(def_id.node); - } - _ {} - } + ret clear_def_if_path(cx, cx.def_map.get(ex.id), to); } _ { v.visit_expr(ex, cx, v); } } diff --git a/src/comp/middle/trans_closure.rs b/src/comp/middle/trans_closure.rs index 2eb881b09e9..dd343e14b4f 100644 --- a/src/comp/middle/trans_closure.rs +++ b/src/comp/middle/trans_closure.rs @@ -9,6 +9,7 @@ import option::{some, none}; import back::abi; import syntax::codemap::span; +import syntax::print::pprust::expr_to_str; import back::link::{ mangle_internal_name_by_path, mangle_internal_name_by_path_and_seq}; @@ -121,6 +122,18 @@ env_ref(ValueRef, ty::t, lval_kind); } +fn ev_to_str(ccx: @crate_ctxt, ev: environment_value) -> str { + alt ev { + env_expr(ex) { expr_to_str(ex) } + env_copy(v, t, lk) { #fmt("copy(%s,%s)", val_str(ccx.tn, v), + ty_to_str(ccx.tcx, t)) } + env_move(v, t, lk) { #fmt("move(%s,%s)", val_str(ccx.tn, v), + ty_to_str(ccx.tcx, t)) } + env_ref(v, t, lk) { #fmt("ref(%s,%s)", val_str(ccx.tn, v), + ty_to_str(ccx.tcx, t)) } + } +} + fn mk_tydesc_ty(tcx: ty::ctxt, ck: ty::closure_kind) -> ty::t { ret alt ck { ty::closure_block. | ty::closure_shared. { ty::mk_type(tcx) } @@ -284,7 +297,7 @@ fn maybe_clone_tydesc(bcx: @block_ctxt, }; } - //let ccx = bcx_ccx(bcx); + let ccx = bcx_ccx(bcx); let tcx = bcx_tcx(bcx); // compute the shape of the closure @@ -351,6 +364,11 @@ fn maybe_clone_tydesc(bcx: @block_ctxt, let {bcx: bcx, val:bindings_slot} = GEP_tup_like_1(bcx, cboxptr_ty, llbox, [0, abi::cbox_elt_bindings]); vec::iteri(bound_values) { |i, bv| + if (!ccx.sess.get_opts().no_asm_comments) { + add_comment(bcx, #fmt("Copy %s into closure", + ev_to_str(ccx, bv))); + } + let bound_data = GEPi(bcx, bindings_slot, [0, i as int]); alt bv { env_expr(e) { diff --git a/src/test/run-pass/cap-clause-move.rs b/src/test/run-pass/cap-clause-move.rs index 96b4b4d3aaa..a8cca1490fa 100644 --- a/src/test/run-pass/cap-clause-move.rs +++ b/src/test/run-pass/cap-clause-move.rs @@ -1,4 +1,3 @@ -// error-pattern: warning: Captured variable 'y' not used in closure fn main() { let x = ~1; let y = ptr::addr_of(*x) as uint; diff --git a/src/test/run-pass/task-spawn-move-and-copy.rs b/src/test/run-pass/task-spawn-move-and-copy.rs new file mode 100644 index 00000000000..00e86a481d3 --- /dev/null +++ b/src/test/run-pass/task-spawn-move-and-copy.rs @@ -0,0 +1,24 @@ +fn main() { + let p = comm::port::(); + let ch = comm::chan(p); + + let x = ~1; + let x_in_parent = ptr::addr_of(*x) as uint; + + let y = ~2; + let y_in_parent = ptr::addr_of(*y) as uint; + + task::spawn(sendfn[copy ch, y; move x]() { + let x_in_child = ptr::addr_of(*x) as uint; + comm::send(ch, x_in_child); + + let y_in_child = ptr::addr_of(*y) as uint; + comm::send(ch, y_in_child); + }); + + let x_in_child = comm::recv(p); + assert x_in_parent == x_in_child; + + let y_in_child = comm::recv(p); + assert y_in_parent != y_in_child; +}