about summary refs log tree commit diff
diff options
context:
space:
mode:
authorPatrick Walton <pcwalton@mimiga.net>2012-03-21 13:28:50 -0700
committerPatrick Walton <pcwalton@mimiga.net>2012-03-21 13:28:50 -0700
commit3e474424714f8e24fd1237d77cf88a3b35a495e5 (patch)
tree4aa230ecf124d82041163dc4e126372506b04374
parent68e364b54d8caad98d69679a8e4d1cee8d6607c5 (diff)
downloadrust-3e474424714f8e24fd1237d77cf88a3b35a495e5.tar.gz
rust-3e474424714f8e24fd1237d77cf88a3b35a495e5.zip
rustc: Add region unification functions
-rw-r--r--src/rustc/middle/ty.rs62
1 files changed, 60 insertions, 2 deletions
diff --git a/src/rustc/middle/ty.rs b/src/rustc/middle/ty.rs
index f7f647c89e3..4666487a238 100644
--- a/src/rustc/middle/ty.rs
+++ b/src/rustc/middle/ty.rs
@@ -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,