]> git.lizzy.rs Git - rust.git/commitdiff
Don't allow the value of generic bare functions to be taken
authorBrian Anderson <banderson@mozilla.com>
Thu, 13 Oct 2011 21:07:57 +0000 (14:07 -0700)
committerBrian Anderson <banderson@mozilla.com>
Thu, 13 Oct 2011 21:39:30 +0000 (14:39 -0700)
Issue #1038

src/comp/middle/fn_usage.rs
src/test/compile-fail/fn-bare-generic-instantiate1.rs [new file with mode: 0644]
src/test/compile-fail/fn-bare-generic-instantiate2.rs [new file with mode: 0644]

index 3e170f19d16ac21ce0fa4fff3f54222ff52448cd..035d611fbdc61ce2c28ca6db8af563e9fd6dc5eb 100644 (file)
@@ -7,7 +7,8 @@
 
 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 (file)
index 0000000..094bec2
--- /dev/null
@@ -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 (file)
index 0000000..2b82ec5
--- /dev/null
@@ -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