Skip to content

Commit fc39ab3

Browse files
committed
---
yaml --- r: 2919 b: refs/heads/master c: ad9afef h: refs/heads/master i: 2917: e0e53ad 2915: 29b0743 2911: ac61320 v: v3
1 parent d32ed01 commit fc39ab3

File tree

2 files changed

+73
-157
lines changed

2 files changed

+73
-157
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
---
2-
refs/heads/master: 76bcbfd269891cf22d1f3b1a312fe15717cb7a00
2+
refs/heads/master: ad9afefa1014e01e63bf1cb48c4f1f9d98a98201

trunk/src/comp/middle/typeck.rs

Lines changed: 72 additions & 156 deletions
Original file line numberDiff line numberDiff line change
@@ -1098,97 +1098,6 @@ fn variant_arg_types(&@crate_ctxt ccx, &span sp, &ast::def_id vid,
10981098
// directly inside check_expr(). This results in a quadratic algorithm.
10991099

11001100
mod pushdown {
1101-
// Push-down over typed patterns. Note that the pattern that you pass to
1102-
// this function must have been passed to check_pat() first.
1103-
//
1104-
// TODO: enforce this via a predicate.
1105-
1106-
fn pushdown_pat(&@stmt_ctxt scx, &ty::t expected, &@ast::pat pat) {
1107-
alt (pat.node) {
1108-
case (ast::pat_wild(?ann)) {
1109-
auto t = demand::simple(scx, pat.span, expected,
1110-
ann_to_type(scx.fcx.ccx.tcx.node_types, ann));
1111-
write::ty_only_fixup(scx, ann.id, t);
1112-
}
1113-
case (ast::pat_lit(?lit, ?ann)) {
1114-
auto t = demand::simple(scx, pat.span, expected,
1115-
ann_to_type(scx.fcx.ccx.tcx.node_types, ann));
1116-
write::ty_only_fixup(scx, ann.id, t);
1117-
}
1118-
case (ast::pat_bind(?id, ?did, ?ann)) {
1119-
auto t = demand::simple(scx, pat.span, expected,
1120-
ann_to_type(scx.fcx.ccx.tcx.node_types, ann));
1121-
scx.fcx.locals.insert(did, t);
1122-
write::ty_only_fixup(scx, ann.id, t);
1123-
}
1124-
case (ast::pat_tag(?id, ?subpats, ?ann)) {
1125-
// Take the variant's type parameters out of the expected
1126-
// type.
1127-
auto tag_tps;
1128-
alt (struct(scx.fcx.ccx.tcx, expected)) {
1129-
case (ty::ty_tag(_, ?tps)) { tag_tps = tps; }
1130-
case (_) {
1131-
scx.fcx.ccx.tcx.sess.span_err(pat.span,
1132-
"Non-constructor used in a pattern");
1133-
}
1134-
}
1135-
1136-
// Get the types of the arguments of the variant.
1137-
1138-
let vec[ty::t] tparams = [];
1139-
auto j = 0u;
1140-
auto actual_ty_params =
1141-
ty::ann_to_type_params(scx.fcx.ccx.tcx.node_types, ann);
1142-
1143-
for (ty::t some_ty in tag_tps) {
1144-
let ty::t t1 = some_ty;
1145-
let ty::t t2 = actual_ty_params.(j);
1146-
1147-
let ty::t res = demand::simple(scx, pat.span, t1, t2);
1148-
1149-
vec::push(tparams, res);
1150-
j += 1u;
1151-
}
1152-
1153-
auto arg_tys;
1154-
alt (scx.fcx.ccx.tcx.def_map.get(ann.id)) {
1155-
case (ast::def_variant(_, ?vdefid)) {
1156-
arg_tys = variant_arg_types(scx.fcx.ccx, pat.span,
1157-
vdefid, tparams);
1158-
}
1159-
}
1160-
1161-
auto i = 0u;
1162-
for (@ast::pat subpat in subpats) {
1163-
pushdown_pat(scx, arg_tys.(i), subpat);
1164-
i += 1u;
1165-
}
1166-
1167-
auto tps =
1168-
ty::ann_to_type_params(scx.fcx.ccx.tcx.node_types, ann);
1169-
auto tt = ann_to_type(scx.fcx.ccx.tcx.node_types, ann);
1170-
1171-
let ty_param_substs_and_ty res_t = demand::full(scx, pat.span,
1172-
expected, tt, tps, NO_AUTODEREF);
1173-
1174-
auto ty_params_subst = ty::ann_to_ty_param_substs_opt_and_ty
1175-
(scx.fcx.ccx.tcx.node_types, ann);
1176-
1177-
auto ty_params_opt;
1178-
alt (ty_params_subst._0) {
1179-
case (none) {
1180-
ty_params_opt = none[vec[ty::t]];
1181-
}
1182-
case (some(?tps)) {
1183-
ty_params_opt = some[vec[ty::t]](tag_tps);
1184-
}
1185-
}
1186-
1187-
write::ty_fixup(scx, ann.id, tup(ty_params_opt, tt));
1188-
}
1189-
}
1190-
}
1191-
11921101
// Push-down over typed expressions. Note that the expression that you
11931102
// pass to this function must have been passed to check_expr() first.
11941103
//
@@ -1673,75 +1582,88 @@ fn check_lit(@crate_ctxt ccx, &@ast::lit lit) -> ty::t {
16731582
fail; // not reached
16741583
}
16751584

1676-
fn check_pat(&@stmt_ctxt scx, &@ast::pat pat) {
1585+
// Pattern checking is top-down rather than bottom-up so that bindings get
1586+
// their types immediately.
1587+
fn check_pat(&@stmt_ctxt scx, &@ast::pat pat, ty::t expected) {
16771588
alt (pat.node) {
16781589
case (ast::pat_wild(?ann)) {
1679-
auto typ = next_ty_var(scx);
1680-
write::ty_only_fixup(scx, ann.id, typ);
1590+
write::ty_only_fixup(scx, ann.id, expected);
16811591
}
16821592
case (ast::pat_lit(?lt, ?ann)) {
16831593
auto typ = check_lit(scx.fcx.ccx, lt);
1594+
typ = demand::simple(scx, pat.span, expected, typ);
16841595
write::ty_only_fixup(scx, ann.id, typ);
16851596
}
1686-
case (ast::pat_bind(?id, ?def_id, ?a)) {
1687-
auto typ = next_ty_var(scx);
1688-
write::ty_only_fixup(scx, a.id, typ);
1597+
case (ast::pat_bind(?id, ?def_id, ?ann)) {
1598+
scx.fcx.locals.insert(def_id, expected);
1599+
write::ty_only_fixup(scx, ann.id, expected);
16891600
}
1690-
case (ast::pat_tag(?p, ?subpats, ?old_ann)) {
1691-
auto vdef = ast::variant_def_ids
1692-
(scx.fcx.ccx.tcx.def_map.get(old_ann.id));
1693-
auto t = ty::lookup_item_type(scx.fcx.ccx.tcx,
1694-
vdef._1)._1;
1695-
auto len = vec::len[ast::ident](p.node.idents);
1696-
auto last_id = p.node.idents.(len - 1u);
1697-
1698-
auto tpt = ty::lookup_item_type(scx.fcx.ccx.tcx,
1699-
vdef._0);
1700-
1701-
auto path_tpot = instantiate_path(scx, p, tpt, pat.span);
1702-
1703-
alt (struct(scx.fcx.ccx.tcx, t)) {
1704-
// N-ary variants have function types.
1705-
case (ty::ty_fn(_, ?args, ?tag_ty, _)) {
1706-
auto arg_len = vec::len[arg](args);
1707-
auto subpats_len = vec::len[@ast::pat](subpats);
1708-
if (arg_len != subpats_len) {
1709-
// TODO: pluralize properly
1710-
auto err_msg = "tag type " + last_id + " has " +
1711-
uint::to_str(arg_len, 10u) +
1712-
" field(s), but this pattern has " +
1713-
uint::to_str(subpats_len, 10u) +
1714-
" field(s)";
1715-
1716-
scx.fcx.ccx.tcx.sess.span_err(pat.span, err_msg);
1717-
fail; // TODO: recover
1718-
}
1719-
1720-
for (@ast::pat subpat in subpats) {
1721-
check_pat(scx, subpat);
1722-
}
1601+
case (ast::pat_tag(?path, ?subpats, ?ann)) {
1602+
// Typecheck the path.
1603+
auto v_def = scx.fcx.ccx.tcx.def_map.get(ann.id);
1604+
auto v_def_ids = ast::variant_def_ids(v_def);
17231605

1724-
write::ty_fixup(scx, old_ann.id, path_tpot);
1725-
}
1726-
1727-
// Nullary variants have tag types.
1728-
case (ty::ty_tag(?tid, _)) {
1729-
auto subpats_len = vec::len[@ast::pat](subpats);
1730-
if (subpats_len > 0u) {
1731-
// TODO: pluralize properly
1732-
auto err_msg = "tag type " + last_id +
1733-
" has no field(s)," +
1734-
" but this pattern has " +
1735-
uint::to_str(subpats_len, 10u) +
1736-
" field(s)";
1737-
1738-
scx.fcx.ccx.tcx.sess.span_err(pat.span, err_msg);
1739-
fail; // TODO: recover
1740-
}
1606+
auto tag_tpt = ty::lookup_item_type(scx.fcx.ccx.tcx,
1607+
v_def_ids._0);
1608+
auto path_tpot = instantiate_path(scx, path, tag_tpt, pat.span);
17411609

1742-
write::ty_fixup(scx, old_ann.id, path_tpot);
1610+
// Take the tag type params out of `expected`.
1611+
auto expected_tps;
1612+
alt (struct(scx.fcx.ccx.tcx, expected)) {
1613+
case (ty::ty_tag(_, ?tps)) { expected_tps = tps; }
1614+
case (_) {
1615+
// FIXME: Switch expected and actual in this message? I
1616+
// can never tell.
1617+
scx.fcx.ccx.tcx.sess.span_err(pat.span,
1618+
#fmt("mismatched types: expected tag but found %s",
1619+
ty::ty_to_str(scx.fcx.ccx.tcx, expected)));
1620+
}
1621+
}
1622+
1623+
// Unify with the expected tag type.
1624+
auto path_tpt = demand::full(scx, pat.span, expected,
1625+
path_tpot._1, expected_tps,
1626+
NO_AUTODEREF);
1627+
path_tpot = tup(some[vec[ty::t]](path_tpt._0), path_tpt._1);
1628+
1629+
// Get the number of arguments in this tag variant.
1630+
auto arg_types = variant_arg_types(scx.fcx.ccx, pat.span,
1631+
v_def_ids._1, expected_tps);
1632+
1633+
auto subpats_len = vec::len[@ast::pat](subpats);
1634+
1635+
if (vec::len[ty::t](arg_types) > 0u) {
1636+
// N-ary variant.
1637+
auto arg_len = vec::len[ty::t](arg_types);
1638+
if (arg_len != subpats_len) {
1639+
// TODO: note definition of tag variant
1640+
// TODO (issue #448): Wrap a #fmt string over multiple
1641+
// lines...
1642+
scx.fcx.ccx.tcx.sess.span_err(pat.span, #fmt(
1643+
"this pattern has %u field%s, but the corresponding variant has %u field%s",
1644+
subpats_len,
1645+
if (subpats_len == 0u) { "" } else { "s" },
1646+
arg_len,
1647+
if (arg_len == 0u) { "" } else { "s" }));
1648+
}
1649+
1650+
// TODO: vec::iter2
1651+
auto i = 0u;
1652+
for (@ast::pat subpat in subpats) {
1653+
check_pat(scx, subpat, arg_types.(i));
1654+
i += 1u;
17431655
}
1656+
} else if (subpats_len > 0u) {
1657+
// TODO: note definition of tag variant
1658+
// TODO (issue #448): Wrap a #fmt string over multiple
1659+
// lines...
1660+
scx.fcx.ccx.tcx.sess.span_err(pat.span, #fmt(
1661+
"this pattern has %u field%s, but the corresponding variant has no fields",
1662+
subpats_len,
1663+
if (subpats_len == 0u) { "" } else { "s" }));
17441664
}
1665+
1666+
write::ty_fixup(scx, ann.id, path_tpot);
17451667
}
17461668
}
17471669
}
@@ -2247,20 +2169,14 @@ fn check_expr(&@stmt_ctxt scx, &@ast::expr expr) {
22472169

22482170
// Typecheck the patterns first, so that we get types for all the
22492171
// bindings.
2250-
auto pattern_ty = expr_ty(scx.fcx.ccx.tcx, expr);
2172+
auto pattern_ty = ty::expr_ty(scx.fcx.ccx.tcx, expr);
22512173

22522174
let vec[@ast::pat] pats = [];
22532175
for (ast::arm arm in arms) {
2254-
check_pat(scx, arm.pat);
2255-
pattern_ty = demand::simple(scx, arm.pat.span, pattern_ty,
2256-
pat_ty(scx.fcx.ccx.tcx, arm.pat));
2176+
check_pat(scx, arm.pat, pattern_ty);
22572177
pats += [arm.pat];
22582178
}
22592179

2260-
for (@ast::pat pat in pats) {
2261-
pushdown::pushdown_pat(scx, pattern_ty, pat);
2262-
}
2263-
22642180
// Now typecheck the blocks.
22652181
auto result_ty = next_ty_var(scx);
22662182

0 commit comments

Comments
 (0)