about summary refs log tree commit diff
diff options
context:
space:
mode:
authorBrian Anderson <banderson@mozilla.com>2011-10-13 14:07:57 -0700
committerBrian Anderson <banderson@mozilla.com>2011-10-13 14:39:30 -0700
commitbc4c3df1bf98443411f96112b4ced136e1abcdf1 (patch)
treedcf4ed1596492bbf13d8524b3c9378a5cb2b9ab8
parent89466ffd745547ee8b9c75a12a998dd16ef3bf2a (diff)
downloadrust-bc4c3df1bf98443411f96112b4ced136e1abcdf1.tar.gz
rust-bc4c3df1bf98443411f96112b4ced136e1abcdf1.zip
Don't allow the value of generic bare functions to be taken
Issue #1038
-rw-r--r--src/comp/middle/fn_usage.rs41
-rw-r--r--src/test/compile-fail/fn-bare-generic-instantiate1.rs10
-rw-r--r--src/test/compile-fail/fn-bare-generic-instantiate2.rs13
3 files changed, 59 insertions, 5 deletions
diff --git a/src/comp/middle/fn_usage.rs b/src/comp/middle/fn_usage.rs
index 3e170f19d16..035d611fbdc 100644
--- a/src/comp/middle/fn_usage.rs
+++ b/src/comp/middle/fn_usage.rs
@@ -7,7 +7,8 @@ export check_crate_fn_usage;
 
 type fn_usage_ctx = {
     tcx: ty::ctxt,
-    unsafe_fn_legal: bool
+    unsafe_fn_legal: bool,
+    generic_bare_fn_legal: bool
 };
 
 fn fn_usage_view_item(_vi: @ast::view_item,
@@ -34,18 +35,44 @@ fn fn_usage_expr(expr: @ast::expr,
               _ {}
             }
         }
+        if !ctx.generic_bare_fn_legal
+            && ty::expr_has_ty_params(ctx.tcx, expr) {
+            alt ty::struct(ctx.tcx, ty::expr_ty(ctx.tcx, expr)) {
+              ty::ty_fn(ast::proto_bare., _, _, _, _) {
+                ctx.tcx.sess.span_fatal(
+                    expr.span,
+                    "generic bare functions can only be called or bound");
+              }
+              _ { }
+            }
+        }
       }
 
       ast::expr_call(f, args) {
-        let f_ctx = {unsafe_fn_legal: true with ctx};
+        let f_ctx = {unsafe_fn_legal: true,
+                     generic_bare_fn_legal: true with ctx};
         visit::visit_expr(f, f_ctx, v);
 
-        let args_ctx = {unsafe_fn_legal: false with ctx};
+        let args_ctx = {unsafe_fn_legal: false,
+                        generic_bare_fn_legal: false with ctx};
         visit::visit_exprs(args, args_ctx, v);
       }
 
+      ast::expr_bind(f, args) {
+        let f_ctx = {unsafe_fn_legal: false,
+                     generic_bare_fn_legal: true with ctx};
+        v.visit_expr(f, f_ctx, v);
+
+        let args_ctx = {unsafe_fn_legal: false,
+                        generic_bare_fn_legal: false with ctx};
+        for arg in args {
+            visit::visit_expr_opt(arg, args_ctx, v);
+        }
+      }
+
       _ {
-        let subctx = {unsafe_fn_legal: false with ctx};
+        let subctx = {unsafe_fn_legal: false,
+                      generic_bare_fn_legal: false with ctx};
         visit::visit_expr(expr, subctx, v);
       }
     }
@@ -57,7 +84,11 @@ fn check_crate_fn_usage(tcx: ty::ctxt, crate: @ast::crate) {
             @{visit_expr: fn_usage_expr,
               visit_view_item: fn_usage_view_item
                   with *visit::default_visitor()});
-    let ctx = {tcx: tcx, unsafe_fn_legal: false};
+    let ctx = {
+        tcx: tcx,
+        unsafe_fn_legal: false,
+        generic_bare_fn_legal: false
+    };
     visit::visit_crate(*crate, ctx, visit);
 }
 
diff --git a/src/test/compile-fail/fn-bare-generic-instantiate1.rs b/src/test/compile-fail/fn-bare-generic-instantiate1.rs
new file mode 100644
index 00000000000..094bec27209
--- /dev/null
+++ b/src/test/compile-fail/fn-bare-generic-instantiate1.rs
@@ -0,0 +1,10 @@
+// error-pattern: generic bare functions can only be called or bound
+// Issue #1038
+
+fn main() {
+    fn# foo<T>() { }
+
+    // This wants to build a closure over type int,
+    // but there's no way to do that while still being a bare function
+    let f: fn#() = foo::<int>;
+}
\ No newline at end of file
diff --git a/src/test/compile-fail/fn-bare-generic-instantiate2.rs b/src/test/compile-fail/fn-bare-generic-instantiate2.rs
new file mode 100644
index 00000000000..2b82ec57e60
--- /dev/null
+++ b/src/test/compile-fail/fn-bare-generic-instantiate2.rs
@@ -0,0 +1,13 @@
+// error-pattern: generic bare functions can only be called or bound
+// Issue #1038
+
+fn main() {
+    fn# foo<T>(i: T) { }
+
+    // This wants to build a closure over type int,
+    // but there's no way to do that while still being a bare function
+    f(foo);
+}
+
+fn f(i: fn#(&&int)) {
+}
\ No newline at end of file