Drop the previous reference when receiving. Closes #763

This commit is contained in:
Brian Anderson 2011-07-28 18:01:27 -07:00
parent bf99573860
commit 3896524750
3 changed files with 56 additions and 8 deletions

View file

@ -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

View 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;
}

View file

@ -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() {