Add new syntax for patterns that match the head constructor only
Adds a new kind of pattern C(*) where C is a constructor that may have any number of fields. This pattern matches any value constructed with C, without binding names for any of the fields. Closes #1701.
This commit is contained in:
@@ -600,11 +600,11 @@ fn pattern_roots(tcx: ty::ctxt, mutbl: option<unsafe_ty>, pat: @ast::pat)
|
||||
if !pat_util::pat_is_variant(tcx.def_map, pat) {
|
||||
set += [{id: pat.id, name: path_to_ident(nm), mutbl: mutbl,
|
||||
span: pat.span}];
|
||||
alt sub { some(p) { walk(tcx, mutbl, p, set); } _ {} }
|
||||
option::iter(sub) {|p| walk(tcx, mutbl, p, set); };
|
||||
}
|
||||
ast::pat_wild | ast::pat_lit(_) | ast::pat_range(_, _) |
|
||||
ast::pat_ident(_, _) {}
|
||||
ast::pat_enum(_, ps) | ast::pat_tup(ps) {
|
||||
ast::pat_ident(_, _) | ast::pat_enum(_, none) {}
|
||||
ast::pat_enum(_, some(ps)) | ast::pat_tup(ps) {
|
||||
for ps.each {|p| walk(tcx, mutbl, p, set); }
|
||||
}
|
||||
ast::pat_rec(fs, _) {
|
||||
|
||||
@@ -3,6 +3,7 @@ import syntax::ast::*;
|
||||
import syntax::ast_util::{variant_def_ids, dummy_sp, unguarded_pat};
|
||||
import middle::const_eval::{compare_lit_exprs, lit_expr_eq};
|
||||
import syntax::codemap::span;
|
||||
import syntax::print::pprust::pat_to_str;
|
||||
import pat_util::*;
|
||||
import syntax::visit;
|
||||
import driver::session::session;
|
||||
@@ -166,13 +167,22 @@ fn check_exhaustive_enum(tcx: ty::ctxt, enum_id: def_id, sp: span,
|
||||
def_variant(_, id) {
|
||||
let variant_idx =
|
||||
option::get(vec::position(*variants, {|v| v.id == id}));
|
||||
let arg_len = variants[variant_idx].args.len();
|
||||
columns_by_variant[variant_idx].seen = true;
|
||||
alt pat.node {
|
||||
pat_enum(_, args) {
|
||||
pat_enum(_, some(args)) {
|
||||
vec::iteri(args) {|i, p|
|
||||
columns_by_variant[variant_idx].cols[i] += [p];
|
||||
}
|
||||
}
|
||||
pat_enum(_, none) {
|
||||
/* (*) pattern -- we fill in n '_' patterns, if the variant
|
||||
has n args */
|
||||
let wild_pat = @{id: tcx.sess.next_node_id(),
|
||||
node: pat_wild, span: pat.span};
|
||||
uint::range(0u, arg_len) {|i|
|
||||
columns_by_variant[variant_idx].cols[i] += [wild_pat]};
|
||||
}
|
||||
_ {}
|
||||
}
|
||||
}
|
||||
@@ -225,9 +235,12 @@ fn pattern_supersedes(tcx: ty::ctxt, a: @pat, b: @pat) -> bool {
|
||||
}
|
||||
pat_enum(va, suba) {
|
||||
alt b.node {
|
||||
pat_enum(vb, subb) {
|
||||
pat_enum(vb, some(subb)) {
|
||||
tcx.def_map.get(a.id) == tcx.def_map.get(b.id) &&
|
||||
patterns_supersede(tcx, suba, subb)
|
||||
alt suba { none { true }
|
||||
some(subaa) {
|
||||
patterns_supersede(tcx, subaa, subb)
|
||||
}}
|
||||
}
|
||||
_ { false }
|
||||
}
|
||||
@@ -310,10 +323,11 @@ fn is_refutable(tcx: ty::ctxt, pat: @pat) -> bool {
|
||||
for elts.each {|elt| if is_refutable(tcx, elt) { ret true; } }
|
||||
false
|
||||
}
|
||||
pat_enum(_, args) {
|
||||
for args.each {|p| if is_refutable(tcx, p) { ret true; } }
|
||||
pat_enum(_, some(args)) {
|
||||
for args.each {|p| if is_refutable(tcx, p) { ret true; } };
|
||||
false
|
||||
}
|
||||
pat_enum(_,_) { false }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -56,9 +56,10 @@ fn walk_pat(pat: @pat, it: fn(@pat)) {
|
||||
alt pat.node {
|
||||
pat_ident(pth, some(p)) { walk_pat(p, it); }
|
||||
pat_rec(fields, _) { for fields.each {|f| walk_pat(f.pat, it); } }
|
||||
pat_enum(_, s) | pat_tup(s) { for s.each {|p| walk_pat(p, it); } }
|
||||
pat_enum(_, some(s)) | pat_tup(s) { for s.each {|p| walk_pat(p, it); } }
|
||||
pat_box(s) | pat_uniq(s) { walk_pat(s, it); }
|
||||
pat_wild | pat_lit(_) | pat_range(_, _) | pat_ident(_, none) {}
|
||||
pat_wild | pat_lit(_) | pat_range(_, _) | pat_ident(_, _)
|
||||
| pat_enum(_, _) {}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -163,7 +163,8 @@ fn enter_opt(tcx: ty::ctxt, m: match, opt: opt, col: uint,
|
||||
enter_match(tcx.def_map, m, col, val) {|p|
|
||||
alt p.node {
|
||||
ast::pat_enum(_, subpats) {
|
||||
if opt_eq(tcx, variant_opt(tcx, p.id), opt) { some(subpats) }
|
||||
if opt_eq(tcx, variant_opt(tcx, p.id), opt) {
|
||||
some(option::get_or_default(subpats, [])) }
|
||||
else { none }
|
||||
}
|
||||
ast::pat_ident(_, none) if pat_is_variant(tcx.def_map, p) {
|
||||
@@ -700,16 +701,15 @@ fn bind_irrefutable_pat(bcx: block, pat: @ast::pat, val: ValueRef,
|
||||
let vdefs = ast_util::variant_def_ids(ccx.tcx.def_map.get(pat.id));
|
||||
let args = extract_variant_args(bcx, pat.id, vdefs, val);
|
||||
let mut i = 0;
|
||||
for vec::each(args.vals) {|argval|
|
||||
option::iter(sub) {|sub| for vec::each(args.vals) {|argval|
|
||||
bcx = bind_irrefutable_pat(bcx, sub[i], argval, make_copy);
|
||||
i += 1;
|
||||
}
|
||||
}}
|
||||
}
|
||||
ast::pat_rec(fields, _) {
|
||||
let rec_fields = ty::get_fields(node_id_type(bcx, pat.id));
|
||||
for vec::each(fields) {|f|
|
||||
let ix = option::get(ty::field_idx(f.ident, rec_fields));
|
||||
// how to get rid of this check?
|
||||
let fldptr = GEPi(bcx, val, [0, ix as int]);
|
||||
bcx = bind_irrefutable_pat(bcx, f.pat, fldptr, make_copy);
|
||||
}
|
||||
|
||||
@@ -2046,7 +2046,7 @@ fn universally_quantify_before_call(fcx: @fn_ctxt,
|
||||
}
|
||||
|
||||
fn check_pat_variant(pcx: pat_ctxt, pat: @ast::pat, path: @ast::path,
|
||||
subpats: [@ast::pat], expected: ty::t) {
|
||||
subpats: option<[@ast::pat]>, expected: ty::t) {
|
||||
|
||||
// Typecheck the path.
|
||||
let fcx = pcx.fcx;
|
||||
@@ -2075,8 +2075,9 @@ fn check_pat_variant(pcx: pat_ctxt, pat: @ast::pat, path: @ast::path,
|
||||
tcx, v_def_ids.enm, v_def_ids.var);
|
||||
vinfo.args.map { |t| ty::subst(tcx, expected_substs, t) }
|
||||
};
|
||||
|
||||
let subpats_len = subpats.len(), arg_len = arg_types.len();
|
||||
let arg_len = arg_types.len(), subpats_len = alt subpats {
|
||||
none { arg_len }
|
||||
some(ps) { ps.len() }};
|
||||
if arg_len > 0u {
|
||||
// N-ary variant.
|
||||
if arg_len != subpats_len {
|
||||
@@ -2089,9 +2090,11 @@ fn check_pat_variant(pcx: pat_ctxt, pat: @ast::pat, path: @ast::path,
|
||||
tcx.sess.span_fatal(pat.span, s);
|
||||
}
|
||||
|
||||
vec::iter2(subpats, arg_types) {|subpat, arg_ty|
|
||||
check_pat(pcx, subpat, arg_ty);
|
||||
}
|
||||
option::iter(subpats) {|pats|
|
||||
vec::iter2(pats, arg_types) {|subpat, arg_ty|
|
||||
check_pat(pcx, subpat, arg_ty);
|
||||
}
|
||||
};
|
||||
} else if subpats_len > 0u {
|
||||
tcx.sess.span_fatal
|
||||
(pat.span, #fmt["this pattern has %u field%s, \
|
||||
@@ -2159,8 +2162,8 @@ fn check_pat(pcx: pat_ctxt, pat: @ast::pat, expected: ty::t) {
|
||||
_ {}
|
||||
}
|
||||
}
|
||||
ast::pat_ident(path, _) {
|
||||
check_pat_variant(pcx, pat, path, [], expected);
|
||||
ast::pat_ident(path, c) {
|
||||
check_pat_variant(pcx, pat, path, some([]), expected);
|
||||
}
|
||||
ast::pat_enum(path, subpats) {
|
||||
check_pat_variant(pcx, pat, path, subpats, expected);
|
||||
@@ -3885,7 +3888,7 @@ fn check_enum_variants(ccx: @crate_ctxt,
|
||||
}) {
|
||||
ccx.tcx.sess.span_err(sp, "illegal recursive enum type. \
|
||||
wrap the inner value in a box to \
|
||||
make it represenable");
|
||||
make it representable");
|
||||
}
|
||||
|
||||
// Check that it is possible to instantiate this enum:
|
||||
|
||||
Reference in New Issue
Block a user