Allow binding of nested patterns
See src/test/run-pass/nested-patterns.rs for some examples. The syntax is boundvar@subpattern Which will match the subpattern as usual, but also bind boundvar to the whole matched value. Closes #838
This commit is contained in:
parent
8c966b7b18
commit
9a269a3aa8
17 changed files with 132 additions and 79 deletions
|
@ -585,8 +585,9 @@ fn pattern_roots(tcx: ty::ctxt, mut: option::t<unsafe_ty>, pat: @ast::pat)
|
|||
&set: [pattern_root]) {
|
||||
alt pat.node {
|
||||
ast::pat_wild. | ast::pat_lit(_) | ast::pat_range(_, _) {}
|
||||
ast::pat_bind(nm) {
|
||||
ast::pat_bind(nm, sub) {
|
||||
set += [{id: pat.id, name: nm, mut: mut, span: pat.span}];
|
||||
alt sub { some(p) { walk(tcx, mut, p, set); } _ {} }
|
||||
}
|
||||
ast::pat_tag(_, ps) | ast::pat_tup(ps) {
|
||||
for p in ps { walk(tcx, mut, p, set); }
|
||||
|
|
|
@ -2,6 +2,7 @@ import syntax::ast::*;
|
|||
import syntax::ast_util::{variant_def_ids, dummy_sp, compare_lit_exprs,
|
||||
lit_expr_eq};
|
||||
import syntax::visit;
|
||||
import std::option::{some, none};
|
||||
|
||||
fn check_crate(tcx: ty::ctxt, crate: @crate) {
|
||||
let v =
|
||||
|
@ -64,57 +65,58 @@ fn pattern_supersedes(tcx: ty::ctxt, a: @pat, b: @pat) -> bool {
|
|||
}
|
||||
|
||||
alt a.node {
|
||||
pat_wild. | pat_bind(_) { ret true; }
|
||||
pat_bind(_, some(p)) { pattern_supersedes(tcx, p, b) }
|
||||
pat_wild. | pat_bind(_, none.) { true }
|
||||
pat_lit(la) {
|
||||
alt b.node {
|
||||
pat_lit(lb) { ret lit_expr_eq(la, lb); }
|
||||
_ { ret false; }
|
||||
pat_lit(lb) { lit_expr_eq(la, lb) }
|
||||
_ { false }
|
||||
}
|
||||
}
|
||||
pat_tag(va, suba) {
|
||||
alt b.node {
|
||||
pat_tag(vb, subb) {
|
||||
ret tcx.def_map.get(a.id) == tcx.def_map.get(b.id) &&
|
||||
patterns_supersede(tcx, suba, subb);
|
||||
tcx.def_map.get(a.id) == tcx.def_map.get(b.id) &&
|
||||
patterns_supersede(tcx, suba, subb)
|
||||
}
|
||||
_ { ret false; }
|
||||
_ { false }
|
||||
}
|
||||
}
|
||||
pat_rec(suba, _) {
|
||||
alt b.node {
|
||||
pat_rec(subb, _) { ret field_patterns_supersede(tcx, suba, subb); }
|
||||
_ { ret false; }
|
||||
pat_rec(subb, _) { field_patterns_supersede(tcx, suba, subb) }
|
||||
_ { false }
|
||||
}
|
||||
}
|
||||
pat_tup(suba) {
|
||||
alt b.node {
|
||||
pat_tup(subb) { ret patterns_supersede(tcx, suba, subb); }
|
||||
_ { ret false; }
|
||||
pat_tup(subb) { patterns_supersede(tcx, suba, subb) }
|
||||
_ { false }
|
||||
}
|
||||
}
|
||||
pat_box(suba) {
|
||||
alt b.node {
|
||||
pat_box(subb) { ret pattern_supersedes(tcx, suba, subb); }
|
||||
_ { ret pattern_supersedes(tcx, suba, b); }
|
||||
pat_box(subb) { pattern_supersedes(tcx, suba, subb) }
|
||||
_ { pattern_supersedes(tcx, suba, b) }
|
||||
}
|
||||
}
|
||||
pat_uniq(suba) {
|
||||
alt b.node {
|
||||
pat_uniq(subb) { ret pattern_supersedes(tcx, suba, subb); }
|
||||
_ { ret pattern_supersedes(tcx, suba, b); }
|
||||
pat_uniq(subb) { pattern_supersedes(tcx, suba, subb) }
|
||||
_ { pattern_supersedes(tcx, suba, b) }
|
||||
}
|
||||
}
|
||||
pat_range(begina, enda) {
|
||||
alt b.node {
|
||||
pat_lit(lb) {
|
||||
ret compare_lit_exprs(begina, lb) <= 0 &&
|
||||
compare_lit_exprs(enda, lb) >= 0;
|
||||
compare_lit_exprs(begina, lb) <= 0 &&
|
||||
compare_lit_exprs(enda, lb) >= 0
|
||||
}
|
||||
pat_range(beginb, endb) {
|
||||
ret compare_lit_exprs(begina, beginb) <= 0 &&
|
||||
compare_lit_exprs(enda, endb) >= 0;
|
||||
compare_lit_exprs(begina, beginb) <= 0 &&
|
||||
compare_lit_exprs(enda, endb) >= 0
|
||||
}
|
||||
_ { ret false; }
|
||||
_ { false }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -130,25 +132,26 @@ fn check_local(tcx: ty::ctxt, loc: @local, &&s: (), v: visit::vt<()>) {
|
|||
|
||||
fn is_refutable(tcx: ty::ctxt, pat: @pat) -> bool {
|
||||
alt pat.node {
|
||||
pat_wild. | pat_bind(_) { ret false; }
|
||||
pat_lit(_) { ret true; }
|
||||
pat_box(sub) { ret is_refutable(tcx, sub); }
|
||||
pat_uniq(sub) { ret is_refutable(tcx, sub); }
|
||||
pat_box(sub) | pat_uniq(sub) | pat_bind(_, some(sub)) {
|
||||
is_refutable(tcx, sub)
|
||||
}
|
||||
pat_wild. | pat_bind(_, none.) { false }
|
||||
pat_lit(_) { true }
|
||||
pat_rec(fields, _) {
|
||||
for field: field_pat in fields {
|
||||
if is_refutable(tcx, field.pat) { ret true; }
|
||||
}
|
||||
ret false;
|
||||
false
|
||||
}
|
||||
pat_tup(elts) {
|
||||
for elt in elts { if is_refutable(tcx, elt) { ret true; } }
|
||||
ret false;
|
||||
false
|
||||
}
|
||||
pat_tag(_, args) {
|
||||
let vdef = variant_def_ids(tcx.def_map.get(pat.id));
|
||||
if std::vec::len(ty::tag_variants(tcx, vdef.tg)) != 1u { ret true; }
|
||||
for p: @pat in args { if is_refutable(tcx, p) { ret true; } }
|
||||
ret false;
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -819,7 +819,7 @@ fn lookup_in_ty_params(name: ident, ty_params: [ast::ty_param]) ->
|
|||
fn lookup_in_pat(name: ident, pat: @ast::pat) -> option::t<def_id> {
|
||||
let found = none;
|
||||
ast_util::pat_bindings(pat) {|bound|
|
||||
let p_name = alt bound.node { ast::pat_bind(n) { n } };
|
||||
let p_name = alt bound.node { ast::pat_bind(n, _) { n } };
|
||||
if str::eq(p_name, name) { found = some(local_def(bound.id)); }
|
||||
};
|
||||
ret found;
|
||||
|
@ -1376,7 +1376,7 @@ fn check_item(e: @env, i: @ast::item, &&x: (), v: vt<()>) {
|
|||
|
||||
fn check_pat(ch: checker, p: @ast::pat) {
|
||||
ast_util::pat_bindings(p) {|p|
|
||||
let ident = alt p.node { pat_bind(n) { n } };
|
||||
let ident = alt p.node { pat_bind(n, _) { n } };
|
||||
add_name(ch, p.span, ident);
|
||||
};
|
||||
}
|
||||
|
@ -1424,7 +1424,7 @@ fn check_block(e: @env, b: ast::blk, &&x: (), v: vt<()>) {
|
|||
let local_values = checker(*e, "value");
|
||||
for (_, loc) in locs {
|
||||
ast_util::pat_bindings(loc.node.pat) {|p|
|
||||
let ident = alt p.node { pat_bind(n) { n } };
|
||||
let ident = alt p.node { pat_bind(n, _) { n } };
|
||||
add_name(local_values, p.span, ident);
|
||||
check_name(values, p.span, ident);
|
||||
};
|
||||
|
|
|
@ -4702,7 +4702,7 @@ fn alloc_ty(cx: @block_ctxt, t: ty::t) -> result {
|
|||
fn alloc_local(cx: @block_ctxt, local: @ast::local) -> @block_ctxt {
|
||||
let t = node_id_type(bcx_ccx(cx), local.node.id);
|
||||
let is_simple = alt local.node.pat.node {
|
||||
ast::pat_bind(_) { true } _ { false }
|
||||
ast::pat_bind(_, none.) { true } _ { false }
|
||||
};
|
||||
// Do not allocate space for locals that can be kept immediate.
|
||||
let ccx = bcx_ccx(cx);
|
||||
|
@ -4716,7 +4716,7 @@ fn alloc_local(cx: @block_ctxt, local: @ast::local) -> @block_ctxt {
|
|||
}
|
||||
let r = alloc_ty(cx, t);
|
||||
alt local.node.pat.node {
|
||||
ast::pat_bind(ident) {
|
||||
ast::pat_bind(ident, none.) {
|
||||
if bcx_ccx(cx).sess.get_opts().debuginfo {
|
||||
let _: () = str::as_buf(ident, {|buf|
|
||||
llvm::LLVMSetValueName(r.val, buf)
|
||||
|
|
|
@ -88,14 +88,31 @@ type match_branch =
|
|||
id_map: ast_util::pat_id_map}};
|
||||
type match = [match_branch];
|
||||
|
||||
fn matches_always(p: @ast::pat) -> bool {
|
||||
ret alt p.node {
|
||||
ast::pat_wild. { true }
|
||||
ast::pat_bind(_) { true }
|
||||
ast::pat_rec(_, _) { true }
|
||||
ast::pat_tup(_) { true }
|
||||
_ { false }
|
||||
};
|
||||
fn has_nested_bindings(m: match, col: uint) -> bool {
|
||||
for br in m {
|
||||
alt br.pats[col].node {
|
||||
ast::pat_bind(_, some(_)) { ret true; }
|
||||
_ {}
|
||||
}
|
||||
}
|
||||
ret false;
|
||||
}
|
||||
|
||||
fn expand_nested_bindings(m: match, col: uint, val: ValueRef) -> match {
|
||||
let result = [];
|
||||
for br in m {
|
||||
alt br.pats[col].node {
|
||||
ast::pat_bind(name, some(inner)) {
|
||||
let pats = vec::slice(br.pats, 0u, col) + [inner] +
|
||||
vec::slice(br.pats, col + 1u, vec::len(br.pats));
|
||||
result += [@{pats: pats,
|
||||
bound: br.bound + [{ident: name, val: val}]
|
||||
with *br}];
|
||||
}
|
||||
_ { result += [br]; }
|
||||
}
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
type enter_pat = fn@(@ast::pat) -> option::t<[@ast::pat]>;
|
||||
|
@ -109,7 +126,7 @@ fn enter_match(m: match, col: uint, val: ValueRef, e: enter_pat) -> match {
|
|||
vec::slice(br.pats, col + 1u, vec::len(br.pats));
|
||||
let new_br = @{pats: pats,
|
||||
bound: alt br.pats[col].node {
|
||||
ast::pat_bind(name) {
|
||||
ast::pat_bind(name, none.) {
|
||||
br.bound + [{ident: name, val: val}]
|
||||
}
|
||||
_ { br.bound }
|
||||
|
@ -123,6 +140,13 @@ fn enter_match(m: match, col: uint, val: ValueRef, e: enter_pat) -> match {
|
|||
}
|
||||
|
||||
fn enter_default(m: match, col: uint, val: ValueRef) -> match {
|
||||
fn matches_always(p: @ast::pat) -> bool {
|
||||
ret alt p.node {
|
||||
ast::pat_wild. | ast::pat_bind(_, none.) | ast::pat_rec(_, _) |
|
||||
ast::pat_tup(_) { true }
|
||||
_ { false }
|
||||
};
|
||||
}
|
||||
fn e(p: @ast::pat) -> option::t<[@ast::pat]> {
|
||||
ret if matches_always(p) { some([]) } else { none };
|
||||
}
|
||||
|
@ -303,18 +327,17 @@ type exit_node = {bound: bind_map, from: BasicBlockRef, to: BasicBlockRef};
|
|||
type mk_fail = fn@() -> BasicBlockRef;
|
||||
|
||||
fn pick_col(m: match) -> uint {
|
||||
fn score(p: @ast::pat) -> uint {
|
||||
alt p.node {
|
||||
ast::pat_lit(_) | ast::pat_tag(_, _) | ast::pat_range(_, _) { 1u }
|
||||
ast::pat_bind(_, some(p)) { score(p) }
|
||||
_ { 0u }
|
||||
}
|
||||
}
|
||||
let scores = vec::init_elt_mut(0u, vec::len(m[0].pats));
|
||||
for br: match_branch in m {
|
||||
let i = 0u;
|
||||
for p: @ast::pat in br.pats {
|
||||
alt p.node {
|
||||
ast::pat_lit(_) | ast::pat_tag(_, _) | ast::pat_range(_, _) {
|
||||
scores[i] += 1u;
|
||||
}
|
||||
_ { }
|
||||
}
|
||||
i += 1u;
|
||||
}
|
||||
for p: @ast::pat in br.pats { scores[i] += score(p); i += 1u; }
|
||||
}
|
||||
let max_score = 0u;
|
||||
let best_col = 0u;
|
||||
|
@ -368,6 +391,9 @@ fn compile_submatch(bcx: @block_ctxt, m: match, vals: [ValueRef], f: mk_fail,
|
|||
|
||||
let col = pick_col(m);
|
||||
let val = vals[col];
|
||||
let m = has_nested_bindings(m, col) ?
|
||||
expand_nested_bindings(m, col, val) : m;
|
||||
|
||||
let vals_left =
|
||||
vec::slice(vals, 0u, col) +
|
||||
vec::slice(vals, col + 1u, vec::len(vals));
|
||||
|
@ -662,7 +688,7 @@ fn bind_irrefutable_pat(bcx: @block_ctxt, pat: @ast::pat, val: ValueRef,
|
|||
make_copy: bool) -> @block_ctxt {
|
||||
let ccx = bcx.fcx.lcx.ccx, bcx = bcx;
|
||||
alt pat.node {
|
||||
ast::pat_bind(_) {
|
||||
ast::pat_bind(_, inner) {
|
||||
if make_copy || ccx.copy_map.contains_key(pat.id) {
|
||||
let ty = ty::node_id_to_monotype(ccx.tcx, pat.id);
|
||||
// FIXME: Could constrain pat_bind to make this
|
||||
|
@ -676,6 +702,10 @@ fn bind_irrefutable_pat(bcx: @block_ctxt, pat: @ast::pat, val: ValueRef,
|
|||
bcx.fcx.lllocals.insert(pat.id, local_mem(alloc));
|
||||
trans_common::add_clean(bcx, alloc, ty);
|
||||
} else { bcx.fcx.lllocals.insert(pat.id, local_mem(val)); }
|
||||
alt inner {
|
||||
some(pat) { bcx = bind_irrefutable_pat(bcx, pat, val, true); }
|
||||
_ {}
|
||||
}
|
||||
}
|
||||
ast::pat_tag(_, sub) {
|
||||
if vec::len(sub) == 0u { ret bcx; }
|
||||
|
|
|
@ -1048,7 +1048,7 @@ type binding = {lhs: [inst], rhs: option::t<initializer>};
|
|||
fn local_to_bindings(loc: @local) -> binding {
|
||||
let lhs = [];
|
||||
pat_bindings(loc.node.pat) {|p|
|
||||
let ident = alt p.node { pat_bind(name) { name } };
|
||||
let ident = alt p.node { pat_bind(name, _) { name } };
|
||||
lhs += [{ident: ident, node: p.id}];
|
||||
};
|
||||
{lhs: lhs, rhs: loc.node.init}
|
||||
|
|
|
@ -12,7 +12,7 @@ type ctxt = {cs: @mutable [sp_constr], tcx: ty::ctxt};
|
|||
|
||||
fn collect_local(loc: @local, cx: ctxt, v: visit::vt<ctxt>) {
|
||||
pat_bindings(loc.node.pat) {|p|
|
||||
let ident = alt p.node { pat_bind(id) { id } };
|
||||
let ident = alt p.node { pat_bind(id, _) { id } };
|
||||
log "collect_local: pushing " + ident;;
|
||||
*cx.cs += [respan(loc.span, ninit(p.id, ident))];
|
||||
};
|
||||
|
|
|
@ -108,7 +108,7 @@ fn find_pre_post_loop(fcx: fn_ctxt, l: @local, index: @expr, body: blk,
|
|||
find_pre_post_expr(fcx, index);
|
||||
find_pre_post_block(fcx, body);
|
||||
pat_bindings(l.node.pat) {|p|
|
||||
let ident = alt p.node { pat_bind(id) { id } };
|
||||
let ident = alt p.node { pat_bind(id, _) { id } };
|
||||
let v_init = ninit(p.id, ident);
|
||||
relax_precond_block(fcx, bit_num(fcx, v_init) as node_id, body);
|
||||
// Hack: for-loop index variables are frequently ignored,
|
||||
|
@ -579,11 +579,7 @@ fn find_pre_post_stmt(fcx: fn_ctxt, s: stmt) {
|
|||
/* FIXME: This won't be necessary when typestate
|
||||
works well enough for pat_bindings to return a
|
||||
refinement-typed thing. */
|
||||
let ident = alt pat.node {
|
||||
pat_bind(n) { n }
|
||||
_ { fcx.ccx.tcx.sess.span_bug(pat.span,
|
||||
"Impossible LHS"); }
|
||||
};
|
||||
let ident = alt pat.node { pat_bind(n, _) { n } };
|
||||
alt p {
|
||||
some(p) {
|
||||
copy_in_postcond(fcx, id,
|
||||
|
@ -612,14 +608,10 @@ fn find_pre_post_stmt(fcx: fn_ctxt, s: stmt) {
|
|||
postconds of the RHSs themselves */
|
||||
pat_bindings(alocal.node.pat) {|pat|
|
||||
alt pat.node {
|
||||
pat_bind(n) {
|
||||
pat_bind(n, _) {
|
||||
set_in_postcond(bit_num(fcx, ninit(pat.id, n)),
|
||||
prev_pp);
|
||||
}
|
||||
_ {
|
||||
fcx.ccx.tcx.sess.span_bug(pat.span,
|
||||
"Impossible LHS");
|
||||
}
|
||||
}
|
||||
};
|
||||
copy_pre_post_(fcx.ccx, id, prev_pp.precondition,
|
||||
|
|
|
@ -206,7 +206,7 @@ fn find_pre_post_state_loop(fcx: fn_ctxt, pres: prestate, l: @local,
|
|||
// in the body
|
||||
let index_post = tritv_clone(expr_poststate(fcx.ccx, index));
|
||||
pat_bindings(l.node.pat) {|p|
|
||||
let ident = alt p.node { pat_bind(name) { name } };
|
||||
let ident = alt p.node { pat_bind(name, _) { name } };
|
||||
set_in_poststate_ident(fcx, p.id, ident, index_post);
|
||||
};
|
||||
|
||||
|
|
|
@ -1178,7 +1178,7 @@ fn gather_locals(ccx: @crate_ctxt, f: ast::_fn, id: ast::node_id,
|
|||
let visit_pat =
|
||||
lambda (p: @ast::pat, &&e: (), v: visit::vt<()>) {
|
||||
alt p.node {
|
||||
ast::pat_bind(_) { assign(p.id, none); }
|
||||
ast::pat_bind(_, _) { assign(p.id, none); }
|
||||
_ {/* no-op */ }
|
||||
}
|
||||
visit::visit_pat(p, e, v);
|
||||
|
@ -1248,7 +1248,7 @@ fn check_pat(fcx: @fn_ctxt, map: ast_util::pat_id_map, pat: @ast::pat,
|
|||
}
|
||||
write::ty_only_fixup(fcx, pat.id, b_ty);
|
||||
}
|
||||
ast::pat_bind(name) {
|
||||
ast::pat_bind(name, sub) {
|
||||
let vid = lookup_local(fcx, pat.span, pat.id);
|
||||
let typ = ty::mk_var(fcx.ccx.tcx, vid);
|
||||
typ = demand::simple(fcx, pat.span, expected, typ);
|
||||
|
@ -1260,6 +1260,10 @@ fn check_pat(fcx: @fn_ctxt, map: ast_util::pat_id_map, pat: @ast::pat,
|
|||
typ = demand::simple(fcx, pat.span, ct, typ);
|
||||
}
|
||||
write::ty_only_fixup(fcx, pat.id, typ);
|
||||
alt sub {
|
||||
some(p) { check_pat(fcx, map, p, expected); }
|
||||
_ {}
|
||||
}
|
||||
}
|
||||
ast::pat_tag(path, subpats) {
|
||||
// Typecheck the path.
|
||||
|
|
|
@ -92,7 +92,7 @@ type field_pat = {ident: ident, pat: @pat};
|
|||
|
||||
tag pat_ {
|
||||
pat_wild;
|
||||
pat_bind(ident);
|
||||
pat_bind(ident, option::t<@pat>);
|
||||
pat_tag(@path, [@pat]);
|
||||
pat_rec([field_pat], bool);
|
||||
pat_tup([@pat]);
|
||||
|
|
|
@ -58,7 +58,7 @@ type pat_id_map = std::map::hashmap<str, node_id>;
|
|||
fn pat_id_map(pat: @pat) -> pat_id_map {
|
||||
let map = std::map::new_str_hash::<node_id>();
|
||||
pat_bindings(pat) {|bound|
|
||||
let name = alt bound.node { pat_bind(n) { n } };
|
||||
let name = alt bound.node { pat_bind(n, _) { n } };
|
||||
map.insert(name, bound.id);
|
||||
};
|
||||
ret map;
|
||||
|
@ -67,7 +67,8 @@ fn pat_id_map(pat: @pat) -> pat_id_map {
|
|||
// FIXME: could return a constrained type
|
||||
fn pat_bindings(pat: @pat, it: block(@pat)) {
|
||||
alt pat.node {
|
||||
pat_bind(_) { it(pat); }
|
||||
pat_bind(_, option::none.) { it(pat); }
|
||||
pat_bind(_, option::some(sub)) { it(pat); pat_bindings(sub, it); }
|
||||
pat_tag(_, sub) { for p in sub { pat_bindings(p, it); } }
|
||||
pat_rec(fields, _) { for f in fields { pat_bindings(f.pat, it); } }
|
||||
pat_tup(elts) { for elt in elts { pat_bindings(elt, it); } }
|
||||
|
|
|
@ -270,7 +270,9 @@ fn noop_fold_arm(a: arm, fld: ast_fold) -> arm {
|
|||
fn noop_fold_pat(p: pat_, fld: ast_fold) -> pat_ {
|
||||
ret alt p {
|
||||
pat_wild. { p }
|
||||
pat_bind(ident) { pat_bind(fld.fold_ident(ident)) }
|
||||
pat_bind(ident, sub) {
|
||||
pat_bind(fld.fold_ident(ident), option::map(fld.fold_pat, sub))
|
||||
}
|
||||
pat_lit(_) { p }
|
||||
pat_tag(pth, pats) {
|
||||
pat_tag(fld.fold_path(pth), vec::map(fld.fold_pat, pats))
|
||||
|
|
|
@ -1429,10 +1429,9 @@ fn parse_pat(p: parser) -> @ast::pat {
|
|||
if p.get_bad_expr_words().contains_key(fieldname) {
|
||||
p.fatal("found " + fieldname + " in binding position");
|
||||
}
|
||||
subpat =
|
||||
@{id: p.get_id(),
|
||||
node: ast::pat_bind(fieldname),
|
||||
span: ast_util::mk_sp(lo, hi)};
|
||||
subpat = @{id: p.get_id(),
|
||||
node: ast::pat_bind(fieldname, none),
|
||||
span: ast_util::mk_sp(lo, hi)};
|
||||
}
|
||||
fields += [{ident: fieldname, pat: subpat}];
|
||||
}
|
||||
|
@ -1479,7 +1478,9 @@ fn parse_pat(p: parser) -> @ast::pat {
|
|||
_ { true }
|
||||
} {
|
||||
hi = p.get_hi_pos();
|
||||
pat = ast::pat_bind(parse_value_ident(p));
|
||||
let name = parse_value_ident(p);
|
||||
let sub = eat(p, token::AT) ? some(parse_pat(p)) : none;
|
||||
pat = ast::pat_bind(name, sub);
|
||||
} else {
|
||||
let tag_path = parse_path_and_ty_param_substs(p);
|
||||
hi = tag_path.span.hi;
|
||||
|
|
|
@ -1062,7 +1062,13 @@ fn print_pat(s: ps, &&pat: @ast::pat) {
|
|||
s.ann.pre(ann_node);
|
||||
alt pat.node {
|
||||
ast::pat_wild. { word(s.s, "_"); }
|
||||
ast::pat_bind(id) { word(s.s, id); }
|
||||
ast::pat_bind(id, sub) {
|
||||
word(s.s, id);
|
||||
alt sub {
|
||||
some(p) { word(s.s, "@"); print_pat(s, p); }
|
||||
_ {}
|
||||
}
|
||||
}
|
||||
ast::pat_tag(path, args) {
|
||||
print_path(s, path, true);
|
||||
if vec::len(args) > 0u {
|
||||
|
|
|
@ -159,8 +159,9 @@ fn visit_pat<E>(p: @pat, e: E, v: vt<E>) {
|
|||
for f: field_pat in fields { v.visit_pat(f.pat, e, v); }
|
||||
}
|
||||
pat_tup(elts) { for elt in elts { v.visit_pat(elt, e, v); } }
|
||||
pat_box(inner) { v.visit_pat(inner, e, v); }
|
||||
pat_uniq(inner) { v.visit_pat(inner, e, v); }
|
||||
pat_box(inner) | pat_uniq(inner) | pat_bind(_, some(inner)) {
|
||||
v.visit_pat(inner, e, v);
|
||||
}
|
||||
_ { }
|
||||
}
|
||||
}
|
||||
|
|
12
src/test/run-pass/nested-patterns.rs
Normal file
12
src/test/run-pass/nested-patterns.rs
Normal file
|
@ -0,0 +1,12 @@
|
|||
fn main() {
|
||||
alt {a: 10, b: @20} {
|
||||
x@{a, b: @20} { assert x.a == 10; assert a == 10; }
|
||||
{b, _} { fail; }
|
||||
}
|
||||
let x@{b, _} = {a: 10, b: {mutable c: 20}};
|
||||
x.b.c = 30;
|
||||
assert b.c == 20;
|
||||
let y@{d, _} = {a: 10, d: {mutable c: 20}};
|
||||
y.d.c = 30;
|
||||
assert d.c == 20;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue