diff --git a/src/comp/middle/trans_comm.rs b/src/comp/middle/trans_comm.rs index 17285b9f1c41..133e2a33c591 100644 --- a/src/comp/middle/trans_comm.rs +++ b/src/comp/middle/trans_comm.rs @@ -229,19 +229,32 @@ fn trans_send(cx: &@block_ctxt, lhs: &@ast::expr, rhs: &@ast::expr, fn trans_recv(cx: &@block_ctxt, lhs: &@ast::expr, rhs: &@ast::expr, id: ast::node_id) -> result { let bcx = cx; - let data = trans_lval(bcx, rhs); - assert (data.is_mem); - bcx = data.res.bcx; // FIXME: calculate copy init-ness in typestate. + let unit_ty = node_id_type(cx.fcx.lcx.ccx, id); + let tmp_alloc = alloc_ty(bcx, unit_ty); + bcx = tmp_alloc.bcx; + let prt = trans_expr(bcx, lhs); bcx = prt.bcx; - let lldataptr = bcx.build.PointerCast(data.res.val, T_ptr(T_ptr(T_i8()))); + let lldataptr = bcx.build.PointerCast(tmp_alloc.val, + T_ptr(T_ptr(T_i8()))); let llportptr = bcx.build.PointerCast(prt.val, T_opaque_port_ptr()); bcx.build.Call(bcx.fcx.lcx.ccx.upcalls.recv, ~[bcx.fcx.lltaskptr, lldataptr, llportptr]); - ret rslt(bcx, data.res.val); + let tmp = load_if_immediate(bcx, tmp_alloc.val, unit_ty); + + let data = trans_lval(bcx, rhs); + assert (data.is_mem); + bcx = data.res.bcx; + + let tmp_lval = lval_val(bcx, tmp); + + let recv_res = + move_val(bcx, DROP_EXISTING, data.res.val, tmp_lval, unit_ty); + + ret rslt(recv_res.bcx, recv_res.val); } // Does a deep copy of a value. This is needed for passing arguments to child diff --git a/src/test/run-pass/chan-leak.rs b/src/test/run-pass/chan-leak.rs new file mode 100644 index 000000000000..c23b746ad214 --- /dev/null +++ b/src/test/run-pass/chan-leak.rs @@ -0,0 +1,36 @@ +// Issue #763 + +use std; +import std::task; + +tag request { + quit; + close(chan[bool]); +} + +type ctx = chan[request]; + +fn request_task(c: chan[ctx]) { + let p: port[request] = port(); + c <| chan(p); + let req: request; + p |> req; + // Need to drop req before receiving it again + p |> req; +} + +fn new() -> ctx { + let p: port[ctx] = port(); + let t = spawn request_task(chan(p)); + let cx: ctx; + p |> cx; + ret cx; +} + +fn main() { + let cx = new(); + + let p: port[bool] = port(); + cx <| close(chan(p)); + cx <| quit; +} diff --git a/src/test/run-pass/task-comm-10.rs b/src/test/run-pass/task-comm-10.rs index ad096c488627..02c636f7c634 100644 --- a/src/test/run-pass/task-comm-10.rs +++ b/src/test/run-pass/task-comm-10.rs @@ -6,15 +6,14 @@ import std::task; fn start(c: chan[chan[str]]) { let p: port[str]; + let a; + let b; p = port(); c <| chan(p); p |> a; log_err a; p |> b; log_err b; - - let a; - let b; } fn main() {