rustc: Add region unification functions
This commit is contained in:
@@ -1550,10 +1550,13 @@ mod unify {
|
|||||||
|
|
||||||
type var_bindings =
|
type var_bindings =
|
||||||
{sets: ufind::ufind, types: smallintmap::smallintmap<t>};
|
{sets: ufind::ufind, types: smallintmap::smallintmap<t>};
|
||||||
|
type region_bindings =
|
||||||
|
{sets: ufind::ufind, regions: smallintmap::smallintmap<region>};
|
||||||
|
|
||||||
enum unify_style {
|
enum unify_style {
|
||||||
precise,
|
precise,
|
||||||
in_bindings(@var_bindings),
|
in_bindings(@var_bindings),
|
||||||
|
in_region_bindings(@var_bindings, @region_bindings)
|
||||||
}
|
}
|
||||||
type uctxt = {st: unify_style, tcx: ctxt};
|
type uctxt = {st: unify_style, tcx: ctxt};
|
||||||
|
|
||||||
@@ -1561,15 +1564,22 @@ mod unify {
|
|||||||
ret @{sets: ufind::make(), types: smallintmap::mk::<t>()};
|
ret @{sets: ufind::make(), types: smallintmap::mk::<t>()};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn mk_region_bindings() -> @region_bindings {
|
||||||
|
ret @{sets: ufind::make(), regions: smallintmap::mk::<region>()};
|
||||||
|
}
|
||||||
|
|
||||||
// Unifies two sets.
|
// Unifies two sets.
|
||||||
fn union<T:copy>(
|
fn union<T:copy>(
|
||||||
cx: @uctxt, set_a: uint, set_b: uint,
|
cx: @uctxt, set_a: uint, set_b: uint,
|
||||||
variance: variance, nxt: fn() -> ures<T>) -> ures<T> {
|
variance: variance, nxt: fn() -> ures<T>) -> ures<T> {
|
||||||
|
|
||||||
let vb = alt cx.st {
|
let vb = alt cx.st {
|
||||||
|
in_region_bindings(vb, _) { vb }
|
||||||
in_bindings(vb) { vb }
|
in_bindings(vb) { vb }
|
||||||
_ { cx.tcx.sess.bug("someone forgot to document an invariant \
|
precise {
|
||||||
in union"); }
|
cx.tcx.sess.bug("someone forgot to document an invariant \
|
||||||
|
in union");
|
||||||
|
}
|
||||||
};
|
};
|
||||||
ufind::grow(vb.sets, uint::max(set_a, set_b) + 1u);
|
ufind::grow(vb.sets, uint::max(set_a, set_b) + 1u);
|
||||||
let root_a = ufind::find(vb.sets, set_a);
|
let root_a = ufind::find(vb.sets, set_a);
|
||||||
@@ -1604,6 +1614,54 @@ mod unify {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Unifies two region sets.
|
||||||
|
//
|
||||||
|
// FIXME: This is a straight copy of the code above. We should use
|
||||||
|
// polymorphism to make this better.
|
||||||
|
fn union_region_sets<T:copy>(
|
||||||
|
cx: @uctxt, set_a: uint, set_b: uint,
|
||||||
|
variance: variance, nxt: fn() -> ures<T>) -> ures<T> {
|
||||||
|
|
||||||
|
let rb = alt cx.st {
|
||||||
|
in_region_bindings(_, rb) { rb }
|
||||||
|
in_bindings(_) | precise {
|
||||||
|
cx.tcx.sess.bug("attempted to unify two region sets without \
|
||||||
|
a set of region bindings present");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
ufind::grow(rb.sets, uint::max(set_a, set_b) + 1u);
|
||||||
|
let root_a = ufind::find(rb.sets, set_a);
|
||||||
|
let root_b = ufind::find(rb.sets, set_b);
|
||||||
|
|
||||||
|
let replace_region = (
|
||||||
|
fn@(rb: @region_bindings, r: region) {
|
||||||
|
ufind::union(rb.sets, set_a, set_b);
|
||||||
|
let root_c: uint = ufind::find(rb.sets, set_a);
|
||||||
|
smallintmap::insert::<region>(rb.regions, root_c, r);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
alt smallintmap::find(rb.regions, root_a) {
|
||||||
|
none {
|
||||||
|
alt smallintmap::find(rb.regions, root_b) {
|
||||||
|
none { ufind::union(rb.sets, set_a, set_b); ret nxt(); }
|
||||||
|
some(r_b) { replace_region(rb, r_b); ret nxt(); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
some(r_a) {
|
||||||
|
alt smallintmap::find(rb.regions, root_b) {
|
||||||
|
none { replace_region(rb, r_a); ret nxt(); }
|
||||||
|
some(r_b) {
|
||||||
|
ret unify_regions(cx, r_a, r_b, variance) {|r_c|
|
||||||
|
replace_region(rb, r_c);
|
||||||
|
nxt()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn record_var_binding<T:copy>(
|
fn record_var_binding<T:copy>(
|
||||||
cx: @uctxt, key: int,
|
cx: @uctxt, key: int,
|
||||||
typ: t, variance: variance,
|
typ: t, variance: variance,
|
||||||
|
|||||||
Reference in New Issue
Block a user