From fa7db7ba5d6240b682a09386982161fc1db4d152 Mon Sep 17 00:00:00 2001 From: Eric Holk Date: Wed, 13 Jun 2012 13:45:12 -0700 Subject: [PATCH] Generate a temporary for assign_ops. Issue #2581 --- src/rustc/middle/trans/base.rs | 14 +++- .../run-pass/operator-overloading-leaks.rs | 74 +++++++++++++++++++ 2 files changed, 86 insertions(+), 2 deletions(-) create mode 100644 src/test/run-pass/operator-overloading-leaks.rs diff --git a/src/rustc/middle/trans/base.rs b/src/rustc/middle/trans/base.rs index 9eff04e523751..94bbb740cce04 100644 --- a/src/rustc/middle/trans/base.rs +++ b/src/rustc/middle/trans/base.rs @@ -1436,6 +1436,7 @@ fn copy_val_no_check(bcx: block, action: copy_action, dst: ValueRef, // doesn't need to be dropped. (Issue #839) fn move_val(cx: block, action: copy_action, dst: ValueRef, src: lval_result, t: ty::t) -> block { + assert !cx.terminated; let _icx = cx.insn_ctxt("move_val"); let mut src_val = src.val; let tcx = cx.tcx(); @@ -1718,7 +1719,11 @@ fn trans_assign_op(bcx: block, ex: @ast::expr, op: ast::binop, some(origin) { let callee_id = ast_util::op_expr_callee_id(ex); let fty = node_id_type(bcx, callee_id); - ret trans_call_inner( + + let dty = expr_ty(bcx, dst); + let target = alloc_ty(bcx, dty); + + let bcx = trans_call_inner( bcx, ex.info(), fty, expr_ty(bcx, ex), {|bcx| @@ -1726,7 +1731,12 @@ fn trans_assign_op(bcx: block, ex: @ast::expr, op: ast::binop, // #2528 impl::trans_method_callee(bcx, callee_id, dst, origin) }, - arg_exprs([src]), save_in(lhs_res.val)); + arg_exprs([src]), save_in(target)); + + ret move_val(bcx, DROP_EXISTING, lhs_res.val, + // FIXME: should kind be owned? + {bcx: bcx, val: target, kind: owned}, + dty); } _ {} } diff --git a/src/test/run-pass/operator-overloading-leaks.rs b/src/test/run-pass/operator-overloading-leaks.rs new file mode 100644 index 0000000000000..a67bffa2e92e5 --- /dev/null +++ b/src/test/run-pass/operator-overloading-leaks.rs @@ -0,0 +1,74 @@ +// The cases commented as "Leaks" need to not leak. Issue #2581 + +impl methods for [T] { + fn -(x: [T]/&) -> [T] { + [x[0], x[0], x[0]] + } + + fn foo(x: [T]/&) -> [T] { + [x[0], x[0], x[0]] + } +} + +impl methods for ~T { + fn +(rhs: ~T) -> ~T { + rhs + } +} + +impl methods for ~int { + fn -(rhs: ~int) -> ~int { + ~(*self - *rhs) + } +} + +impl methods for @int { + fn +(rhs: @int) -> @int { + @(*self + *rhs) + } +} + +fn main() { + // leaks + let mut bar = [1, 2, 3]; + bar -= [3, 2, 1]; + bar -= [4, 5, 6]; + + io::println(#fmt("%?", bar)); + + // okay + let mut bar = [1, 2, 3]; + bar = bar.foo([3, 2, 1]); + bar = bar.foo([4, 5, 6]); + + io::println(#fmt("%?", bar)); + + // okay + let mut bar = [1, 2, 3]; + bar = bar - [3, 2, 1]; + bar = bar - [4, 5, 6]; + + io::println(#fmt("%?", bar)); + + // Leaks + let mut bar = ~1; + bar += ~2; + bar += ~3; + + io:: println(#fmt("%?", bar)); + + // Leaks + let mut bar = ~1; + bar -= ~2; + bar -= ~3; + + io:: println(#fmt("%?", bar)); + + // Leaks + let mut bar = @1; + bar += @2; + bar += @3; + + io:: println(#fmt("%?", bar)); + +}