rustc: Add a region checking pass
Errors aren't reported yet, because the regions aren't properly inferred from the & operator at the moment and that would break the tests.
This commit is contained in:
parent
0905ad2bbe
commit
e8c7b5347d
src/rustc
@ -163,6 +163,8 @@ fn compile_upto(sess: session, cfg: ast::crate_cfg,
|
||||
let mutbl_map =
|
||||
time(time_passes, "mutability checking",
|
||||
bind middle::mutbl::check_crate(ty_cx, crate));
|
||||
time(time_passes, "region checking",
|
||||
bind middle::regionck::check_crate(ty_cx, crate));
|
||||
let (copy_map, ref_map) =
|
||||
time(time_passes, "alias checking",
|
||||
bind middle::alias::check_crate(ty_cx, crate));
|
||||
|
71
src/rustc/middle/regionck.rs
Normal file
71
src/rustc/middle/regionck.rs
Normal file
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* The region checking pass. Ensures that region-annotated pointers never
|
||||
* outlive their referents.
|
||||
*/
|
||||
|
||||
import driver::session::session;
|
||||
import middle::ty;
|
||||
import std::map::hashmap;
|
||||
import syntax::{ast, visit};
|
||||
|
||||
type ctxt = {
|
||||
tcx: ty::ctxt,
|
||||
enclosing_block: option<ast::node_id>
|
||||
};
|
||||
|
||||
fn check_expr(expr: @ast::expr, cx: ctxt, visitor: visit::vt<ctxt>) {
|
||||
ty::walk_ty(cx.tcx, ty::expr_ty(cx.tcx, expr)) { |t|
|
||||
alt ty::get(t).struct {
|
||||
ty::ty_rptr(region, _) {
|
||||
alt region {
|
||||
ty::re_named(_) | ty::re_caller(_) { /* ok */ }
|
||||
ty::re_block(rbi) {
|
||||
let referent_block_id = rbi;
|
||||
let enclosing_block_id = alt cx.enclosing_block {
|
||||
none {
|
||||
cx.tcx.sess.span_bug(expr.span, "block " +
|
||||
"region type outside " +
|
||||
"a block?!");
|
||||
}
|
||||
some(eb) { eb }
|
||||
};
|
||||
|
||||
let parent_blocks = cx.tcx.region_map.parent_blocks;
|
||||
while enclosing_block_id != referent_block_id {
|
||||
if parent_blocks.contains_key(referent_block_id) {
|
||||
referent_block_id =
|
||||
parent_blocks.get(referent_block_id);
|
||||
} else {
|
||||
// TODO: Enable this.
|
||||
|
||||
//cx.tcx.sess.span_err(expr.span,
|
||||
// "reference escapes " +
|
||||
// "its block");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ { /* no-op */ }
|
||||
}
|
||||
}
|
||||
|
||||
visit::visit_expr(expr, cx, visitor);
|
||||
}
|
||||
|
||||
fn check_block(blk: ast::blk, cx: ctxt, visitor: visit::vt<ctxt>) {
|
||||
let new_cx: ctxt = { enclosing_block: some(blk.node.id) with cx };
|
||||
visit::visit_block(blk, new_cx, visitor);
|
||||
}
|
||||
|
||||
fn check_crate(ty_cx: ty::ctxt, crate: @ast::crate) {
|
||||
let cx: ctxt = {tcx: ty_cx, enclosing_block: none};
|
||||
let visitor = visit::mk_vt(@{
|
||||
visit_expr: check_expr,
|
||||
visit_block: check_block
|
||||
with *visit::default_visitor()
|
||||
});
|
||||
visit::visit_crate(*crate, cx, visitor);
|
||||
}
|
||||
|
@ -45,6 +45,7 @@ mod middle {
|
||||
mod capture;
|
||||
mod pat_util;
|
||||
mod region;
|
||||
mod regionck;
|
||||
|
||||
mod tstate {
|
||||
mod ck;
|
||||
|
Loading…
x
Reference in New Issue
Block a user