rustc: Unify regions in most cases. (Nested functions aren't properly handled yet.)
This commit is contained in:
parent
f7efc29b38
commit
3e8bb22af1
@ -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}, _) {
|
||||
|
@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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, _));
|
||||
|
Loading…
Reference in New Issue
Block a user