diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index db06a6ca6cda..53f8b0b0d347 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -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); } diff --git a/src/comp/middle/trans_alt.rs b/src/comp/middle/trans_alt.rs index c77a34512668..899ba437cb19 100644 --- a/src/comp/middle/trans_alt.rs +++ b/src/comp/middle/trans_alt.rs @@ -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(_) {} } diff --git a/src/test/run-pass/let-destruct-fresh-mem.rs b/src/test/run-pass/let-destruct-fresh-mem.rs new file mode 100644 index 000000000000..fa2798ecc66a --- /dev/null +++ b/src/test/run-pass/let-destruct-fresh-mem.rs @@ -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; +}