Drop the previous reference when receiving. Closes #763
This commit is contained in:
parent
bf99573860
commit
3896524750
3 changed files with 56 additions and 8 deletions
|
|
@ -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
|
||||
|
|
|
|||
36
src/test/run-pass/chan-leak.rs
Normal file
36
src/test/run-pass/chan-leak.rs
Normal file
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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() {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue