rustc: Add fast paths for vars and param folds. 3x typechecking speedup.
This commit is contained in:
parent
73ae684536
commit
a4663d2845
@ -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.
|
||||
|
@ -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 {
|
||||
|
Loading…
x
Reference in New Issue
Block a user