aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Walton <[email protected]>2011-03-08 12:19:37 -0800
committerPatrick Walton <[email protected]>2011-03-08 12:19:37 -0800
commite2f6f19fc807e1e9067a5fa6abc188ddf21f775c (patch)
tree5939555e9eeff08bef272d56f65af5c1cf5cc628
parentrustc: Expose common.def_eq(). (diff)
downloadrust-e2f6f19fc807e1e9067a5fa6abc188ddf21f775c.tar.xz
rust-e2f6f19fc807e1e9067a5fa6abc188ddf21f775c.zip
rustc: Rework type substitution to pair up type parameter IDs with the supplied type parameter instantiations explicitly
-rw-r--r--src/comp/middle/typeck.rs103
1 files changed, 60 insertions, 43 deletions
diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs
index 002a011b..9634841a 100644
--- a/src/comp/middle/typeck.rs
+++ b/src/comp/middle/typeck.rs
@@ -85,59 +85,47 @@ fn generalize_ty(@crate_ctxt cx, @ty.t t) -> @ty.t {
// expression.
fn substitute_ty_params(&@crate_ctxt ccx,
@ty.t typ,
+ vec[ast.def_id] ty_params,
vec[@ast.ty] supplied,
&span sp) -> @ty.t {
state obj ty_substituter(@crate_ctxt ccx,
- @mutable uint i,
- vec[@ast.ty] supplied,
- @hashmap[int,@ty.t] substs) {
+ vec[ast.def_id] ty_params,
+ vec[@ast.ty] supplied) {
fn fold_simple_ty(@ty.t typ) -> @ty.t {
alt (typ.struct) {
- case (ty.ty_var(?vid)) {
- alt (substs.find(vid)) {
- case (some[@ty.t](?resolved_ty)) {
- ret resolved_ty;
- }
- case (none[@ty.t]) {
- if (i >= _vec.len[@ast.ty](supplied)) {
- // Just leave it as an unresolved parameter
- // for now. (We will error out later.)
- ret typ;
- }
-
- auto result = ast_ty_to_ty_crate(ccx,
- supplied.(*i));
- *i += 1u;
- substs.insert(vid, result);
- ret result;
- }
+ case (ty.ty_param(?pid)) {
+ // Find the index of the type parameter.
+ auto ty_param_len = _vec.len[ast.def_id](ty_params);
+ auto i = 0u;
+ while (i < ty_param_len &&
+ !common.def_eq(pid, ty_params.(i))) {
+ i += 1u;
+ }
+ if (i == ty_param_len) {
+ log "substitute_ty_params(): " +
+ "no ty param for param id!";
+ fail;
}
+
+ // Substitute it in.
+ ret ast_ty_to_ty_crate(ccx, supplied.(i));
}
case (_) { ret typ; }
}
}
}
- fn hash_int(&int x) -> uint { ret x as uint; }
- fn eq_int(&int a, &int b) -> bool { ret a == b; }
- auto hasher = hash_int;
- auto eqer = eq_int;
- auto substs = @map.mk_hashmap[int,@ty.t](hasher, eqer);
-
- auto subst_count = @mutable 0u;
- auto substituter = ty_substituter(ccx, subst_count, supplied, substs);
-
- auto result = ty.fold_ty(substituter, typ);
-
+ auto ty_param_len = _vec.len[ast.def_id](ty_params);
auto supplied_len = _vec.len[@ast.ty](supplied);
- if ((*subst_count) != supplied_len) {
- ccx.sess.span_err(sp, "expected " + _uint.to_str(*subst_count, 10u) +
+ if (ty_param_len != supplied_len) {
+ ccx.sess.span_err(sp, "expected " + _uint.to_str(ty_param_len, 10u) +
" type parameter(s) but found " +
_uint.to_str(supplied_len, 10u) + " parameter(s)");
fail;
}
- ret result;
+ auto substituter = ty_substituter(ccx, ty_params, supplied);
+ ret ty.fold_ty(substituter, typ);
}
// Parses the programmer's textual representation of a type into our internal
@@ -1476,49 +1464,60 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr {
case (ast.expr_path(?pth, ?defopt, _)) {
auto t = plain_ty(ty.ty_nil);
check (defopt != none[ast.def]);
+
+ auto ty_params;
alt (option.get[ast.def](defopt)) {
case (ast.def_arg(?id)) {
check (fcx.locals.contains_key(id));
t = fcx.locals.get(id);
+ ty_params = none[vec[ast.def_id]];
}
case (ast.def_local(?id)) {
alt (fcx.locals.find(id)) {
case (some[@ty.t](?t1)) { t = t1; }
case (none[@ty.t]) { t = plain_ty(ty.ty_local(id)); }
}
+ ty_params = none[vec[ast.def_id]];
}
case (ast.def_obj_field(?id)) {
check (fcx.locals.contains_key(id));
t = fcx.locals.get(id);
+ ty_params = none[vec[ast.def_id]];
}
case (ast.def_fn(?id)) {
check (fcx.ccx.item_types.contains_key(id));
- t = generalize_ty(fcx.ccx, fcx.ccx.item_types.get(id));
+ t = fcx.ccx.item_types.get(id);
+ ty_params = some(fcx.ccx.item_ty_params.get(id));
}
case (ast.def_native_fn(?id)) {
check (fcx.ccx.item_types.contains_key(id));
- t = generalize_ty(fcx.ccx, fcx.ccx.item_types.get(id));
+ t = fcx.ccx.item_types.get(id);
+ ty_params = some(fcx.ccx.item_ty_params.get(id));
}
case (ast.def_const(?id)) {
check (fcx.ccx.item_types.contains_key(id));
t = fcx.ccx.item_types.get(id);
+ ty_params = none[vec[ast.def_id]];
}
- case (ast.def_variant(_, ?variant_id)) {
+ case (ast.def_variant(?tag_id, ?variant_id)) {
check (fcx.ccx.item_types.contains_key(variant_id));
- t = generalize_ty(fcx.ccx,
- fcx.ccx.item_types.get(variant_id));
+ t = fcx.ccx.item_types.get(variant_id);
+ ty_params = some(fcx.ccx.item_ty_params.get(tag_id));
}
case (ast.def_binding(?id)) {
check (fcx.locals.contains_key(id));
t = fcx.locals.get(id);
+ ty_params = none[vec[ast.def_id]];
}
case (ast.def_obj(?id)) {
check (fcx.ccx.item_types.contains_key(id));
- t = generalize_ty(fcx.ccx, fcx.ccx.item_types.get(id));
+ t = fcx.ccx.item_types.get(id);
+ ty_params = some(fcx.ccx.item_ty_params.get(id));
}
case (ast.def_mod(_)) {
// Hopefully part of a path.
+ ty_params = none[vec[ast.def_id]];
}
case (_) {
@@ -1531,8 +1530,26 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr {
// Substitute type parameters if the user provided some.
if (_vec.len[@ast.ty](pth.node.types) > 0u) {
- t = substitute_ty_params(fcx.ccx, t, pth.node.types,
- expr.span);
+ alt (ty_params) {
+ case (none[vec[ast.def_id]]) {
+ fcx.ccx.sess.span_err(expr.span, "this kind of " +
+ "item may not take type " +
+ "parameters");
+ }
+ case (some[vec[ast.def_id]](?tps)) {
+ t = substitute_ty_params(fcx.ccx, t, tps,
+ pth.node.types, expr.span);
+ }
+ }
+ } else {
+ alt (ty_params) {
+ case (none[vec[ast.def_id]]) { /* nothing */ }
+ case (some[vec[ast.def_id]](_)) {
+ // We will acquire the type parameters through
+ // unification.
+ t = generalize_ty(fcx.ccx, t);
+ }
+ }
}
ret @fold.respan[ast.expr_](expr.span,