diff options
| author | Brian Anderson <banderson@mozilla.com> | 2011-10-13 14:07:57 -0700 |
|---|---|---|
| committer | Brian Anderson <banderson@mozilla.com> | 2011-10-13 14:39:30 -0700 |
| commit | bc4c3df1bf98443411f96112b4ced136e1abcdf1 (patch) | |
| tree | dcf4ed1596492bbf13d8524b3c9378a5cb2b9ab8 | |
| parent | 89466ffd745547ee8b9c75a12a998dd16ef3bf2a (diff) | |
| download | rust-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.rs | 41 | ||||
| -rw-r--r-- | src/test/compile-fail/fn-bare-generic-instantiate1.rs | 10 | ||||
| -rw-r--r-- | src/test/compile-fail/fn-bare-generic-instantiate2.rs | 13 |
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 |
