rustc: Map region names to their functions. Also speed up region checking by 17x.
This commit is contained in:
parent
db79f3c0a5
commit
864ff4707e
@ -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,
|
||||
|
@ -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 */ }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user