Skip to content

Commit acb129c

Browse files
committed
Add temp cleanups for copy/move mode args when other args fail. Fixes rust-lang#1374
1 parent f3ca50c commit acb129c

File tree

2 files changed

+29
-5
lines changed

2 files changed

+29
-5
lines changed

src/comp/middle/trans/base.rs

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2563,8 +2563,10 @@ fn trans_cast(cx: block, e: @ast::expr, id: ast::node_id,
25632563
ret store_in_dest(e_res.bcx, newval, dest);
25642564
}
25652565

2566-
fn trans_arg_expr(cx: block, arg: ty::arg, lldestty: TypeRef,
2567-
e: @ast::expr) -> result {
2566+
// temp_cleanups: cleanups that should run only if failure occurs before the
2567+
// call takes place:
2568+
fn trans_arg_expr(cx: block, arg: ty::arg, lldestty: TypeRef, e: @ast::expr,
2569+
&temp_cleanups: [ValueRef]) -> result {
25682570
let ccx = cx.ccx();
25692571
let e_ty = expr_ty(cx, e);
25702572
let is_bot = ty::type_is_bot(e_ty);
@@ -2612,6 +2614,11 @@ fn trans_arg_expr(cx: block, arg: ty::arg, lldestty: TypeRef,
26122614
if lv.kind != temporary && !move_out {
26132615
bcx = take_ty(bcx, val, e_ty);
26142616
}
2617+
2618+
// In the event that failure occurs before the call actually
2619+
// happens, have to cleanup this copy:
2620+
add_clean_temp_mem(bcx, val, e_ty);
2621+
temp_cleanups += [val];
26152622
} else if ty::type_is_immediate(e_ty) && lv.kind != owned {
26162623
let r = do_spill(bcx, val, e_ty);
26172624
val = r.val;
@@ -2638,6 +2645,7 @@ fn trans_args(cx: block, llenv: ValueRef,
26382645
args: [ValueRef],
26392646
retslot: ValueRef} {
26402647

2648+
let temp_cleanups = [];
26412649
let args = ty::ty_fn_args(fn_ty);
26422650
let llargs: [ValueRef] = [];
26432651
let lltydescs: [ValueRef] = [];
@@ -2718,11 +2726,19 @@ fn trans_args(cx: block, llenv: ValueRef,
27182726
let arg_tys = type_of_explicit_args(ccx, args);
27192727
let i = 0u;
27202728
for e: @ast::expr in es {
2721-
let r = trans_arg_expr(bcx, args[i], arg_tys[i], e);
2729+
let r = trans_arg_expr(bcx, args[i], arg_tys[i], e, temp_cleanups);
27222730
bcx = r.bcx;
27232731
llargs += [r.val];
27242732
i += 1u;
27252733
}
2734+
2735+
// now that all arguments have been successfully built, we can revoke any
2736+
// temporary cleanups, as they are only needed if argument construction
2737+
// should fail (for example, cleanup of copy mode args).
2738+
vec::iter(temp_cleanups) {|c|
2739+
revoke_clean(bcx, c)
2740+
}
2741+
27262742
ret {bcx: bcx,
27272743
args: llargs,
27282744
retslot: llretslot};

src/comp/middle/trans/impl.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,16 @@ fn trans_impl(ccx: crate_ctxt, path: path, name: ast::ident,
6363
fn trans_self_arg(bcx: block, base: @ast::expr) -> result {
6464
let basety = expr_ty(bcx, base);
6565
let m_by_ref = ast::expl(ast::by_ref);
66-
trans_arg_expr(bcx, {mode: m_by_ref, ty: basety},
67-
T_ptr(type_of_or_i8(bcx.ccx(), basety)), base)
66+
let temp_cleanups = [];
67+
let result = trans_arg_expr(bcx, {mode: m_by_ref, ty: basety},
68+
T_ptr(type_of_or_i8(bcx.ccx(), basety)), base,
69+
temp_cleanups);
70+
71+
// by-ref self argument should not require cleanup in the case of
72+
// other arguments failing:
73+
assert temp_cleanups == [];
74+
75+
ret result;
6876
}
6977

7078
fn trans_method_callee(bcx: block, callee_id: ast::node_id,

0 commit comments

Comments
 (0)