add pass to check that unsafe fns cannot be used as values

This commit is contained in:
Niko Matsakis 2011-10-11 17:31:23 -07:00 committed by Brian Anderson
parent e39db5a100
commit 81533ff737
4 changed files with 85 additions and 1 deletions

View File

@ -5,7 +5,7 @@ import metadata::{creader, cstore};
import syntax::parse::{parser, token};
import syntax::{ast, codemap};
import front::attr;
import middle::{trans, resolve, freevars, kind, ty, typeck};
import middle::{trans, resolve, freevars, kind, ty, typeck, unsafeck};
import middle::tstate::ck;
import syntax::print::{pp, pprust};
import util::{ppaux, common, filesearch};
@ -129,6 +129,8 @@ fn compile_input(sess: session::session, cfg: ast::crate_cfg, input: str,
bind freevars::annotate_freevars(def_map, crate));
let ty_cx = ty::mk_ctxt(sess, def_map, ext_map, ast_map, freevars);
time(time_passes, "typechecking", bind typeck::check_crate(ty_cx, crate));
time(time_passes, "unsafechecking",
bind unsafeck::unsafeck_crate(ty_cx, crate));
time(time_passes, "alt checking",
bind middle::check_alt::check_crate(ty_cx, crate));
if sess.get_opts().run_typestate {

View File

@ -0,0 +1,72 @@
import syntax::ast;
import syntax::visit;
import std::option::some;
import syntax::print::pprust::{expr_to_str, path_to_str};
export unsafeck_crate;
type unsafe_ctx = {
tcx: ty::ctxt,
unsafe_fn_legal: bool
};
fn unsafeck_view_item(_vi: @ast::view_item,
_ctx: unsafe_ctx,
_v: visit::vt<unsafe_ctx>) {
// Ignore paths that appear in use, import, etc
}
fn unsafeck_expr(expr: @ast::expr,
ctx: unsafe_ctx,
v: visit::vt<unsafe_ctx>) {
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.)) {
log_err ("expr=", expr_to_str(expr));
ctx.tcx.sess.span_fatal(
expr.span,
"unsafe functions can only be called");
}
_ {}
}
}
}
ast::expr_call(f, args) {
let f_ctx = {unsafe_fn_legal: true with ctx};
visit::visit_expr(f, f_ctx, v);
let args_ctx = {unsafe_fn_legal: false with ctx};
visit::visit_exprs(args, args_ctx, v);
}
_ {
let subctx = {unsafe_fn_legal: false with ctx};
visit::visit_expr(expr, subctx, v);
}
}
}
fn unsafeck_crate(tcx: ty::ctxt, crate: @ast::crate) {
let visit =
visit::mk_vt(
@{visit_expr: unsafeck_expr,
visit_view_item: unsafeck_view_item
with *visit::default_visitor()});
let ctx = {tcx: tcx, unsafe_fn_legal: false};
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
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:

View File

@ -25,6 +25,7 @@ mod middle {
mod ast_map;
mod resolve;
mod typeck;
mod unsafeck;
mod check_alt;
mod mut;
mod alias;

View File

@ -0,0 +1,9 @@
// -*- rust -*-
// error-pattern: unsafe functions can only be called
unsafe fn f() { ret; }
fn main() {
let x = f;
x();
}