Skip to content

Commit bc4c3df

Browse files
committed
Don't allow the value of generic bare functions to be taken
Issue #1038
1 parent 89466ff commit bc4c3df

File tree

3 files changed

+59
-5
lines changed

3 files changed

+59
-5
lines changed

src/comp/middle/fn_usage.rs

+36-5
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ export check_crate_fn_usage;
77

88
type fn_usage_ctx = {
99
tcx: ty::ctxt,
10-
unsafe_fn_legal: bool
10+
unsafe_fn_legal: bool,
11+
generic_bare_fn_legal: bool
1112
};
1213

1314
fn fn_usage_view_item(_vi: @ast::view_item,
@@ -34,18 +35,44 @@ fn fn_usage_expr(expr: @ast::expr,
3435
_ {}
3536
}
3637
}
38+
if !ctx.generic_bare_fn_legal
39+
&& ty::expr_has_ty_params(ctx.tcx, expr) {
40+
alt ty::struct(ctx.tcx, ty::expr_ty(ctx.tcx, expr)) {
41+
ty::ty_fn(ast::proto_bare., _, _, _, _) {
42+
ctx.tcx.sess.span_fatal(
43+
expr.span,
44+
"generic bare functions can only be called or bound");
45+
}
46+
_ { }
47+
}
48+
}
3749
}
3850

3951
ast::expr_call(f, args) {
40-
let f_ctx = {unsafe_fn_legal: true with ctx};
52+
let f_ctx = {unsafe_fn_legal: true,
53+
generic_bare_fn_legal: true with ctx};
4154
visit::visit_expr(f, f_ctx, v);
4255

43-
let args_ctx = {unsafe_fn_legal: false with ctx};
56+
let args_ctx = {unsafe_fn_legal: false,
57+
generic_bare_fn_legal: false with ctx};
4458
visit::visit_exprs(args, args_ctx, v);
4559
}
4660

61+
ast::expr_bind(f, args) {
62+
let f_ctx = {unsafe_fn_legal: false,
63+
generic_bare_fn_legal: true with ctx};
64+
v.visit_expr(f, f_ctx, v);
65+
66+
let args_ctx = {unsafe_fn_legal: false,
67+
generic_bare_fn_legal: false with ctx};
68+
for arg in args {
69+
visit::visit_expr_opt(arg, args_ctx, v);
70+
}
71+
}
72+
4773
_ {
48-
let subctx = {unsafe_fn_legal: false with ctx};
74+
let subctx = {unsafe_fn_legal: false,
75+
generic_bare_fn_legal: false with ctx};
4976
visit::visit_expr(expr, subctx, v);
5077
}
5178
}
@@ -57,7 +84,11 @@ fn check_crate_fn_usage(tcx: ty::ctxt, crate: @ast::crate) {
5784
@{visit_expr: fn_usage_expr,
5885
visit_view_item: fn_usage_view_item
5986
with *visit::default_visitor()});
60-
let ctx = {tcx: tcx, unsafe_fn_legal: false};
87+
let ctx = {
88+
tcx: tcx,
89+
unsafe_fn_legal: false,
90+
generic_bare_fn_legal: false
91+
};
6192
visit::visit_crate(*crate, ctx, visit);
6293
}
6394

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// error-pattern: generic bare functions can only be called or bound
2+
// Issue #1038
3+
4+
fn main() {
5+
fn# foo<T>() { }
6+
7+
// This wants to build a closure over type int,
8+
// but there's no way to do that while still being a bare function
9+
let f: fn#() = foo::<int>;
10+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// error-pattern: generic bare functions can only be called or bound
2+
// Issue #1038
3+
4+
fn main() {
5+
fn# foo<T>(i: T) { }
6+
7+
// This wants to build a closure over type int,
8+
// but there's no way to do that while still being a bare function
9+
f(foo);
10+
}
11+
12+
fn f(i: fn#(&&int)) {
13+
}

0 commit comments

Comments
 (0)