about summary refs log tree commit diff
path: root/src/comp/middle
diff options
context:
space:
mode:
authorPatrick Walton <pcwalton@mimiga.net>2011-06-09 11:20:47 -0700
committerPatrick Walton <pcwalton@mimiga.net>2011-06-09 11:20:47 -0700
commita4663d2845b39f05a969af3cabe60a55dc0ee5fc (patch)
tree3238eb3ec0906259e0f12b18b89d202ea31bdc04 /src/comp/middle
parent73ae684536e61ccd1571558f391ec526dbce6e9c (diff)
downloadrust-a4663d2845b39f05a969af3cabe60a55dc0ee5fc.tar.gz
rust-a4663d2845b39f05a969af3cabe60a55dc0ee5fc.zip
rustc: Add fast paths for vars and param folds. 3x typechecking speedup.
Diffstat (limited to 'src/comp/middle')
-rw-r--r--src/comp/middle/trans.rs3
-rw-r--r--src/comp/middle/ty.rs128
2 files changed, 70 insertions, 61 deletions
diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs
index f08d450e81d..e08eed612cd 100644
--- a/src/comp/middle/trans.rs
+++ b/src/comp/middle/trans.rs
@@ -1260,8 +1260,7 @@ fn simplify_type(&@crate_ctxt ccx, &ty::t typ) -> ty::t {
             case (_) { ret typ; }
         }
     }
-    auto f = bind simplifier(ccx, _);
-    ret ty::fold_ty(ccx.tcx, f, typ);
+    ret ty::fold_ty(ccx.tcx, ty::fm_general(bind simplifier(ccx, _)), typ);
 }
 
 // Computes the size of the data part of a non-dynamically-sized tag.
diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs
index 3cd2602ed81..1c4046756e8 100644
--- a/src/comp/middle/ty.rs
+++ b/src/comp/middle/ty.rs
@@ -697,10 +697,22 @@ fn walk_ty(&ctxt cx, ty_walk walker, t ty) {
     walker(ty);
 }
 
-type ty_fold = fn(t) -> t;
+tag fold_mode {
+    fm_var(fn(int)->t);
+    fm_param(fn(uint)->t);
+    fm_general(fn(t)->t);
+}
 
-fn fold_ty(&ctxt cx, ty_fold fld, t ty_0) -> t {
+fn fold_ty(&ctxt cx, fold_mode fld, t ty_0) -> t {
     auto ty = ty_0;
+
+    // Fast paths.
+    alt (fld) {
+        case (fm_var(_)) { if (!type_contains_vars(cx, ty)) { ret ty; } }
+        case (fm_param(_)) { if (!type_contains_params(cx, ty)) { ret ty; } }
+        case (fm_general(_)) { /* no fast path */ }
+    }
+
     alt (struct(cx, ty)) {
         case (ty_nil)           { /* no-op */ }
         case (ty_bot)           { /* no-op */ }
@@ -788,11 +800,25 @@ fn fold_ty(&ctxt cx, ty_fold fld, t ty_0) -> t {
             }
             ty = copy_cname(cx, mk_obj(cx, new_methods), ty);
         }
-        case (ty_var(_))         { /* no-op */ }
-        case (ty_param(_))       { /* no-op */ }
+        case (ty_var(?id)) {
+            alt (fld) {
+                case (fm_var(?folder)) { ty = folder(id); }
+                case (_) { /* no-op */ }
+            }
+        }
+        case (ty_param(?id)) {
+            alt (fld) {
+                case (fm_param(?folder)) { ty = folder(id); }
+                case (_) { /* no-op */ }
+            }
+        }
     }
 
-    ret fld(ty);
+    // If this is a general type fold, then we need to run it now.
+    alt (fld) {
+        case (fm_general(?folder)) { ret folder(ty); }
+        case (_) { ret ty; }
+    }
 }
 
 // Type utilities
@@ -2101,29 +2127,23 @@ mod unify {
     fn resolve_all_vars(&ty_ctxt tcx, &@var_bindings vb, t typ) -> t {
         if (!type_contains_vars(tcx, typ)) { ret typ; }
 
-        fn folder(ty_ctxt tcx, @var_bindings vb, t typ) -> t {
-            alt (struct(tcx, typ)) {
-                case (ty_var(?vid)) {
-                    // It's possible that we haven't even created the var set.
-                    // Handle this case gracefully.
-                    if ((vid as uint) >= ufind::set_count(vb.sets)) {
-                        ret typ;
-                    }
+        fn folder(ty_ctxt tcx, @var_bindings vb, int vid) -> t {
+            // It's possible that we haven't even created the var set.
+            // Handle this case gracefully.
+            if ((vid as uint) >= ufind::set_count(vb.sets)) {
+                ret ty::mk_var(tcx, vid);
+            }
 
-                    auto root_id = ufind::find(vb.sets, vid as uint);
-                    alt (smallintmap::find[t](vb.types, root_id)) {
-                        case (some[t](?typ2)) {
-                            ret fold_ty(tcx, bind folder(tcx, vb, _), typ2);
-                        }
-                        case (none[t]) { ret typ; }
-                    }
+            auto root_id = ufind::find(vb.sets, vid as uint);
+            alt (smallintmap::find[t](vb.types, root_id)) {
+                case (some[t](?typ2)) {
+                    ret fold_ty(tcx, fm_var(bind folder(tcx, vb, _)), typ2);
                 }
-
-                case (_) { ret typ; }
+                case (none[t]) { ret ty::mk_var(tcx, vid); }
             }
         }
 
-        ret fold_ty(tcx, bind folder(tcx, vb, _), typ);
+        ret fold_ty(tcx, fm_var(bind folder(tcx, vb, _)), typ);
     }
 
     // If the given type is a variable, returns the structure of that type.
@@ -2542,32 +2562,29 @@ mod unify {
 
     fn fixup_vars(ty_ctxt tcx, @var_bindings vb, t typ) -> fixup_result {
         fn subst_vars(ty_ctxt tcx, @var_bindings vb,
-                      @mutable option::t[int] unresolved, t typ) -> t {
-            alt (struct(tcx, typ)) {
-                case (ty::ty_var(?vid)) {
-                    if ((vid as uint) >= ufind::set_count(vb.sets)) {
-                        *unresolved = some[int](vid);
-                        ret typ;
-                    }
+                      @mutable option::t[int] unresolved, int vid) -> t {
+            if ((vid as uint) >= ufind::set_count(vb.sets)) {
+                *unresolved = some[int](vid);
+                ret ty::mk_var(tcx, vid);
+            }
 
-                    auto root_id = ufind::find(vb.sets, vid as uint);
-                    alt (smallintmap::find[t](vb.types, root_id)) {
-                        case (none[t]) {
-                            *unresolved = some[int](vid);
-                            ret typ;
-                        }
-                        case (some[t](?rt)) {
-                            ret fold_ty(tcx,
-                                bind subst_vars(tcx, vb, unresolved, _), rt);
-                        }
-                    }
+            auto root_id = ufind::find(vb.sets, vid as uint);
+            alt (smallintmap::find[t](vb.types, root_id)) {
+                case (none[t]) {
+                    *unresolved = some[int](vid);
+                    ret ty::mk_var(tcx, vid);
+                }
+                case (some[t](?rt)) {
+                    ret fold_ty(tcx,
+                        fm_var(bind subst_vars(tcx, vb, unresolved, _)), rt);
                 }
-                case (_) { ret typ; }
             }
         }
 
         auto unresolved = @mutable none[int];
-        auto rty = fold_ty(tcx, bind subst_vars(tcx, vb, unresolved, _), typ);
+        auto rty = fold_ty(tcx,
+                           fm_var(bind subst_vars(tcx, vb, unresolved, _)),
+                           typ);
 
         auto ur = *unresolved;
         alt (ur) {
@@ -2641,8 +2658,7 @@ fn type_err_to_str(&ty::type_err err) -> str {
 // Converts type parameters in a type to type variables and returns the
 // resulting type along with a list of type variable IDs.
 fn bind_params_in_type(&ctxt cx, fn()->int next_ty_var, t typ,
-                       uint ty_param_count)
-        -> tup(vec[int], t) {
+                       uint ty_param_count) -> tup(vec[int], t) {
     let vec[int] param_var_ids = [];
     auto i = 0u;
     while (i < ty_param_count) {
@@ -2650,16 +2666,13 @@ fn bind_params_in_type(&ctxt cx, fn()->int next_ty_var, t typ,
         i += 1u;
     }
 
-    fn binder(ctxt cx, vec[int] param_var_ids, fn()->int next_ty_var, t typ)
-            -> t {
-        alt (struct(cx, typ)) {
-            case (ty_param(?index)) { ret mk_var(cx, param_var_ids.(index)); }
-            case (_) { ret typ; }
-        }
+    fn binder(ctxt cx, vec[int] param_var_ids, fn()->int next_ty_var,
+              uint index) -> t {
+        ret mk_var(cx, param_var_ids.(index));
     }
 
-    auto f = bind binder(cx, param_var_ids, next_ty_var, _);
-    auto new_typ = fold_ty(cx, f, typ);
+    auto new_typ = fold_ty(cx,
+        fm_param(bind binder(cx, param_var_ids, next_ty_var, _)), typ);
     ret tup(param_var_ids, new_typ);
 }
 
@@ -2668,14 +2681,11 @@ fn bind_params_in_type(&ctxt cx, fn()->int next_ty_var, t typ,
 fn substitute_type_params(&ctxt cx, vec[ty::t] substs, t typ) -> t {
     if (!type_contains_params(cx, typ)) { ret typ; }
 
-    fn substituter(ctxt cx, vec[ty::t] substs, t typ) -> t {
-        alt (struct(cx, typ)) {
-            case (ty_param(?idx)) { ret substs.(idx); }
-            case (_) { ret typ; }
-        }
+    fn substituter(ctxt cx, vec[ty::t] substs, uint idx) -> t {
+        ret substs.(idx);
     }
 
-    ret fold_ty(cx, bind substituter(cx, substs, _), typ);
+    ret fold_ty(cx, fm_param(bind substituter(cx, substs, _)), typ);
 }
 
 fn def_has_ty_params(&ast::def def) -> bool {