rustc: Unify regions in most cases. (Nested functions aren't properly handled yet.)

This commit is contained in:
Patrick Walton 2012-03-11 13:28:43 -07:00
parent f7efc29b38
commit 3e8bb22af1
3 changed files with 67 additions and 5 deletions

View File

@ -43,6 +43,20 @@ type ctxt = {
parent: parent
};
// Returns true if `subblock` is equal to or is lexically nested inside
// `superblock` and false otherwise.
fn block_contains(region_map: @region_map, superblock: ast::node_id,
subblock: ast::node_id) -> bool {
let subblock = subblock;
while superblock != subblock {
alt region_map.parent_blocks.find(subblock) {
none { ret false; }
some(blk) { subblock = blk; }
}
}
ret true;
}
fn resolve_ty(ty: @ast::ty, cx: ctxt, visitor: visit::vt<ctxt>) {
alt ty.node {
ast::ty_rptr({id: region_id, node: node}, _) {

View File

@ -283,6 +283,7 @@ enum type_err {
terr_mode_mismatch(mode, mode),
terr_constr_len(uint, uint),
terr_constr_mismatch(@type_constr, @type_constr),
terr_regions_differ,
}
enum param_bound {
@ -1885,6 +1886,45 @@ mod unify {
}
}
}
fn unify_regions(cx: @uctxt, e_region: region, a_region: region,
variance: variance) -> option<region> {
let sub, super;
alt variance {
covariant { super = e_region; sub = a_region; }
contravariant { super = a_region; sub = e_region; }
invariant {
ret if e_region == a_region { some(e_region) } else { none };
}
}
alt (super, sub) {
(re_caller(_), re_caller(_)) {
// FIXME: This is wrong w/r/t nested functions.
ret some(super);
}
(re_caller(_), re_named(_)) | (re_named(_), re_caller(_)) {
ret none;
}
(re_named(a), re_named(b)) {
ret if a == b { some(super) } else { none }
}
(re_caller(_), re_block(_)) | (re_named(_), re_block(_)) {
// FIXME: This is wrong w/r/t nested functions.
ret some(super);
}
(re_block(_), re_caller(_)) | (re_block(_), re_named(_)) {
ret none;
}
(re_block(superblock), re_block(subblock)) {
if region::block_contains(cx.tcx.region_map, superblock,
subblock) {
ret some(super);
} else {
ret none;
}
}
}
}
fn unify_step(cx: @uctxt, expected: t, actual: t,
variance: variance) -> result {
@ -1943,9 +1983,13 @@ mod unify {
unify_mt(cx, e_mt, a_mt, variance, terr_ptr_mutability, mk_ptr)
}
(ty_rptr(e_region, e_mt), ty_rptr(a_region, a_mt)) {
// TODO: Unify regions. Take covariance/invariance into account.
unify_mt(cx, e_mt, a_mt, variance, terr_ref_mutability,
bind mk_rptr(_, re_block(0), _))
alt unify_regions(cx, e_region, a_region, variance) {
none { ures_err(terr_regions_differ) }
some(r_region) {
unify_mt(cx, e_mt, a_mt, variance, terr_ref_mutability,
bind mk_rptr(_, r_region, _))
}
}
}
(ty_res(e_id, e_inner, e_tps), ty_res(a_id, a_inner, a_tps))
if e_id == a_id {
@ -2154,6 +2198,9 @@ fn type_err_to_str(err: type_err) -> str {
" but found one with constraint " +
ty_constr_to_str(a_constr);
}
terr_regions_differ {
ret "inconsistent pointer lifetimes"
}
}
}

View File

@ -319,8 +319,9 @@ fn ast_ty_to_ty(tcx: ty::ctxt, mode: mode, &&ast_ty: @ast::ty) -> ty::t {
ast::ty_ptr(mt) {
ty::mk_ptr(tcx, ast_mt_to_mt(tcx, mode, mt))
}
ast::ty_rptr(_, mt) {
ty::mk_rptr(tcx, ty::re_block(0), ast_mt_to_mt(tcx, mode, mt))
ast::ty_rptr(region, mt) {
let region = tcx.region_map.ast_type_to_region.get(region.id);
ty::mk_rptr(tcx, region, ast_mt_to_mt(tcx, mode, mt))
}
ast::ty_tup(fields) {
let flds = vec::map(fields, bind ast_ty_to_ty(tcx, mode, _));