Copy locals created by destructuring on the content of a box
This is required so that assigning to these locals doesn't clobber the content of the box. (A possible optimization would be to only do this copying for locals that actually are assigned to.)
This commit is contained in:
parent
043d95a2bd
commit
f8fa574864
3 changed files with 29 additions and 8 deletions
|
|
@ -3631,7 +3631,7 @@ fn trans_for(cx: &@block_ctxt, local: &@ast::local, seq: &@ast::expr,
|
|||
let loc_r = copy_val(local_res.bcx, INIT, local_res.val, curr, t);
|
||||
add_clean(scope_cx, local_res.val, t);
|
||||
let bcx = trans_alt::bind_irrefutable_pat
|
||||
(loc_r.bcx, local.node.pat, local_res.val, cx.fcx.lllocals);
|
||||
(loc_r.bcx, local.node.pat, local_res.val, cx.fcx.lllocals, false);
|
||||
bcx = trans_block(bcx, body, return).bcx;
|
||||
if !bcx.build.is_terminated() {
|
||||
bcx.build.Br(next_cx.llbb);
|
||||
|
|
@ -3982,7 +3982,7 @@ fn trans_for_each(cx: &@block_ctxt, local: &@ast::local, seq: &@ast::expr,
|
|||
// Add bindings for the loop variable alias.
|
||||
bcx = trans_alt::bind_irrefutable_pat
|
||||
(bcx, local.node.pat, llvm::LLVMGetParam(fcx.llfn, 3u),
|
||||
bcx.fcx.llupvars);
|
||||
bcx.fcx.llupvars, false);
|
||||
let lltop = bcx.llbb;
|
||||
let r = trans_block(bcx, body, return);
|
||||
finish_fn(fcx, lltop);
|
||||
|
|
@ -5949,7 +5949,7 @@ fn init_local(bcx: @block_ctxt, local: &@ast::local) -> result {
|
|||
_ { bcx = zero_alloca(bcx, llptr, ty).bcx; }
|
||||
}
|
||||
bcx = trans_alt::bind_irrefutable_pat(bcx, local.node.pat, llptr,
|
||||
bcx.fcx.lllocals);
|
||||
bcx.fcx.lllocals, false);
|
||||
ret rslt(bcx, llptr);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -437,12 +437,23 @@ fn trans_alt(cx: &@block_ctxt, expr: &@ast::expr, arms: &ast::arm[],
|
|||
|
||||
// Not alt-related, but similar to the pattern-munging code above
|
||||
fn bind_irrefutable_pat(bcx: @block_ctxt, pat: &@ast::pat, val: ValueRef,
|
||||
table: hashmap[ast::node_id, ValueRef])
|
||||
table: hashmap[ast::node_id, ValueRef], copy: bool)
|
||||
-> @block_ctxt {
|
||||
let ccx = bcx.fcx.lcx.ccx;
|
||||
alt pat.node {
|
||||
ast::pat_bind(_) {
|
||||
table.insert(pat.id, val);
|
||||
if copy {
|
||||
let ty = ty::node_id_to_monotype(ccx.tcx, pat.id);
|
||||
let llty = trans::type_of(ccx, pat.span, ty);
|
||||
let alloc = trans::alloca(bcx, llty);
|
||||
bcx = trans::memmove_ty(bcx, alloc, val, ty).bcx;
|
||||
let loaded = trans::load_if_immediate(bcx, alloc, ty);
|
||||
bcx = trans::copy_ty(bcx, loaded, ty).bcx;
|
||||
table.insert(pat.id, alloc);
|
||||
trans_common::add_clean(bcx, alloc, ty);
|
||||
} else {
|
||||
table.insert(pat.id, val);
|
||||
}
|
||||
}
|
||||
ast::pat_tag(_, sub) {
|
||||
if ivec::len(sub) == 0u { ret bcx; }
|
||||
|
|
@ -450,7 +461,7 @@ fn bind_irrefutable_pat(bcx: @block_ctxt, pat: &@ast::pat, val: ValueRef,
|
|||
let args = extract_variant_args(bcx, pat.id, vdefs, val);
|
||||
let i = 0;
|
||||
for argval: ValueRef in args.vals {
|
||||
bcx = bind_irrefutable_pat(bcx, sub.(i), argval, table);
|
||||
bcx = bind_irrefutable_pat(bcx, sub.(i), argval, table, copy);
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
|
|
@ -462,14 +473,14 @@ fn bind_irrefutable_pat(bcx: @block_ctxt, pat: &@ast::pat, val: ValueRef,
|
|||
let ix: uint =
|
||||
ty::field_idx(ccx.sess, pat.span, f.ident, rec_fields);
|
||||
let r = trans::GEP_tup_like(bcx, rec_ty, val, ~[0, ix as int]);
|
||||
bcx = bind_irrefutable_pat(r.bcx, f.pat, r.val, table);
|
||||
bcx = bind_irrefutable_pat(r.bcx, f.pat, r.val, table, copy);
|
||||
}
|
||||
}
|
||||
ast::pat_box(inner) {
|
||||
let box = bcx.build.Load(val);
|
||||
let unboxed = bcx.build.InBoundsGEP
|
||||
(box, ~[C_int(0), C_int(back::abi::box_rc_field_body)]);
|
||||
bcx = bind_irrefutable_pat(bcx, inner, unboxed, table);
|
||||
bcx = bind_irrefutable_pat(bcx, inner, unboxed, table, true);
|
||||
}
|
||||
ast::pat_wild. | ast::pat_lit(_) {}
|
||||
}
|
||||
|
|
|
|||
10
src/test/run-pass/let-destruct-fresh-mem.rs
Normal file
10
src/test/run-pass/let-destruct-fresh-mem.rs
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
fn main() {
|
||||
let u = {x: 10, y: @{a: 20}};
|
||||
let {x, y: @{a}} = u;
|
||||
x = 100;
|
||||
a = 100;
|
||||
assert x == 100;
|
||||
assert a == 100;
|
||||
assert u.x == 10;
|
||||
assert u.y.a == 20;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue