Skip to content

Commit 3896524

Browse files
committed
Drop the previous reference when receiving. Closes #763
1 parent bf99573 commit 3896524

File tree

3 files changed

+56
-8
lines changed

3 files changed

+56
-8
lines changed

src/comp/middle/trans_comm.rs

+18-5
Original file line numberDiff line numberDiff line change
@@ -229,19 +229,32 @@ fn trans_send(cx: &@block_ctxt, lhs: &@ast::expr, rhs: &@ast::expr,
229229
fn trans_recv(cx: &@block_ctxt, lhs: &@ast::expr, rhs: &@ast::expr,
230230
id: ast::node_id) -> result {
231231
let bcx = cx;
232-
let data = trans_lval(bcx, rhs);
233-
assert (data.is_mem);
234-
bcx = data.res.bcx;
235232
// FIXME: calculate copy init-ness in typestate.
236233

234+
let unit_ty = node_id_type(cx.fcx.lcx.ccx, id);
235+
let tmp_alloc = alloc_ty(bcx, unit_ty);
236+
bcx = tmp_alloc.bcx;
237+
237238
let prt = trans_expr(bcx, lhs);
238239
bcx = prt.bcx;
239-
let lldataptr = bcx.build.PointerCast(data.res.val, T_ptr(T_ptr(T_i8())));
240+
let lldataptr = bcx.build.PointerCast(tmp_alloc.val,
241+
T_ptr(T_ptr(T_i8())));
240242
let llportptr = bcx.build.PointerCast(prt.val, T_opaque_port_ptr());
241243
bcx.build.Call(bcx.fcx.lcx.ccx.upcalls.recv,
242244
~[bcx.fcx.lltaskptr, lldataptr, llportptr]);
243245

244-
ret rslt(bcx, data.res.val);
246+
let tmp = load_if_immediate(bcx, tmp_alloc.val, unit_ty);
247+
248+
let data = trans_lval(bcx, rhs);
249+
assert (data.is_mem);
250+
bcx = data.res.bcx;
251+
252+
let tmp_lval = lval_val(bcx, tmp);
253+
254+
let recv_res =
255+
move_val(bcx, DROP_EXISTING, data.res.val, tmp_lval, unit_ty);
256+
257+
ret rslt(recv_res.bcx, recv_res.val);
245258
}
246259

247260
// Does a deep copy of a value. This is needed for passing arguments to child

src/test/run-pass/chan-leak.rs

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// Issue #763
2+
3+
use std;
4+
import std::task;
5+
6+
tag request {
7+
quit;
8+
close(chan[bool]);
9+
}
10+
11+
type ctx = chan[request];
12+
13+
fn request_task(c: chan[ctx]) {
14+
let p: port[request] = port();
15+
c <| chan(p);
16+
let req: request;
17+
p |> req;
18+
// Need to drop req before receiving it again
19+
p |> req;
20+
}
21+
22+
fn new() -> ctx {
23+
let p: port[ctx] = port();
24+
let t = spawn request_task(chan(p));
25+
let cx: ctx;
26+
p |> cx;
27+
ret cx;
28+
}
29+
30+
fn main() {
31+
let cx = new();
32+
33+
let p: port[bool] = port();
34+
cx <| close(chan(p));
35+
cx <| quit;
36+
}

src/test/run-pass/task-comm-10.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,14 @@ import std::task;
66
fn start(c: chan[chan[str]]) {
77
let p: port[str];
88

9+
let a;
10+
let b;
911
p = port();
1012
c <| chan(p);
1113
p |> a;
1214
log_err a;
1315
p |> b;
1416
log_err b;
15-
16-
let a;
17-
let b;
1817
}
1918

2019
fn main() {

0 commit comments

Comments
 (0)