rustc: Use interior vectors for tag type parameters

This commit is contained in:
Patrick Walton 2011-07-01 12:46:14 -07:00
parent 111989a626
commit ede35f4c43
5 changed files with 185 additions and 120 deletions

View File

@ -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);
}

View File

@ -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);
@ -8470,10 +8500,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);

View File

@ -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 {

View File

@ -267,11 +267,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" +
@ -649,8 +649,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;
@ -692,9 +697,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.
@ -705,7 +714,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, []);
@ -861,7 +870,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);
@ -991,7 +1004,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)) {
@ -1310,67 +1323,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.
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 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.
// FIXME: Remove this ivec->vec conversion.
auto tps_vec = [];
for (ty::t tp in expected_tps) { tps_vec += [tp]; }
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 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_len = vec::len[ty::t](arg_types);
if (arg_len != subpats_len) {
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
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",
@ -1378,6 +1384,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);
}

View File

@ -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, ",") + "]";
}
}