rustc: Combine and unify regions
This commit is contained in:
parent
03086c5304
commit
b7a741b5d0
@ -409,39 +409,9 @@ impl unify_methods for infer_ctxt {
|
||||
}
|
||||
|
||||
fn regions(a: ty::region, b: ty::region) -> ures {
|
||||
alt (a, b) {
|
||||
(ty::re_var(_), _) | (_, ty::re_var(_)) {
|
||||
self.uok() // FIXME: We need region variables!
|
||||
}
|
||||
(ty::re_inferred, _) | (_, ty::re_inferred) {
|
||||
fail "tried to unify inferred regions"
|
||||
}
|
||||
(ty::re_param(_), ty::re_param(_)) |
|
||||
(ty::re_self, ty::re_self) {
|
||||
if a == b {
|
||||
self.uok()
|
||||
} else {
|
||||
self.uerr(ty::terr_regions_differ(false, a, b))
|
||||
}
|
||||
}
|
||||
(ty::re_param(_), ty::re_block(_)) |
|
||||
(ty::re_self, ty::re_block(_)) {
|
||||
self.uok()
|
||||
}
|
||||
(ty::re_block(_), ty::re_param(_)) |
|
||||
(ty::re_block(_), ty::re_self) {
|
||||
self.uerr(ty::terr_regions_differ(false, a, b))
|
||||
}
|
||||
(ty::re_block(superblock), ty::re_block(subblock)) {
|
||||
// The region corresponding to an outer block is a subtype of the
|
||||
// region corresponding to an inner block.
|
||||
let rm = self.tcx.region_map;
|
||||
if region::scope_contains(rm, subblock, superblock) {
|
||||
self.uok()
|
||||
} else {
|
||||
self.uerr(ty::terr_regions_differ(false, a, b))
|
||||
}
|
||||
}
|
||||
alt combine_or_unify_regions(self.tcx, a, b, false) {
|
||||
ok(_) { self.uok() }
|
||||
err(e) { self.uerr(e) }
|
||||
}
|
||||
}
|
||||
|
||||
@ -1214,6 +1184,47 @@ fn c_tys<C:combine>(
|
||||
}
|
||||
}
|
||||
|
||||
fn combine_or_unify_regions(tcx: ty::ctxt,
|
||||
a: ty::region,
|
||||
b: ty::region,
|
||||
contravariant_combine: bool) -> cres<ty::region> {
|
||||
alt (a, b) {
|
||||
(ty::re_var(_), _) | (_, ty::re_var(_)) {
|
||||
ok(a) // FIXME: We need region variables!
|
||||
}
|
||||
(ty::re_inferred, _) | (_, ty::re_inferred) {
|
||||
fail "tried to combine or unify inferred regions"
|
||||
}
|
||||
(ty::re_param(_), ty::re_param(_)) |
|
||||
(ty::re_self, ty::re_self) {
|
||||
if a == b {
|
||||
ok(a)
|
||||
} else {
|
||||
err(ty::terr_regions_differ(false, a, b))
|
||||
}
|
||||
}
|
||||
(ty::re_param(_), ty::re_block(_)) |
|
||||
(ty::re_self, ty::re_block(_)) {
|
||||
ok(a)
|
||||
}
|
||||
(ty::re_block(_), ty::re_param(_)) |
|
||||
(ty::re_block(_), ty::re_self) {
|
||||
err(ty::terr_regions_differ(false, a, b))
|
||||
}
|
||||
(ty::re_block(block_a), ty::re_block(block_b)) {
|
||||
// The region corresponding to an outer block is a subtype of the
|
||||
// region corresponding to an inner block.
|
||||
let rm = tcx.region_map;
|
||||
let nca_opt = region::nearest_common_ancestor(rm, block_a, block_b);
|
||||
alt nca_opt {
|
||||
some(nca) if nca == block_b { ok(a) }
|
||||
some(nca) if contravariant_combine { ok(ty::re_block(nca)) }
|
||||
_ { err(ty::terr_regions_differ(false, a, b)) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl of combine for lub {
|
||||
fn infcx() -> infer_ctxt { *self }
|
||||
|
||||
@ -1232,10 +1243,6 @@ impl of combine for lub {
|
||||
ok(b)
|
||||
}
|
||||
|
||||
fn c_regions(a: ty::region, _b: ty::region) -> cres<ty::region> {
|
||||
ok(a) // FIXME
|
||||
}
|
||||
|
||||
fn c_mts(a: ty::mt, b: ty::mt) -> cres<ty::mt> {
|
||||
let tcx = self.infcx().tcx;
|
||||
|
||||
@ -1302,6 +1309,10 @@ impl of combine for lub {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn c_regions(a: ty::region, b: ty::region) -> cres<ty::region> {
|
||||
ret combine_or_unify_regions(self.tcx, a, b, true);
|
||||
}
|
||||
}
|
||||
|
||||
impl of combine for glb {
|
||||
@ -1410,4 +1421,8 @@ impl of combine for glb {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn c_regions(a: ty::region, b: ty::region) -> cres<ty::region> {
|
||||
ret combine_or_unify_regions(self.tcx, a, b, false);
|
||||
}
|
||||
}
|
||||
|
@ -84,6 +84,42 @@ fn scope_contains(region_map: @region_map, superscope: ast::node_id,
|
||||
ret true;
|
||||
}
|
||||
|
||||
fn nearest_common_ancestor(region_map: @region_map, scope_a: ast::node_id,
|
||||
scope_b: ast::node_id) -> option<ast::node_id> {
|
||||
|
||||
fn ancestors_of(region_map: @region_map, scope: ast::node_id)
|
||||
-> [ast::node_id] {
|
||||
let mut result = [scope];
|
||||
let mut scope = scope;
|
||||
loop {
|
||||
alt region_map.parents.find(scope) {
|
||||
none { ret result; }
|
||||
some(superscope) {
|
||||
result += [superscope];
|
||||
scope = superscope;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if scope_a == scope_b { ret some(scope_a); }
|
||||
|
||||
let a_ancestors = ancestors_of(region_map, scope_a);
|
||||
let b_ancestors = ancestors_of(region_map, scope_b);
|
||||
let mut a_index = vec::len(a_ancestors) - 1u;
|
||||
let mut b_index = vec::len(b_ancestors) - 1u;
|
||||
while a_ancestors[a_index] == b_ancestors[b_index] {
|
||||
a_index -= 1u;
|
||||
b_index -= 1u;
|
||||
}
|
||||
|
||||
if a_index == vec::len(a_ancestors) {
|
||||
ret none;
|
||||
}
|
||||
|
||||
ret some(a_ancestors[a_index + 1u]);
|
||||
}
|
||||
|
||||
fn get_inferred_region(cx: ctxt, sp: syntax::codemap::span) -> ty::region {
|
||||
// We infer to the caller region if we're at item scope
|
||||
// and to the block region if we're at block scope.
|
||||
|
Loading…
x
Reference in New Issue
Block a user