Skip to content

Commit 12c68bc

Browse files
committed
make sure we do not bind unique closures (or blocks, for that matter)
1 parent 8478349 commit 12c68bc

File tree

3 files changed

+43
-10
lines changed

3 files changed

+43
-10
lines changed

src/comp/middle/typeck.rs

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2394,6 +2394,16 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
23942394
_ { fail "LHS of bind expr didn't have a function type?!"; }
23952395
}
23962396

2397+
let proto = alt proto {
2398+
ast::proto_bare | ast::proto_box { ast::proto_box }
2399+
ast::proto_uniq | ast::proto_any | ast::proto_block {
2400+
tcx.sess.span_err(expr.span,
2401+
#fmt["cannot bind %s closures",
2402+
proto_to_str(proto)]);
2403+
proto // dummy value so compilation can proceed
2404+
}
2405+
};
2406+
23972407
// For each blank argument, add the type of that argument
23982408
// to the resulting function type.
23992409
let out_args = [];
@@ -2406,16 +2416,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
24062416
i += 1u;
24072417
}
24082418

2409-
// Determine what fn prototype results from binding
2410-
fn lower_bound_proto(proto: ast::proto) -> ast::proto {
2411-
// FIXME: This is right for bare fns, possibly not others
2412-
alt proto {
2413-
ast::proto_bare { ast::proto_box }
2414-
_ { proto }
2415-
}
2416-
}
2417-
2418-
let ft = ty::mk_fn(tcx, {proto: lower_bound_proto(proto),
2419+
let ft = ty::mk_fn(tcx, {proto: proto,
24192420
inputs: out_args, output: rt,
24202421
ret_style: cf, constraints: constrs});
24212422
write_ty(tcx, id, ft);
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
fn foo(x: fn()) {
2+
bind x(); //! ERROR cannot bind fn closures
3+
}
4+
5+
fn bar(x: fn&()) {
6+
bind x(); //! ERROR cannot bind fn& closures
7+
}
8+
9+
fn main() {
10+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// -*- rust -*-
2+
3+
// I originally made this test to ensure that bind does the right
4+
// thing when binding a unique closure (which is to copy the closure,
5+
// I suppose?). But I've since decided it's not worth the effort, and
6+
// so I just made it a simple error. But I left the test as is in
7+
// case we ever decide that bind should work with unique closures,
8+
// though a simpler test would suffice for now.
9+
10+
fn make_addr(-x: ~int) -> fn~() -> uint {
11+
(fn~[move x]() -> uint { ptr::addr_of(*x) as uint })
12+
}
13+
14+
fn main() {
15+
let x = ~3;
16+
let a = ptr::addr_of(*x) as uint;
17+
let adder: fn~() -> uint = make_addr(x);
18+
let bound_adder: fn~() -> uint = bind adder();
19+
//!^ ERROR cannot bind fn~ closures
20+
assert adder() == a;
21+
assert bound_adder() != a;
22+
}

0 commit comments

Comments
 (0)