add pass to check that unsafe fns cannot be used as values
This commit is contained in:
parent
e39db5a100
commit
81533ff737
@ -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 {
|
||||
|
72
src/comp/middle/unsafeck.rs
Normal file
72
src/comp/middle/unsafeck.rs
Normal 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:
|
@ -25,6 +25,7 @@ mod middle {
|
||||
mod ast_map;
|
||||
mod resolve;
|
||||
mod typeck;
|
||||
mod unsafeck;
|
||||
mod check_alt;
|
||||
mod mut;
|
||||
mod alias;
|
||||
|
9
src/test/compile-fail/unsafe-fn-used-as-value.rs
Normal file
9
src/test/compile-fail/unsafe-fn-used-as-value.rs
Normal file
@ -0,0 +1,9 @@
|
||||
// -*- rust -*-
|
||||
// error-pattern: unsafe functions can only be called
|
||||
|
||||
unsafe fn f() { ret; }
|
||||
|
||||
fn main() {
|
||||
let x = f;
|
||||
x();
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user