rustc: Add region unification functions

This commit is contained in:
Patrick Walton 2012-03-21 13:28:50 -07:00
parent 68e364b54d
commit 3e47442471

View File

@ -1550,10 +1550,13 @@ mod unify {
type var_bindings =
{sets: ufind::ufind, types: smallintmap::smallintmap<t>};
type region_bindings =
{sets: ufind::ufind, regions: smallintmap::smallintmap<region>};
enum unify_style {
precise,
in_bindings(@var_bindings),
in_region_bindings(@var_bindings, @region_bindings)
}
type uctxt = {st: unify_style, tcx: ctxt};
@ -1561,15 +1564,22 @@ mod unify {
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.
fn union<T:copy>(
cx: @uctxt, set_a: uint, set_b: uint,
variance: variance, nxt: fn() -> ures<T>) -> ures<T> {
let vb = alt cx.st {
in_region_bindings(vb, _) { vb }
in_bindings(vb) { vb }
_ { cx.tcx.sess.bug("someone forgot to document an invariant \
in union"); }
precise {
cx.tcx.sess.bug("someone forgot to document an invariant \
in union");
}
};
ufind::grow(vb.sets, uint::max(set_a, set_b) + 1u);
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>(
cx: @uctxt, key: int,
typ: t, variance: variance,