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:
Patrick Walton 2012-03-09 17:38:57 -08:00
parent 0905ad2bbe
commit e8c7b5347d
3 changed files with 74 additions and 0 deletions
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));

@ -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;