about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/comp/middle/typeck.rs21
-rw-r--r--src/test/compile-fail/bind-stack-closure.rs10
-rw-r--r--src/test/compile-fail/bind-unique-closure.rs22
3 files changed, 43 insertions, 10 deletions
diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs
index 40cd1d37a8d..e1c56b9fc54 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 00000000000..6a08b9b56c0
--- /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 00000000000..233c92b7bb3
--- /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;
+}