2011-10-11 19:31:23 -05:00
|
|
|
import syntax::ast;
|
|
|
|
import syntax::visit;
|
2011-12-13 18:25:51 -06:00
|
|
|
import option::some;
|
2011-11-10 10:41:42 -06:00
|
|
|
import syntax::print::pprust::expr_to_str;
|
2012-01-12 10:59:49 -06:00
|
|
|
import driver::session::session;
|
2011-10-11 19:31:23 -05:00
|
|
|
|
2011-10-13 14:25:57 -05:00
|
|
|
export check_crate_fn_usage;
|
2011-10-11 19:31:23 -05:00
|
|
|
|
2011-10-13 14:25:57 -05:00
|
|
|
type fn_usage_ctx = {
|
2011-10-11 19:31:23 -05:00
|
|
|
tcx: ty::ctxt,
|
2011-12-11 22:51:14 -06:00
|
|
|
unsafe_fn_legal: bool,
|
|
|
|
generic_bare_fn_legal: bool
|
2011-10-11 19:31:23 -05:00
|
|
|
};
|
|
|
|
|
2011-10-13 14:25:57 -05:00
|
|
|
fn fn_usage_expr(expr: @ast::expr,
|
|
|
|
ctx: fn_usage_ctx,
|
|
|
|
v: visit::vt<fn_usage_ctx>) {
|
2011-10-11 19:31:23 -05:00
|
|
|
alt expr.node {
|
|
|
|
ast::expr_path(path) {
|
|
|
|
if !ctx.unsafe_fn_legal {
|
|
|
|
alt ctx.tcx.def_map.find(expr.id) {
|
|
|
|
some(ast::def_fn(_, ast::unsafe_fn.)) |
|
|
|
|
some(ast::def_native_fn(_, ast::unsafe_fn.)) {
|
2011-12-22 19:53:53 -06:00
|
|
|
log(error, ("expr=", expr_to_str(expr)));
|
2011-10-11 19:31:23 -05:00
|
|
|
ctx.tcx.sess.span_fatal(
|
|
|
|
expr.span,
|
|
|
|
"unsafe functions can only be called");
|
|
|
|
}
|
|
|
|
|
|
|
|
_ {}
|
|
|
|
}
|
|
|
|
}
|
2011-12-11 22:51:14 -06:00
|
|
|
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)) {
|
2011-12-23 09:09:52 -06:00
|
|
|
ty::ty_fn({proto: ast::proto_bare., _}) {
|
2011-12-11 22:51:14 -06:00
|
|
|
ctx.tcx.sess.span_fatal(
|
|
|
|
expr.span,
|
|
|
|
"generic bare functions can only be called or bound");
|
|
|
|
}
|
|
|
|
_ { }
|
|
|
|
}
|
|
|
|
}
|
2011-10-11 19:31:23 -05:00
|
|
|
}
|
|
|
|
|
2011-10-21 07:11:24 -05:00
|
|
|
ast::expr_call(f, args, _) {
|
2011-12-11 22:51:14 -06:00
|
|
|
let f_ctx = {unsafe_fn_legal: true,
|
|
|
|
generic_bare_fn_legal: true with ctx};
|
2011-10-13 16:53:34 -05:00
|
|
|
v.visit_expr(f, f_ctx, v);
|
2011-10-11 19:31:23 -05:00
|
|
|
|
2011-12-11 22:51:14 -06:00
|
|
|
let args_ctx = {unsafe_fn_legal: false,
|
|
|
|
generic_bare_fn_legal: false with ctx};
|
2011-10-11 19:31:23 -05:00
|
|
|
visit::visit_exprs(args, args_ctx, v);
|
|
|
|
}
|
|
|
|
|
2011-10-13 16:07:57 -05:00
|
|
|
ast::expr_bind(f, args) {
|
2011-12-11 22:51:14 -06:00
|
|
|
let f_ctx = {unsafe_fn_legal: false,
|
|
|
|
generic_bare_fn_legal: true with ctx};
|
2011-10-13 16:07:57 -05:00
|
|
|
v.visit_expr(f, f_ctx, v);
|
|
|
|
|
2011-12-11 22:51:14 -06:00
|
|
|
let args_ctx = {unsafe_fn_legal: false,
|
|
|
|
generic_bare_fn_legal: false with ctx};
|
2011-10-13 16:07:57 -05:00
|
|
|
for arg in args {
|
|
|
|
visit::visit_expr_opt(arg, args_ctx, v);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-10-11 19:31:23 -05:00
|
|
|
_ {
|
2011-12-11 22:51:14 -06:00
|
|
|
let subctx = {unsafe_fn_legal: false,
|
|
|
|
generic_bare_fn_legal: false with ctx};
|
2011-10-11 19:31:23 -05:00
|
|
|
visit::visit_expr(expr, subctx, v);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-10-13 14:25:57 -05:00
|
|
|
fn check_crate_fn_usage(tcx: ty::ctxt, crate: @ast::crate) {
|
2011-10-11 19:31:23 -05:00
|
|
|
let visit =
|
|
|
|
visit::mk_vt(
|
2011-10-13 16:55:27 -05:00
|
|
|
@{visit_expr: fn_usage_expr
|
2011-10-11 19:31:23 -05:00
|
|
|
with *visit::default_visitor()});
|
2011-10-13 16:07:57 -05:00
|
|
|
let ctx = {
|
|
|
|
tcx: tcx,
|
2011-12-11 22:51:14 -06:00
|
|
|
unsafe_fn_legal: false,
|
|
|
|
generic_bare_fn_legal: false
|
2011-10-13 16:07:57 -05:00
|
|
|
};
|
2011-10-11 19:31:23 -05:00
|
|
|
visit::visit_crate(*crate, ctx, visit);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Local Variables:
|
|
|
|
// mode: rust
|
|
|
|
// fill-column: 78;
|
|
|
|
// indent-tabs-mode: nil
|
|
|
|
// c-basic-offset: 4
|
|
|
|
// buffer-file-coding-system: utf-8-unix
|
|
|
|
// End:
|