about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorPatrick Walton <pcwalton@mimiga.net>2011-03-08 12:19:37 -0800
committerPatrick Walton <pcwalton@mimiga.net>2011-03-08 12:19:37 -0800
commite2f6f19fc807e1e9067a5fa6abc188ddf21f775c (patch)
tree5939555e9eeff08bef272d56f65af5c1cf5cc628 /src
parent51be50490e277ce61d156fcf40a5d5b4057eee64 (diff)
downloadrust-e2f6f19fc807e1e9067a5fa6abc188ddf21f775c.tar.gz
rust-e2f6f19fc807e1e9067a5fa6abc188ddf21f775c.zip
rustc: Rework type substitution to pair up type parameter IDs with the supplied type parameter instantiations explicitly
Diffstat (limited to 'src')
-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 002a011bade..9634841a836 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,