Skip to content

Commit

Permalink
Don't allow the value of generic bare functions to be taken
Browse files Browse the repository at this point in the history
Issue #1038
  • Loading branch information
brson committed Oct 13, 2011
1 parent 89466ff commit bc4c3df
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 5 deletions.
41 changes: 36 additions & 5 deletions src/comp/middle/fn_usage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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);
}
}
Expand All @@ -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);
}

Expand Down
10 changes: 10 additions & 0 deletions src/test/compile-fail/fn-bare-generic-instantiate1.rs
Original file line number Diff line number Diff line change
@@ -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 changes: 13 additions & 0 deletions src/test/compile-fail/fn-bare-generic-instantiate2.rs
Original file line number Diff line number Diff line change
@@ -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)) {
}

0 comments on commit bc4c3df

Please sign in to comment.