mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-01 06:51:58 +00:00
Add a pass that checks that blocks are only used in safe ways
Closes #1188
This commit is contained in:
parent
86c1f16a10
commit
b4217b383b
@ -139,6 +139,8 @@ fn compile_input(sess: session::session, cfg: ast::crate_cfg, input: str,
|
|||||||
bind freevars::annotate_freevars(def_map, crate));
|
bind freevars::annotate_freevars(def_map, crate));
|
||||||
let ty_cx = ty::mk_ctxt(sess, def_map, ext_map, ast_map, freevars);
|
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, "typechecking", bind typeck::check_crate(ty_cx, crate));
|
||||||
|
time(time_passes, "block-use checking",
|
||||||
|
bind middle::block_use::check_crate(ty_cx, crate));
|
||||||
time(time_passes, "function usage",
|
time(time_passes, "function usage",
|
||||||
bind fn_usage::check_crate_fn_usage(ty_cx, crate));
|
bind fn_usage::check_crate_fn_usage(ty_cx, crate));
|
||||||
time(time_passes, "alt checking",
|
time(time_passes, "alt checking",
|
||||||
|
41
src/comp/middle/block_use.rs
Normal file
41
src/comp/middle/block_use.rs
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
import syntax::visit;
|
||||||
|
import syntax::ast::*;
|
||||||
|
|
||||||
|
type ctx = {tcx: ty::ctxt, mutable allow_block: bool};
|
||||||
|
|
||||||
|
fn check_crate(tcx: ty::ctxt, crate: @crate) {
|
||||||
|
let cx = {tcx: tcx, mutable allow_block: false};
|
||||||
|
let v = visit::mk_vt(@{visit_expr: visit_expr
|
||||||
|
with *visit::default_visitor()});
|
||||||
|
visit::visit_crate(*crate, cx, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_expr(ex: @expr, cx: ctx, v: visit::vt<ctx>) {
|
||||||
|
if !cx.allow_block {
|
||||||
|
alt ty::struct(cx.tcx, ty::expr_ty(cx.tcx, ex)) {
|
||||||
|
ty::ty_fn(proto_block., _, _, _, _) {
|
||||||
|
cx.tcx.sess.span_err(ex.span, "expressions with block type \
|
||||||
|
can only appear in callee or (by-ref) argument position");
|
||||||
|
}
|
||||||
|
_ {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let outer = cx.allow_block;
|
||||||
|
alt ex.node {
|
||||||
|
expr_call(f, args, _) {
|
||||||
|
cx.allow_block = true;
|
||||||
|
v.visit_expr(f, cx, v);
|
||||||
|
let i = 0u;
|
||||||
|
for arg_t in ty::ty_fn_args(cx.tcx, ty::expr_ty(cx.tcx, f)) {
|
||||||
|
cx.allow_block = arg_t.mode == by_ref;
|
||||||
|
v.visit_expr(args[i], cx, v);
|
||||||
|
i += 1u;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ {
|
||||||
|
cx.allow_block = false;
|
||||||
|
visit::visit_expr(ex, cx, v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cx.allow_block = outer;
|
||||||
|
}
|
@ -31,6 +31,7 @@ mod middle {
|
|||||||
mod mut;
|
mod mut;
|
||||||
mod alias;
|
mod alias;
|
||||||
mod last_use;
|
mod last_use;
|
||||||
|
mod block_use;
|
||||||
mod kind;
|
mod kind;
|
||||||
mod freevars;
|
mod freevars;
|
||||||
mod shape;
|
mod shape;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// error-pattern: copying a noncopyable value
|
// error-pattern: block type can only appear
|
||||||
|
|
||||||
fn lol(f: block()) -> block() { ret f; }
|
fn lol(f: block()) -> block() { ret f; }
|
||||||
fn main() { let i = 8; let f = lol(block () { log_err i; }); f(); }
|
fn main() { let i = 8; let f = lol(block () { log_err i; }); f(); }
|
||||||
|
@ -1,11 +1,8 @@
|
|||||||
// error-pattern:Tried to deinitialize a variable declared in a different
|
// error-pattern:Tried to deinitialize a variable declared in a different
|
||||||
fn force(f: block() -> int) -> int { ret f(); }
|
fn force(f: block()) { f(); }
|
||||||
fn main() {
|
fn main() {
|
||||||
let x = @{x: 17, y: 2};
|
let x = @{x: 17, y: 2};
|
||||||
let y = @{x: 5, y: 5};
|
let y = @{x: 5, y: 5};
|
||||||
|
|
||||||
let f = {|i| log_err i; x <- y; ret 7; };
|
force({|| x <- y;});
|
||||||
assert (f(5) == 7);
|
|
||||||
log_err x;
|
|
||||||
log_err y;
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user