From 12c68bcd6df325cc369adce018c07dfe3e2b767a Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Wed, 11 Jan 2012 13:24:30 -0800 Subject: [PATCH] make sure we do not bind unique closures (or blocks, for that matter) --- src/comp/middle/typeck.rs | 21 ++++++++++--------- src/test/compile-fail/bind-stack-closure.rs | 10 +++++++++ src/test/compile-fail/bind-unique-closure.rs | 22 ++++++++++++++++++++ 3 files changed, 43 insertions(+), 10 deletions(-) create mode 100644 src/test/compile-fail/bind-stack-closure.rs create mode 100644 src/test/compile-fail/bind-unique-closure.rs diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index 40cd1d37a8d4..e1c56b9fc549 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -2394,6 +2394,16 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier, _ { fail "LHS of bind expr didn't have a function type?!"; } } + let proto = alt proto { + ast::proto_bare | ast::proto_box { ast::proto_box } + ast::proto_uniq | ast::proto_any | ast::proto_block { + tcx.sess.span_err(expr.span, + #fmt["cannot bind %s closures", + proto_to_str(proto)]); + proto // dummy value so compilation can proceed + } + }; + // For each blank argument, add the type of that argument // to the resulting function type. let out_args = []; @@ -2406,16 +2416,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier, i += 1u; } - // Determine what fn prototype results from binding - fn lower_bound_proto(proto: ast::proto) -> ast::proto { - // FIXME: This is right for bare fns, possibly not others - alt proto { - ast::proto_bare { ast::proto_box } - _ { proto } - } - } - - let ft = ty::mk_fn(tcx, {proto: lower_bound_proto(proto), + let ft = ty::mk_fn(tcx, {proto: proto, inputs: out_args, output: rt, ret_style: cf, constraints: constrs}); write_ty(tcx, id, ft); diff --git a/src/test/compile-fail/bind-stack-closure.rs b/src/test/compile-fail/bind-stack-closure.rs new file mode 100644 index 000000000000..6a08b9b56c0b --- /dev/null +++ b/src/test/compile-fail/bind-stack-closure.rs @@ -0,0 +1,10 @@ +fn foo(x: fn()) { + bind x(); //! ERROR cannot bind fn closures +} + +fn bar(x: fn&()) { + bind x(); //! ERROR cannot bind fn& closures +} + +fn main() { +} diff --git a/src/test/compile-fail/bind-unique-closure.rs b/src/test/compile-fail/bind-unique-closure.rs new file mode 100644 index 000000000000..233c92b7bb39 --- /dev/null +++ b/src/test/compile-fail/bind-unique-closure.rs @@ -0,0 +1,22 @@ +// -*- rust -*- + +// I originally made this test to ensure that bind does the right +// thing when binding a unique closure (which is to copy the closure, +// I suppose?). But I've since decided it's not worth the effort, and +// so I just made it a simple error. But I left the test as is in +// case we ever decide that bind should work with unique closures, +// though a simpler test would suffice for now. + +fn make_addr(-x: ~int) -> fn~() -> uint { + (fn~[move x]() -> uint { ptr::addr_of(*x) as uint }) +} + +fn main() { + let x = ~3; + let a = ptr::addr_of(*x) as uint; + let adder: fn~() -> uint = make_addr(x); + let bound_adder: fn~() -> uint = bind adder(); + //!^ ERROR cannot bind fn~ closures + assert adder() == a; + assert bound_adder() != a; +}