Don't allow the value of generic bare functions to be taken
Issue #1038
This commit is contained in:
parent
89466ffd74
commit
bc4c3df1bf
3 changed files with 59 additions and 5 deletions
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
10
src/test/compile-fail/fn-bare-generic-instantiate1.rs
Normal file
10
src/test/compile-fail/fn-bare-generic-instantiate1.rs
Normal file
|
|
@ -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>;
|
||||
}
|
||||
13
src/test/compile-fail/fn-bare-generic-instantiate2.rs
Normal file
13
src/test/compile-fail/fn-bare-generic-instantiate2.rs
Normal file
|
|
@ -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)) {
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue