From 64176107886f75d92725f9607ffc0dd5e488afff Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Thu, 19 May 2011 11:14:04 -0700 Subject: [PATCH] rustc: Generalize variable bindings so that we can use it for locals too --- src/comp/middle/ty.rs | 72 ++++++++++++++++++++------------------- src/comp/middle/typeck.rs | 9 ++--- src/lib/int.rs | 4 +++ 3 files changed, 46 insertions(+), 39 deletions(-) diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs index 6b2ee1441bba..65d603895a3f 100644 --- a/src/comp/middle/ty.rs +++ b/src/comp/middle/ty.rs @@ -1865,18 +1865,19 @@ mod unify { ures_err(type_err, t, t); } - type var_bindings = rec(ufind::ufind sets, - hashmap[int,uint] var_ids, - mutable vec[mutable vec[t]] types); + type bindings[T] = rec(ufind::ufind sets, + hashmap[T,uint] ids, + mutable vec[mutable vec[t]] types); - fn mk_var_bindings() -> @var_bindings { + fn mk_bindings[T](map::hashfn[T] hasher, map::eqfn[T] eqer) + -> @bindings[T] { let vec[mutable vec[t]] types = [mutable]; ret @rec(sets=ufind::make(), - var_ids=common::new_int_hash[uint](), + ids=map::mk_hashmap[T,uint](hasher, eqer), mutable types=types); } - type ctxt = rec(@var_bindings var_bindings, + type ctxt = rec(@bindings[int] bindings, unify_handler handler, ty_ctxt tcx); @@ -2079,10 +2080,10 @@ mod unify { fn get_or_create_set(&@ctxt cx, int id) -> uint { auto set_num; - alt (cx.var_bindings.var_ids.find(id)) { + alt (cx.bindings.ids.find(id)) { case (none[uint]) { - set_num = ufind::make_set(cx.var_bindings.sets); - cx.var_bindings.var_ids.insert(id, set_num); + set_num = ufind::make_set(cx.bindings.sets); + cx.bindings.ids.insert(id, set_num); } case (some[uint](?n)) { set_num = n; } } @@ -2107,18 +2108,17 @@ mod unify { alt (struct(cx.tcx, expected)) { case (ty::ty_var(?expected_id)) { auto expected_n = get_or_create_set(cx, expected_id); - ufind::union(cx.var_bindings.sets, expected_n, - actual_n); + ufind::union(cx.bindings.sets, expected_n, actual_n); } case (_) { // Just bind the type variable to the expected type. - auto vlen = vec::len[vec[t]](cx.var_bindings.types); + auto vlen = vec::len[vec[t]](cx.bindings.types); if (actual_n < vlen) { - cx.var_bindings.types.(actual_n) += [expected]; + cx.bindings.types.(actual_n) += [expected]; } else { assert (actual_n == vlen); - cx.var_bindings.types += [mutable [expected]]; + cx.bindings.types += [mutable [expected]]; } } } @@ -2482,12 +2482,12 @@ mod unify { case (ty::ty_var(?expected_id)) { // Add a binding. auto expected_n = get_or_create_set(cx, expected_id); - auto vlen = vec::len[vec[t]](cx.var_bindings.types); + auto vlen = vec::len[vec[t]](cx.bindings.types); if (expected_n < vlen) { - cx.var_bindings.types.(expected_n) += [actual]; + cx.bindings.types.(expected_n) += [actual]; } else { assert (expected_n == vlen); - cx.var_bindings.types += [mutable [actual]]; + cx.bindings.types += [mutable [actual]]; } ret ures_ok(expected); } @@ -2519,19 +2519,23 @@ mod unify { } // Performs type binding substitution. - fn substitute(&ty_ctxt tcx, &@var_bindings var_bindings, - &vec[t] set_types, &t typ) -> t { + fn substitute(&ty_ctxt tcx, + &@bindings[int] bindings, + &vec[t] set_types, + &t typ) -> t { if (!type_contains_vars(tcx, typ)) { ret typ; } - fn substituter(ty_ctxt tcx, @var_bindings var_bindings, vec[t] types, + fn substituter(ty_ctxt tcx, + @bindings[int] bindings, + vec[t] types, t typ) -> t { alt (struct(tcx, typ)) { case (ty_var(?id)) { - alt (var_bindings.var_ids.find(id)) { + alt (bindings.ids.find(id)) { case (some[uint](?n)) { - auto root = ufind::find(var_bindings.sets, n); + auto root = ufind::find(bindings.sets, n); ret types.(root); } case (none[uint]) { ret typ; } @@ -2541,24 +2545,22 @@ mod unify { } } - auto f = bind substituter(tcx, var_bindings, set_types, _); + auto f = bind substituter(tcx, bindings, set_types, _); ret fold_ty(tcx, f, typ); } - fn unify_sets(&@var_bindings var_bindings) -> vec[t] { - let vec[t] throwaway = []; - let vec[mutable vec[t]] set_types = [mutable throwaway]; - vec::pop[vec[t]](set_types); // FIXME: botch + fn unify_sets[T](&@bindings[T] bindings) -> vec[t] { + let vec[mutable vec[t]] set_types = [mutable]; - for (ufind::node node in var_bindings.sets.nodes) { + for (ufind::node node in bindings.sets.nodes) { let vec[t] v = []; set_types += [mutable v]; } auto i = 0u; while (i < vec::len[vec[t]](set_types)) { - auto root = ufind::find(var_bindings.sets, i); - set_types.(root) += var_bindings.types.(i); + auto root = ufind::find(bindings.sets, i); + set_types.(root) += bindings.types.(i); i += 1u; } @@ -2578,15 +2580,15 @@ mod unify { fn unify(&t expected, &t actual, &unify_handler handler, - &@var_bindings var_bindings, + &@bindings[int] bindings, &ty_ctxt tcx) -> result { - auto cx = @rec(var_bindings=var_bindings, handler=handler, tcx=tcx); + auto cx = @rec(bindings=bindings, handler=handler, tcx=tcx); ret unify_step(cx, expected, actual); } - fn fixup(&ty_ctxt tcx, &@var_bindings var_bindings, t typ) -> t { - auto set_types = unify_sets(var_bindings); - ret substitute(tcx, var_bindings, set_types, typ); + fn fixup(&ty_ctxt tcx, &@bindings[int] bindings, t typ) -> t { + auto set_types = unify_sets[int](bindings); + ret substitute(tcx, bindings, set_types, typ); } } diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index dbad2715776e..72c22ab691c4 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -37,6 +37,7 @@ import middle::ty::ty_nil; import middle::ty::unify::ures_ok; import middle::ty::unify::ures_err; +import std::int; import std::str; import std::uint; import std::vec; @@ -969,15 +970,15 @@ mod unify { auto handler = unify_handler(scx, param_substs); - auto var_bindings = ty::unify::mk_var_bindings(); - auto result = ty::unify::unify(expected, actual, handler, - var_bindings, scx.fcx.ccx.tcx); + auto bindings = ty::unify::mk_bindings[int](int::hash, int::eq_alias); + auto result = ty::unify::unify(expected, actual, handler, bindings, + scx.fcx.ccx.tcx); alt (result) { case (ures_ok(?rty)) { if (ty::type_contains_vars(scx.fcx.ccx.tcx, rty)) { result = ures_ok(ty::unify::fixup(scx.fcx.ccx.tcx, - var_bindings, rty)); + bindings, rty)); } } case (_) { /* nothing */ } diff --git a/src/lib/int.rs b/src/lib/int.rs index 1e253b3857cb..23aabbc6cd98 100644 --- a/src/lib/int.rs +++ b/src/lib/int.rs @@ -17,6 +17,10 @@ fn negative(int x) -> bool { ret x < 0; } fn nonpositive(int x) -> bool { ret x <= 0; } fn nonnegative(int x) -> bool { ret x >= 0; } +// FIXME: Make sure this works with negative integers. +fn hash(&int x) -> uint { ret x as uint; } +fn eq_alias(&int x, &int y) -> bool { ret x == y; } + iter range(int lo, int hi) -> int { let int lo_ = lo; while (lo_ < hi) {