about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorPatrick Walton <pcwalton@mimiga.net>2011-07-01 12:46:14 -0700
committerPatrick Walton <pcwalton@mimiga.net>2011-07-06 11:09:06 -0700
commit09e591c12fcfef0533c113eca7dab59cd770e521 (patch)
tree101c57d7aa00ac9ea9ecd286ba225c72821df6db /src
parent9c4411ac5eb9b96fa8fac490103d95d39980cfd8 (diff)
downloadrust-09e591c12fcfef0533c113eca7dab59cd770e521.tar.gz
rust-09e591c12fcfef0533c113eca7dab59cd770e521.zip
rustc: Use interior vectors for tag type parameters
Diffstat (limited to 'src')
-rw-r--r--src/comp/metadata/tydecode.rs4
-rw-r--r--src/comp/middle/trans.rs100
-rw-r--r--src/comp/middle/ty.rs55
-rw-r--r--src/comp/middle/typeck.rs145
-rw-r--r--src/comp/util/ppaux.rs7
5 files changed, 188 insertions, 123 deletions
diff --git a/src/comp/metadata/tydecode.rs b/src/comp/metadata/tydecode.rs
index b40a84ec305..052af38c151 100644
--- a/src/comp/metadata/tydecode.rs
+++ b/src/comp/metadata/tydecode.rs
@@ -169,8 +169,8 @@ fn parse_ty(@pstate st, str_def sd) -> ty::t {
         case ('t') {
             assert (next(st) as char == '[');
             auto def = parse_def(st, sd);
-            let vec[ty::t] params = [];
-            while (peek(st) as char != ']') { params += [parse_ty(st, sd)]; }
+            let ty::t[] params = ~[];
+            while (peek(st) as char != ']') { params += ~[parse_ty(st, sd)]; }
             st.pos = st.pos + 1u;
             ret ty::mk_tag(st.tcx, def, params);
         }
diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs
index 7647ccd23fe..2abba3e6c21 100644
--- a/src/comp/middle/trans.rs
+++ b/src/comp/middle/trans.rs
@@ -879,7 +879,11 @@ fn type_of_inner(&@crate_ctxt cx, &span sp, &ty::t t) -> TypeRef {
             llty = abs_pair;
         }
         case (ty::ty_res(_, ?sub, ?tps)) {
-            auto sub1 = ty::substitute_type_params(cx.tcx, tps, sub);
+            // FIXME: Remove this vec->ivec conversion.
+            auto tps_ivec = ~[];
+            for (ty::t typ in tps) { tps_ivec += ~[typ]; }
+
+            auto sub1 = ty::substitute_type_params(cx.tcx, tps_ivec, sub);
             ret T_struct([T_i32(), type_of_inner(cx, sp, sub1)]);
         }
         case (ty::ty_var(_)) {
@@ -1240,7 +1244,12 @@ fn simplify_type(&@crate_ctxt ccx, &ty::t typ) -> ty::t {
                                                     ty::mk_nil(ccx.tcx))]);
             }
             case (ty::ty_res(_, ?sub, ?tps)) {
-                auto sub1 = ty::substitute_type_params(ccx.tcx, tps, sub);
+                // FIXME: Remove this vec->ivec conversion.
+                auto tps_ivec = ~[];
+                for (ty::t typ in tps) { tps_ivec += ~[typ]; }
+
+                auto sub1 = ty::substitute_type_params(ccx.tcx, tps_ivec,
+                                                       sub);
                 ret ty::mk_imm_tup(ccx.tcx, ~[ty::mk_int(ccx.tcx),
                                               simplify_type(ccx, sub1)]);
             }
@@ -1259,36 +1268,35 @@ fn static_size_of_tag(&@crate_ctxt cx, &span sp, &ty::t t) -> uint {
                                  "static_size_of_tag()");
     }
     if (cx.tag_sizes.contains_key(t)) { ret cx.tag_sizes.get(t); }
-    auto tid;
-    let vec[ty::t] subtys;
     alt (ty::struct(cx.tcx, t)) {
-        case (ty::ty_tag(?tid_, ?subtys_)) { tid = tid_; subtys = subtys_; }
+        case (ty::ty_tag(?tid, ?subtys)) {
+            // Compute max(variant sizes).
+
+            auto max_size = 0u;
+            auto variants = ty::tag_variants(cx.tcx, tid);
+            for (ty::variant_info variant in variants) {
+                // TODO: Remove this vec->ivec conversion.
+                auto args = ~[];
+                for (ty::t typ in variant.args) { args += ~[typ]; }
+
+                auto tup_ty = simplify_type(cx, ty::mk_imm_tup(cx.tcx, args));
+                // Perform any type parameter substitutions.
+
+                tup_ty = ty::substitute_type_params(cx.tcx, subtys, tup_ty);
+                // Here we possibly do a recursive call.
+
+                auto this_size = llsize_of_real(cx, type_of(cx, sp, tup_ty));
+                if (max_size < this_size) { max_size = this_size; }
+            }
+            cx.tag_sizes.insert(t, max_size);
+            ret max_size;
+        }
         case (_) {
             cx.tcx.sess.span_fatal(sp,
                                  "non-tag passed to " +
                                      "static_size_of_tag()");
         }
     }
-    // Compute max(variant sizes).
-
-    auto max_size = 0u;
-    auto variants = ty::tag_variants(cx.tcx, tid);
-    for (ty::variant_info variant in variants) {
-        // TODO: Remove this vec->ivec conversion.
-        auto args = ~[];
-        for (ty::t typ in variant.args) { args += ~[typ]; }
-
-        auto tup_ty = simplify_type(cx, ty::mk_imm_tup(cx.tcx, args));
-        // Perform any type parameter substitutions.
-
-        tup_ty = ty::substitute_type_params(cx.tcx, subtys, tup_ty);
-        // Here we possibly do a recursive call.
-
-        auto this_size = llsize_of_real(cx, type_of(cx, sp, tup_ty));
-        if (max_size < this_size) { max_size = this_size; }
-    }
-    cx.tag_sizes.insert(t, max_size);
-    ret max_size;
 }
 
 fn dynamic_size_of(&@block_ctxt cx, ty::t t) -> result {
@@ -1516,7 +1524,7 @@ fn GEP_tup_like(&@block_ctxt cx, &ty::t t, ValueRef base, &vec[int] ixs) ->
 // appropriate. @llblobptr is the data part of a tag value; its actual type is
 // meaningless, as it will be cast away.
 fn GEP_tag(@block_ctxt cx, ValueRef llblobptr, &ast::def_id tag_id,
-           &ast::def_id variant_id, &vec[ty::t] ty_substs, int ix) -> result {
+           &ast::def_id variant_id, &ty::t[] ty_substs, int ix) -> result {
     auto variant =
         ty::tag_variant_with_id(cx.fcx.lcx.ccx.tcx, tag_id, variant_id);
     // Synthesize a tuple type so that GEP_tup_like() can work its magic.
@@ -2138,8 +2146,12 @@ fn make_drop_glue(&@block_ctxt cx, ValueRef v0, &ty::t t) {
 
 fn trans_res_drop(@block_ctxt cx, ValueRef rs, &ast::def_id did,
                   ty::t inner_t, &vec[ty::t] tps) -> result {
+    // FIXME: Remove this vec->ivec conversion.
+    auto tps_ivec = ~[];
+    for (ty::t tp in tps) { tps_ivec += ~[tp]; }
+
     auto ccx = cx.fcx.lcx.ccx;
-    auto inner_t_s = ty::substitute_type_params(ccx.tcx, tps, inner_t);
+    auto inner_t_s = ty::substitute_type_params(ccx.tcx, tps_ivec, inner_t);
     auto tup_ty = ty::mk_imm_tup(ccx.tcx, ~[ty::mk_int(ccx.tcx), inner_t_s]);
     auto drop_cx = new_sub_block_ctxt(cx, "drop res");
     auto next_cx = new_sub_block_ctxt(cx, "next");
@@ -2645,7 +2657,7 @@ fn iter_structural_ty_full(&@block_ctxt cx, ValueRef av, ValueRef bv,
     }
 
     fn iter_variant(@block_ctxt cx, ValueRef a_tup, ValueRef b_tup,
-                    &ty::variant_info variant, &vec[ty::t] tps,
+                    &ty::variant_info variant, &ty::t[] tps,
                     &ast::def_id tid, &val_pair_and_ty_fn f) -> result {
         if (vec::len[ty::t](variant.args) == 0u) {
             ret rslt(cx, C_nil());
@@ -2707,8 +2719,12 @@ fn iter_structural_ty_full(&@block_ctxt cx, ValueRef av, ValueRef bv,
             }
         }
         case (ty::ty_res(_, ?inner, ?tps)) {
+            // FIXME: Remove this vec->ivec conversion.
+            auto tps_ivec = ~[];
+            for (ty::t tp in tps) { tps_ivec += ~[tp]; }
+
             auto inner1 = ty::substitute_type_params(cx.fcx.lcx.ccx.tcx,
-                                                     tps, inner);
+                                                     tps_ivec, inner);
             r = GEP_tup_like(r.bcx, t, av, [0, 1]);
             auto llfld_a = r.val;
             r = GEP_tup_like(r.bcx, t, bv, [0, 1]);
@@ -4137,8 +4153,12 @@ fn autoderef_lval(&@block_ctxt cx, ValueRef v, &ty::t t, bool is_lval)
                 } else { v1 = body; }
             }
             case (ty::ty_res(?did, ?inner, ?tps)) {
+                // FIXME: Remove this vec->ivec conversion.
+                auto tps_ivec = ~[];
+                for (ty::t tp in tps) { tps_ivec += ~[tp]; }
+
                 if (is_lval) { v1 = cx.build.Load(v1); }
-                t1 = ty::substitute_type_params(ccx.tcx, tps, inner);
+                t1 = ty::substitute_type_params(ccx.tcx, tps_ivec, inner);
                 v1 = cx.build.GEP(v1, [C_int(0), C_int(1)]);
             }
             case (ty::ty_tag(?did, ?tps)) {
@@ -4712,14 +4732,19 @@ fn trans_pat_match(&@block_ctxt cx, &@ast::pat pat, ValueRef llval,
                         matched_cx.build.GEP(lltagptr, [C_int(0), C_int(1)]);
                 }
             }
+
             auto ty_params = ty::node_id_to_type_params
                 (cx.fcx.lcx.ccx.tcx, pat.id);
+            // FIXME: Remove this vec->ivec conversion.
+            auto tps_ivec = ~[];
+            for (ty::t tp in ty_params) { tps_ivec += ~[tp]; }
+
             if (vec::len(subpats) > 0u) {
                 auto i = 0;
                 for (@ast::pat subpat in subpats) {
                     auto rslt =
                         GEP_tag(matched_cx, llblobptr, vdef._0, vdef._1,
-                                ty_params, i);
+                                tps_ivec, i);
                     auto llsubvalptr = rslt.val;
                     matched_cx = rslt.bcx;
                     auto llsubval =
@@ -4773,14 +4798,19 @@ fn trans_pat_binding(&@block_ctxt cx, &@ast::pat pat, ValueRef llval,
                     (llval, T_opaque_tag_ptr(cx.fcx.lcx.ccx.tn));
                 llblobptr = cx.build.GEP(lltagptr, [C_int(0), C_int(1)]);
             }
+
             auto ty_param_substs =
                 ty::node_id_to_type_params(cx.fcx.lcx.ccx.tcx, pat.id);
+            // FIXME: Remove this vec->ivec conversion.
+            auto tps_ivec = ~[];
+            for (ty::t tp in ty_param_substs) { tps_ivec += ~[tp]; }
+
             auto this_cx = cx;
             auto i = 0;
             for (@ast::pat subpat in subpats) {
                 auto rslt =
-                    GEP_tag(this_cx, llblobptr, vdef._0, vdef._1,
-                            ty_param_substs, i);
+                    GEP_tag(this_cx, llblobptr, vdef._0, vdef._1, tps_ivec,
+                            i);
                 this_cx = rslt.bcx;
                 auto subpat_res =
                     trans_pat_binding(this_cx, subpat, rslt.val, true);
@@ -8478,10 +8508,10 @@ fn trans_tag_variant(@local_ctxt cx, ast::node_id tag_id,
     create_llargs_for_fn_args(fcx, ast::proto_fn, none[ty_self_pair],
                               ty::ret_ty_of_fn(cx.ccx.tcx, variant.node.id),
                               fn_args, ty_params);
-    let vec[ty::t] ty_param_substs = [];
+    let ty::t[] ty_param_substs = ~[];
     i = 0u;
     for (ast::ty_param tp in ty_params) {
-        ty_param_substs += [ty::mk_param(cx.ccx.tcx, i)];
+        ty_param_substs += ~[ty::mk_param(cx.ccx.tcx, i)];
         i += 1u;
     }
     auto arg_tys = arg_tys_of_fn(cx.ccx, variant.node.id);
diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs
index 5ef38434e5d..5ab7aafce98 100644
--- a/src/comp/middle/ty.rs
+++ b/src/comp/middle/ty.rs
@@ -257,7 +257,7 @@ tag sty {
     ty_char;
     ty_str;
     ty_istr;
-    ty_tag(def_id, vec[t]);
+    ty_tag(def_id, t[]);
     ty_box(mt);
     ty_vec(mt);
     ty_ivec(mt);
@@ -557,7 +557,7 @@ fn mk_str(&ctxt cx) -> t { ret idx_str; }
 
 fn mk_istr(&ctxt cx) -> t { ret idx_istr; }
 
-fn mk_tag(&ctxt cx, &ast::def_id did, &vec[t] tys) -> t {
+fn mk_tag(&ctxt cx, &ast::def_id did, &t[] tys) -> t {
     ret gen_ty(cx, ty_tag(did, tys));
 }
 
@@ -753,9 +753,9 @@ fn fold_ty(&ctxt cx, fold_mode fld, t ty_0) -> t {
             ty = copy_cname(cx, mk_chan(cx, fold_ty(cx, fld, subty)), ty);
         }
         case (ty_tag(?tid, ?subtys)) {
-            let vec[t] new_subtys = [];
+            let t[] new_subtys = ~[];
             for (t subty in subtys) {
-                new_subtys += [fold_ty(cx, fld, subty)];
+                new_subtys += ~[fold_ty(cx, fld, subty)];
             }
             ty = copy_cname(cx, mk_tag(cx, tid, new_subtys), ty);
         }
@@ -1052,8 +1052,12 @@ fn type_has_pointers(&ctxt cx, &t ty) -> bool {
             }
         }
         case (ty_res(?did, ?inner, ?tps)) {
+            // FIXME: Remove this vec->ivec conversion.
+            auto tps_ivec = ~[];
+            for (ty::t tp in tps) { tps_ivec += ~[tp]; }
+
             result = type_has_pointers
-                (cx, substitute_type_params(cx, tps, inner));
+                (cx, substitute_type_params(cx, tps_ivec, inner));
         }
         case (_) { result = true; }
     }
@@ -1086,7 +1090,7 @@ fn type_has_dynamic_size(&ctxt cx, &t ty) -> bool {
         case (ty_istr) { ret false; }
         case (ty_tag(_, ?subtys)) {
             auto i = 0u;
-            while (i < vec::len[t](subtys)) {
+            while (i < ivec::len[t](subtys)) {
                 if (type_has_dynamic_size(cx, subtys.(i))) { ret true; }
                 i += 1u;
             }
@@ -1240,8 +1244,12 @@ fn type_owns_heap_mem(&ctxt cx, &t ty) -> bool {
             }
         }
         case (ty_res(_, ?inner, ?tps)) {
+            // FIXME: Remove this vec->ivec conversion.
+            auto tps_ivec = ~[];
+            for (ty::t tp in tps) { tps_ivec += ~[tp]; }
+
             result = type_owns_heap_mem
-                (cx, substitute_type_params(cx, tps, inner));
+                (cx, substitute_type_params(cx, tps_ivec, inner));
         }
 
         case (ty_ptr(_)) { result = false; }
@@ -1272,7 +1280,11 @@ fn type_autoderef(&ctxt cx, &ty::t t) -> ty::t {
         alt (struct(cx, t1)) {
             case (ty::ty_box(?mt)) { t1 = mt.ty; }
             case (ty::ty_res(_, ?inner, ?tps)) {
-                t1 = substitute_type_params(cx, tps, inner);
+                // FIXME: Remove this vec->ivec conversion.
+                auto tps_ivec = ~[];
+                for (ty::t tp in tps) { tps_ivec += ~[tp]; }
+
+                t1 = substitute_type_params(cx, tps_ivec, inner);
             }
             case (ty::ty_tag(?did, ?tps)) {
                 auto variants = tag_variants(cx, did);
@@ -1514,8 +1526,8 @@ fn equal_type_structures(&sty a, &sty b) -> bool {
             alt (b) {
                 case (ty_tag(?id_b, ?tys_b)) {
                     if (!equal_def(id_a, id_b)) { ret false; }
-                    auto len = vec::len[t](tys_a);
-                    if (len != vec::len[t](tys_b)) { ret false; }
+                    auto len = ivec::len[t](tys_a);
+                    if (len != ivec::len[t](tys_b)) { ret false; }
                     auto i = 0u;
                     while (i < len) {
                         if (!eq_ty(tys_a.(i), tys_b.(i))) { ret false; }
@@ -1755,7 +1767,13 @@ fn ty_param_substs_opt_and_ty_to_monotype(&ctxt cx,
    t {
     alt (tpot._0) {
         case (none) { ret tpot._1; }
-        case (some(?tps)) { ret substitute_type_params(cx, tps, tpot._1); }
+        case (some(?tps)) {
+            // FIXME: Remove this vec->ivec conversion.
+            auto tps_ivec = ~[];
+            for (ty::t tp in tps) { tps_ivec += ~[tp]; }
+
+            ret substitute_type_params(cx, tps_ivec, tpot._1);
+        }
     }
 }
 
@@ -2328,18 +2346,16 @@ mod unify {
                         // TODO: factor this cruft out, see the TODO in the
                         // ty::ty_tup case
 
-                        let vec[t] result_tps = [];
+                        let t[] result_tps = ~[];
                         auto i = 0u;
-                        auto expected_len = vec::len[t](expected_tps);
+                        auto expected_len = ivec::len[t](expected_tps);
                         while (i < expected_len) {
                             auto expected_tp = expected_tps.(i);
                             auto actual_tp = actual_tps.(i);
                             auto result =
                                 unify_step(cx, expected_tp, actual_tp);
                             alt (result) {
-                                case (ures_ok(?rty)) {
-                                    vec::push[t](result_tps, rty);
-                                }
+                                case (ures_ok(?rty)) { result_tps += ~[rty]; }
                                 case (_) { ret result; }
                             }
                             i += 1u;
@@ -2769,14 +2785,13 @@ fn bind_params_in_type(&span sp, &ctxt cx, fn() -> int  next_ty_var, t typ,
 
 // Replaces type parameters in the given type using the given list of
 // substitions.
-fn substitute_type_params(&ctxt cx, vec[ty::t] substs, t typ) -> t {
+fn substitute_type_params(&ctxt cx, &ty::t[] substs, t typ) -> t {
     if (!type_contains_params(cx, typ)) { ret typ; }
-    fn substituter(ctxt cx, vec[ty::t] substs, uint idx) -> t {
+    fn substituter(ctxt cx, @ty::t[] substs, uint idx) -> t {
         // FIXME: bounds check can fail
-
         ret substs.(idx);
     }
-    ret fold_ty(cx, fm_param(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 {
diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs
index aa950769863..825bdf007d8 100644
--- a/src/comp/middle/typeck.rs
+++ b/src/comp/middle/typeck.rs
@@ -265,11 +265,11 @@ fn ast_ty_to_ty(&ty::ctxt tcx, &ty_getter getter, &@ast::ty ast_ty) -> ty::t {
         // The typedef is type-parametric. Do the type substitution.
         //
 
-        let vec[ty::t] param_bindings = [];
+        let ty::t[] param_bindings = ~[];
         for (@ast::ty ast_ty in args) {
-            param_bindings += [ast_ty_to_ty(tcx, getter, ast_ty)];
+            param_bindings += ~[ast_ty_to_ty(tcx, getter, ast_ty)];
         }
-        if (vec::len(param_bindings) !=
+        if (ivec::len(param_bindings) !=
                 ty::count_ty_params(tcx, params_opt_and_ty._1)) {
             tcx.sess.span_fatal(sp,
                               "Wrong number of type arguments for a" +
@@ -647,8 +647,13 @@ mod collect {
                 // Create a new generic polytype.
 
                 auto ty_param_count = vec::len[ast::ty_param](tps);
+
                 let vec[ty::t] subtys = mk_ty_params(cx, ty_param_count);
-                auto t = ty::mk_tag(cx.tcx, local_def(it.id), subtys);
+                // FIXME: Remove this vec->ivec conversion.
+                auto tps_ivec = ~[];
+                for (ty::t tp in subtys) { tps_ivec += ~[tp]; }
+
+                auto t = ty::mk_tag(cx.tcx, local_def(it.id), tps_ivec);
                 auto tpt = tup(ty_param_count, t);
                 cx.tcx.tcache.insert(local_def(it.id), tpt);
                 ret tpt;
@@ -690,9 +695,13 @@ mod collect {
             // Nullary tag constructors get turned into constants; n-ary tag
             // constructors get turned into functions.
 
+            // FIXME: Remove this vec->ivec conversion.
+            auto tps_ivec = ~[];
+            for (ty::t tp in ty_param_tys) { tps_ivec += ~[tp]; }
+
             auto result_ty;
             if (vec::len[ast::variant_arg](variant.node.args) == 0u) {
-                result_ty = ty::mk_tag(cx.tcx, tag_id, ty_param_tys);
+                result_ty = ty::mk_tag(cx.tcx, tag_id, tps_ivec);
             } else {
                 // As above, tell ast_ty_to_ty() that trans_ty_item_to_ty()
                 // should be called to resolve named types.
@@ -703,7 +712,7 @@ mod collect {
                     auto arg_ty = ast_ty_to_ty(cx.tcx, f, va.ty);
                     args += ~[rec(mode=ty::mo_alias(false), ty=arg_ty)];
                 }
-                auto tag_t = ty::mk_tag(cx.tcx, tag_id, ty_param_tys);
+                auto tag_t = ty::mk_tag(cx.tcx, tag_id, tps_ivec);
                 // FIXME: this will be different for constrained types
                 result_ty = ty::mk_fn(cx.tcx, ast::proto_fn, args, tag_t,
                                       ast::return, []);
@@ -859,7 +868,11 @@ fn do_autoderef(&@fn_ctxt fcx, &span sp, &ty::t t) -> ty::t {
         alt (structure_of(fcx, sp, t1)) {
             case (ty::ty_box(?inner)) { t1 = inner.ty; }
             case (ty::ty_res(_, ?inner, ?tps)) {
-                t1 = ty::substitute_type_params(fcx.ccx.tcx, tps, inner);
+                // FIXME: Remove this vec->ivec conversion.
+                auto tps_ivec = ~[];
+                for (ty::t tp in tps) { tps_ivec += ~[tp]; }
+
+                t1 = ty::substitute_type_params(fcx.ccx.tcx, tps_ivec, inner);
             }
             case (ty::ty_tag(?did, ?tps)) {
                 auto variants = ty::tag_variants(fcx.ccx.tcx, did);
@@ -989,7 +1002,7 @@ fn are_compatible(&@fn_ctxt fcx, &ty::t expected, &ty::t actual) -> bool {
 
 // Returns the types of the arguments to a tag variant.
 fn variant_arg_types(&@crate_ctxt ccx, &span sp, &ast::def_id vid,
-                     &vec[ty::t] tag_ty_params) -> vec[ty::t] {
+                     &ty::t[] tag_ty_params) -> vec[ty::t] {
     let vec[ty::t] result = [];
     auto tpt = ty::lookup_item_type(ccx.tcx, vid);
     alt (ty::struct(ccx.tcx, tpt._1)) {
@@ -1278,67 +1291,60 @@ fn check_pat(&@fn_ctxt fcx, &@ast::pat pat, ty::t expected) {
             auto path_tpot = instantiate_path(fcx, path, tag_tpt, pat.span);
             // Take the tag type params out of `expected`.
 
-            auto expected_tps;
             alt (structure_of(fcx, pat.span, expected)) {
-                case (ty::ty_tag(_, ?tps)) { expected_tps = tps; }
-                case (_) {
-                    // FIXME: Switch expected and actual in this message? I
-                    // can never tell.
+              case (ty::ty_tag(_, ?expected_tps)) {
+                // Unify with the expected tag type.
+
+                auto ctor_ty =
+                    ty::ty_param_substs_opt_and_ty_to_monotype(fcx.ccx.tcx,
+                                                               path_tpot);
+
+                // FIXME: Remove this ivec->vec conversion.
+                auto tps_vec = [];
+                for (ty::t tp in expected_tps) { tps_vec += [tp]; }
+
+                auto path_tpt =
+                    demand::full(fcx, pat.span, expected, ctor_ty, tps_vec,
+                                 NO_AUTODEREF);
+                path_tpot = tup(some[vec[ty::t]](path_tpt._0), path_tpt._1);
+                // Get the number of arguments in this tag variant.
+
+                auto arg_types =
+                    variant_arg_types(fcx.ccx, pat.span, v_def_ids._1,
+                                      expected_tps);
+                auto subpats_len = vec::len[@ast::pat](subpats);
+                if (vec::len[ty::t](arg_types) > 0u) {
+                    // N-ary variant.
+
+                    auto arg_len = vec::len[ty::t](arg_types);
+                    if (arg_len != subpats_len) {
+                        // TODO: note definition of tag variant
+                        // TODO (issue #448): Wrap a #fmt string over multiple
+                        // lines...
+                        auto s = #fmt("this pattern has %u field%s, but the \
+                                       corresponding variant has %u field%s",
+                                      subpats_len,
+                                      if (subpats_len == 1u) {
+                                          ""
+                                      } else { "s" }, arg_len,
+                                      if (arg_len == 1u) {
+                                          ""
+                                      } else { "s" });
+                        fcx.ccx.tcx.sess.span_fatal(pat.span, s);
+                    }
+                    // TODO: vec::iter2
 
-                    fcx.ccx.tcx.sess.span_fatal(pat.span,
-                                              #fmt("mismatched types: \
-                                                    expected tag, found %s",
-                                                   ty_to_str(fcx.ccx.tcx,
-                                                             expected)));
-                }
-            }
-            // Unify with the expected tag type.
-
-            auto ctor_ty =
-                ty::ty_param_substs_opt_and_ty_to_monotype(fcx.ccx.tcx,
-                                                           path_tpot);
-            auto path_tpt =
-                demand::full(fcx, pat.span, expected, ctor_ty, expected_tps,
-                             NO_AUTODEREF);
-            path_tpot = tup(some[vec[ty::t]](path_tpt._0), path_tpt._1);
-            // Get the number of arguments in this tag variant.
-
-            auto arg_types =
-                variant_arg_types(fcx.ccx, pat.span, v_def_ids._1,
-                                  expected_tps);
-            auto subpats_len = vec::len[@ast::pat](subpats);
-            if (vec::len[ty::t](arg_types) > 0u) {
-                // N-ary variant.
-
-                auto arg_len = vec::len[ty::t](arg_types);
-                if (arg_len != subpats_len) {
+                    auto i = 0u;
+                    for (@ast::pat subpat in subpats) {
+                        check_pat(fcx, subpat, arg_types.(i));
+                        i += 1u;
+                    }
+                } else if (subpats_len > 0u) {
                     // TODO: note definition of tag variant
                     // TODO (issue #448): Wrap a #fmt string over multiple
                     // lines...
-                    auto s = #fmt("this pattern has %u field%s, but the \
-                                   corresponding variant has %u field%s",
-                                  subpats_len,
-                                  if (subpats_len == 1u) {
-                                      ""
-                                  } else { "s" }, arg_len,
-                                  if (arg_len == 1u) {
-                                      ""
-                                  } else { "s" });
-                    fcx.ccx.tcx.sess.span_fatal(pat.span, s);
-                }
-                // TODO: vec::iter2
-
-                auto i = 0u;
-                for (@ast::pat subpat in subpats) {
-                    check_pat(fcx, subpat, arg_types.(i));
-                    i += 1u;
-                }
-            } else if (subpats_len > 0u) {
-                // TODO: note definition of tag variant
-                // TODO (issue #448): Wrap a #fmt string over multiple
-                // lines...
 
-                fcx.ccx.tcx.sess.span_fatal(pat.span,
+                    fcx.ccx.tcx.sess.span_fatal(pat.span,
                                           #fmt("this pattern has %u field%s, \
                                                 but the corresponding \
                                                 variant has no fields",
@@ -1346,6 +1352,19 @@ fn check_pat(&@fn_ctxt fcx, &@ast::pat pat, ty::t expected) {
                                                if (subpats_len == 1u) {
                                                    ""
                                                } else { "s" }));
+                }
+                write::ty_fixup(fcx, pat.id, path_tpot);
+              }
+              case (_) {
+                // FIXME: Switch expected and actual in this message? I
+                // can never tell.
+
+                fcx.ccx.tcx.sess.span_fatal(pat.span,
+                                            #fmt("mismatched types: \
+                                                  expected tag, found %s",
+                                                 ty_to_str(fcx.ccx.tcx,
+                                                           expected)));
+              }
             }
             write::ty_fixup(fcx, pat.id, path_tpot);
         }
diff --git a/src/comp/util/ppaux.rs b/src/comp/util/ppaux.rs
index e3eb707dbf5..58ed9b6157c 100644
--- a/src/comp/util/ppaux.rs
+++ b/src/comp/util/ppaux.rs
@@ -1,4 +1,5 @@
 import std::io;
+import std::ivec;
 import std::vec;
 import std::str;
 import std::int;
@@ -118,9 +119,9 @@ fn ty_to_str(&ctxt cx, &t typ) -> str {
             // The user should never see this if the cname is set properly!
 
             s += "<tag#" + int::str(id._0) + ":" + int::str(id._1) + ">";
-            if (vec::len[t](tps) > 0u) {
-                auto f = bind ty_to_str(cx, _);
-                auto strs = vec::map[t, str](f, tps);
+            if (ivec::len[t](tps) > 0u) {
+                let vec[str] strs = [];
+                for (t typ in tps) { strs += [ty_to_str(cx, typ)]; }
                 s += "[" + str::connect(strs, ",") + "]";
             }
         }