rustc: Map region names to their functions. Also speed up region checking by 17x.

This commit is contained in:
Patrick Walton 2012-03-12 13:24:37 -07:00
parent db79f3c0a5
commit 864ff4707e
3 changed files with 66 additions and 43 deletions

View File

@ -6,6 +6,8 @@
import driver::session::session;
import middle::ty;
import syntax::{ast, visit};
import util::common::new_def_hash;
import std::map;
import std::map::hashmap;
@ -27,6 +29,8 @@ type region_map = {
ast_type_to_region: hashmap<ast::node_id,ty::region>,
/* Mapping from a local variable to its containing block. */
local_blocks: hashmap<ast::node_id,ast::node_id>,
/* Mapping from a region name to its function. */
region_name_to_fn: hashmap<ast::def_id,ast::node_id>,
};
type ctxt = {
@ -105,9 +109,15 @@ fn resolve_ty(ty: @ast::ty, cx: ctxt, visitor: visit::vt<ctxt>) {
alt cx.names_in_scope.find(ident) {
some(def_id) { region = ty::re_named(def_id); }
none {
let def_id = {crate: ast::local_crate,
node: region_id};
cx.names_in_scope.insert(ident, def_id);
region = ty::re_named(def_id);
alt cx.parent {
pa_item(_) | pa_nested_fn(_) {
/* ok; fall through */
pa_item(fn_id) | pa_nested_fn(fn_id) {
let rf = cx.region_map.region_name_to_fn;
rf.insert(def_id, fn_id);
}
pa_block(_) {
cx.sess.span_err(ty.span,
@ -120,11 +130,6 @@ fn resolve_ty(ty: @ast::ty, cx: ctxt, visitor: visit::vt<ctxt>) {
"level?!");
}
}
let def_id = {crate: ast::local_crate,
node: region_id};
cx.names_in_scope.insert(ident, def_id);
region = ty::re_named(def_id);
}
}
}
@ -256,7 +261,8 @@ fn resolve_crate(sess: session, def_map: resolve::def_map, crate: @ast::crate)
def_map: def_map,
region_map: @{parents: map::new_int_hash(),
ast_type_to_region: map::new_int_hash(),
local_blocks: map::new_int_hash()},
local_blocks: map::new_int_hash(),
region_name_to_fn: new_def_hash()},
names_in_scope: map::new_str_hash(),
mut queued_locals: [],
parent: pa_crate,

View File

@ -22,33 +22,37 @@ type ctxt = {
};
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?!");
let t = ty::expr_ty(cx.tcx, expr);
if ty::type_has_rptrs(t) {
ty::walk_ty(cx.tcx, t) { |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 }
};
if !region::scope_contains(cx.tcx.region_map,
referent_block_id,
enclosing_block_id) {
cx.tcx.sess.span_err(expr.span, "reference " +
"escapes its block");
}
some(eb) { eb }
};
if !region::scope_contains(cx.tcx.region_map,
referent_block_id,
enclosing_block_id) {
cx.tcx.sess.span_err(expr.span, "reference " +
"escapes its block");
}
}
}
_ { /* no-op */ }
}
_ { /* no-op */ }
}
}

View File

@ -89,7 +89,7 @@ export ty_uniq, mk_uniq, mk_imm_uniq, type_is_unique_box;
export ty_var, mk_var;
export ty_self, mk_self;
export region, re_named, re_caller, re_block;
export get, type_has_params, type_has_vars, type_id;
export get, type_has_params, type_has_vars, type_has_rptrs, type_id;
export same_type;
export ty_var_id;
export ty_fn_args;
@ -187,6 +187,7 @@ type t_box = @{struct: sty,
id: uint,
has_params: bool,
has_vars: bool,
has_rptrs: bool,
o_def_id: option<ast::def_id>};
// To reduce refcounting cost, we're representing types as unsafe pointers
@ -206,6 +207,7 @@ pure fn get(t: t) -> t_box unsafe {
fn type_has_params(t: t) -> bool { get(t).has_params }
fn type_has_vars(t: t) -> bool { get(t).has_vars }
fn type_has_rptrs(t: t) -> bool { get(t).has_rptrs }
fn type_def_id(t: t) -> option<ast::def_id> { get(t).o_def_id }
fn type_id(t: t) -> uint { get(t).id }
@ -368,11 +370,13 @@ fn mk_t_with_id(cx: ctxt, st: sty, o_def_id: option<ast::def_id>) -> t {
some(t) { unsafe { ret unsafe::reinterpret_cast(t); } }
_ {}
}
let has_params = false, has_vars = false;
fn derive_flags(&has_params: bool, &has_vars: bool, tt: t) {
let has_params = false, has_vars = false, has_rptrs = false;
fn derive_flags(&has_params: bool, &has_vars: bool, &has_rptrs: bool,
tt: t) {
let t = get(tt);
has_params |= t.has_params;
has_vars |= t.has_vars;
has_rptrs |= t.has_rptrs;
}
alt st {
ty_nil | ty_bot | ty_bool | ty_int(_) | ty_float(_) | ty_uint(_) |
@ -381,33 +385,42 @@ fn mk_t_with_id(cx: ctxt, st: sty, o_def_id: option<ast::def_id>) -> t {
ty_param(_, _) { has_params = true; }
ty_var(_) | ty_self(_) { has_vars = true; }
ty_enum(_, tys) | ty_iface(_, tys) | ty_class(_, tys) {
for tt in tys { derive_flags(has_params, has_vars, tt); }
for tt in tys { derive_flags(has_params, has_vars, has_rptrs, tt); }
}
ty_box(m) | ty_uniq(m) | ty_vec(m) | ty_ptr(m) | ty_rptr(_, m) {
derive_flags(has_params, has_vars, m.ty);
ty_box(m) | ty_uniq(m) | ty_vec(m) | ty_ptr(m) {
derive_flags(has_params, has_vars, has_rptrs, m.ty);
}
ty_rptr(_, m) {
has_rptrs = true;
derive_flags(has_params, has_vars, has_rptrs, m.ty);
}
ty_rec(flds) {
for f in flds { derive_flags(has_params, has_vars, f.mt.ty); }
for f in flds {
derive_flags(has_params, has_vars, has_rptrs, f.mt.ty);
}
}
ty_tup(ts) {
for tt in ts { derive_flags(has_params, has_vars, tt); }
for tt in ts { derive_flags(has_params, has_vars, has_rptrs, tt); }
}
ty_fn(f) {
for a in f.inputs { derive_flags(has_params, has_vars, a.ty); }
derive_flags(has_params, has_vars, f.output);
for a in f.inputs {
derive_flags(has_params, has_vars, has_rptrs, a.ty);
}
derive_flags(has_params, has_vars, has_rptrs, f.output);
}
ty_res(_, tt, tps) {
derive_flags(has_params, has_vars, tt);
for tt in tps { derive_flags(has_params, has_vars, tt); }
derive_flags(has_params, has_vars, has_rptrs, tt);
for tt in tps { derive_flags(has_params, has_vars, has_rptrs, tt); }
}
ty_constr(tt, _) {
derive_flags(has_params, has_vars, tt);
derive_flags(has_params, has_vars, has_rptrs, tt);
}
}
let t = @{struct: st,
id: cx.next_id,
has_params: has_params,
has_vars: has_vars,
has_rptrs: has_rptrs,
o_def_id: o_def_id};
cx.interner.insert(key, t);
cx.next_id += 1u;