auto merge of #10366 : brson/rust/ignore-patterns, r=alexcrichton

This replaces `*` with `..` in enums, `_` with `..` in structs, and `.._` with `..` in vectors. It adds obsolete syntax warnings for the old forms but doesn't turn them on yet because we need a snapshot.

#5830
This commit is contained in:
bors 2013-11-18 16:36:33 -08:00
commit 7fc3e82aae
17 changed files with 138 additions and 24 deletions

View file

@ -97,7 +97,7 @@ impl CFGBuilder {
ast::PatEnum(_, None) |
ast::PatLit(*) |
ast::PatRange(*) |
ast::PatWild => {
ast::PatWild | ast::PatWildMulti => {
self.add_node(pat.id, [pred])
}

View file

@ -333,7 +333,7 @@ fn is_useful_specialized(cx: &MatchCheckCtxt,
fn pat_ctor_id(cx: &MatchCheckCtxt, p: @Pat) -> Option<ctor> {
let pat = raw_pat(p);
match pat.node {
PatWild => { None }
PatWild | PatWildMulti => { None }
PatIdent(_, _, _) | PatEnum(_, _) => {
match cx.tcx.def_map.find(&pat.id) {
Some(&DefVariant(_, id, _)) => Some(variant(id)),
@ -369,7 +369,7 @@ fn pat_ctor_id(cx: &MatchCheckCtxt, p: @Pat) -> Option<ctor> {
fn is_wild(cx: &MatchCheckCtxt, p: @Pat) -> bool {
let pat = raw_pat(p);
match pat.node {
PatWild => { true }
PatWild | PatWildMulti => { true }
PatIdent(_, _, _) => {
match cx.tcx.def_map.find(&pat.id) {
Some(&DefVariant(_, _, _)) | Some(&DefStatic(*)) => { false }
@ -532,6 +532,10 @@ fn wild() -> @Pat {
@Pat {id: 0, node: PatWild, span: dummy_sp()}
}
fn wild_multi() -> @Pat {
@Pat {id: 0, node: PatWildMulti, span: dummy_sp()}
}
fn specialize(cx: &MatchCheckCtxt,
r: &[@Pat],
ctor_id: &ctor,
@ -546,6 +550,9 @@ fn specialize(cx: &MatchCheckCtxt,
PatWild => {
Some(vec::append(vec::from_elem(arity, wild()), r.tail()))
}
PatWildMulti => {
Some(vec::append(vec::from_elem(arity, wild_multi()), r.tail()))
}
PatIdent(_, _, _) => {
match cx.tcx.def_map.find(&pat_id) {
Some(&DefVariant(_, id, _)) => {
@ -849,7 +856,7 @@ fn is_refutable(cx: &MatchCheckCtxt, pat: &Pat) -> bool {
PatIdent(_, _, Some(sub)) => {
is_refutable(cx, sub)
}
PatWild | PatIdent(_, _, None) => { false }
PatWild | PatWildMulti | PatIdent(_, _, None) => { false }
PatLit(@Expr {node: ExprLit(@Spanned { node: lit_nil, _}), _}) => {
// "()"
false

View file

@ -876,7 +876,7 @@ impl mem_categorization_ctxt {
op(cmt, pat);
match pat.node {
ast::PatWild => {
ast::PatWild | ast::PatWildMulti => {
// _
}

View file

@ -65,7 +65,7 @@ pub fn pat_is_binding(dm: resolve::DefMap, pat: @Pat) -> bool {
pub fn pat_is_binding_or_wild(dm: resolve::DefMap, pat: @Pat) -> bool {
match pat.node {
PatIdent(*) => pat_is_binding(dm, pat),
PatWild => true,
PatWild | PatWildMulti => true,
_ => false
}
}

View file

@ -545,7 +545,7 @@ fn enter_default<'r>(bcx: @mut Block,
// Collect all of the matches that can match against anything.
let matches = do enter_match(bcx, dm, m, col, val) |p| {
match p.node {
ast::PatWild | ast::PatTup(_) => Some(~[]),
ast::PatWild | ast::PatWildMulti | ast::PatTup(_) => Some(~[]),
ast::PatIdent(_, _, None) if pat_is_binding(dm, p) => Some(~[]),
_ => None
}
@ -2234,7 +2234,7 @@ fn bind_irrefutable_pat(bcx: @mut Block,
pat.span,
format!("vector patterns are never irrefutable!"));
}
ast::PatWild | ast::PatLit(_) | ast::PatRange(_, _) => ()
ast::PatWild | ast::PatWildMulti | ast::PatLit(_) | ast::PatRange(_, _) => ()
}
return bcx;
}

View file

@ -2429,7 +2429,7 @@ fn populate_scope_map(cx: &mut CrateContext,
}
}
ast::PatWild => {
ast::PatWild | ast::PatWildMulti => {
scope_map.insert(pat.id, scope_stack.last().scope_metadata);
}

View file

@ -414,7 +414,7 @@ pub fn check_pat(pcx: &pat_ctxt, pat: @ast::Pat, expected: ty::t) {
let tcx = pcx.fcx.ccx.tcx;
match pat.node {
ast::PatWild => {
ast::PatWild | ast::PatWildMulti => {
fcx.write_ty(pat.id, expected);
}
ast::PatLit(lt) => {

View file

@ -1219,7 +1219,7 @@ pub mod guarantor {
rcx.fcx.pat_to_str(pat), guarantor);
match pat.node {
ast::PatWild => {}
ast::PatWild | ast::PatWildMulti => {}
ast::PatIdent(ast::BindByRef(_), _, opt_p) => {
link(rcx, pat.span, pat.id, guarantor);

View file

@ -1137,6 +1137,7 @@ fn name_from_pat(p: &ast::Pat) -> ~str {
use syntax::ast::*;
match p.node {
PatWild => ~"_",
PatWildMulti => ~"..",
PatIdent(_, ref p, _) => path_to_str(p),
PatEnum(ref p, _) => path_to_str(p),
PatStruct(*) => fail!("tried to get argument name from pat_struct, \

View file

@ -337,6 +337,7 @@ pub enum BindingMode {
#[deriving(Clone, Eq, Encodable, Decodable, IterBytes)]
pub enum Pat_ {
PatWild,
PatWildMulti,
// A pat_ident may either be a new bound variable,
// or a nullary enum (in which case the second field
// is None).

View file

@ -657,7 +657,7 @@ pub fn walk_pat(pat: @Pat, it: &fn(@Pat) -> bool) -> bool {
slice.iter().advance(|&p| walk_pat(p, |p| it(p))) &&
after.iter().advance(|&p| walk_pat(p, |p| it(p)))
}
PatWild | PatLit(_) | PatRange(_, _) | PatIdent(_, _, _) |
PatWild | PatWildMulti | PatLit(_) | PatRange(_, _) | PatIdent(_, _, _) |
PatEnum(_, _) => {
true
}

View file

@ -174,6 +174,7 @@ pub trait ast_fold {
fn fold_pat(&self, p: @Pat) -> @Pat {
let node = match p.node {
PatWild => PatWild,
PatWildMulti => PatWildMulti,
PatIdent(binding_mode, ref pth, ref sub) => {
PatIdent(binding_mode,
self.fold_path(pth),

View file

@ -39,6 +39,9 @@ pub enum ObsoleteSyntax {
ObsoleteConstPointer,
ObsoleteEmptyImpl,
ObsoleteLoopAsContinue,
ObsoleteEnumWildcard,
ObsoleteStructWildcard,
ObsoleteVecDotDotWildcard
}
impl to_bytes::IterBytes for ObsoleteSyntax {
@ -113,6 +116,18 @@ impl ParserObsoleteMethods for Parser {
"`loop` is now only used for loops and `continue` is used for \
skipping iterations"
),
ObsoleteEnumWildcard => (
"enum wildcard",
"use `..` instead of `*` for matching all enum fields"
),
ObsoleteStructWildcard => (
"struct wildcard",
"use `..` instead of `_` for matching trailing struct fields"
),
ObsoleteVecDotDotWildcard => (
"vec slice wildcard",
"use `..` instead of `.._` for matching slices"
),
};
self.report(sp, kind, kind_str, desc);

View file

@ -43,7 +43,7 @@ use ast::{MutImmutable, MutMutable, mac_, mac_invoc_tt, matcher, match_nontermin
use ast::{match_seq, match_tok, method, mt, BiMul, Mutability};
use ast::{named_field, UnNeg, noreturn, UnNot, Pat, PatBox, PatEnum};
use ast::{PatIdent, PatLit, PatRange, PatRegion, PatStruct};
use ast::{PatTup, PatUniq, PatWild, private};
use ast::{PatTup, PatUniq, PatWild, PatWildMulti, private};
use ast::{BiRem, required};
use ast::{ret_style, return_val, BiShl, BiShr, Stmt, StmtDecl};
use ast::{StmtExpr, StmtSemi, StmtMac, struct_def, struct_field};
@ -2724,17 +2724,35 @@ impl Parser {
}
}
let subpat = self.parse_pat();
if is_slice {
match subpat {
@ast::Pat { node: PatWild, _ } => (),
@ast::Pat { node: PatIdent(_, _, _), _ } => (),
@ast::Pat { span, _ } => self.span_fatal(
span, "expected an identifier or `_`"
)
if *self.token == token::COMMA || *self.token == token::RBRACKET {
slice = Some(@ast::Pat {
id: ast::DUMMY_NODE_ID,
node: PatWildMulti,
span: *self.span,
})
} else {
let subpat = self.parse_pat();
match subpat {
@ast::Pat { id, node: PatWild, span } => {
// NOTE #5830 activate after snapshot
// self.obsolete(*self.span, ObsoleteVecDotDotWildcard);
slice = Some(@ast::Pat {
id: id,
node: PatWildMulti,
span: span
})
},
@ast::Pat { node: PatIdent(_, _, _), _ } => {
slice = Some(subpat);
}
@ast::Pat { span, _ } => self.span_fatal(
span, "expected an identifier or nothing"
)
}
}
slice = Some(subpat);
} else {
let subpat = self.parse_pat();
if before_slice {
before.push(subpat);
} else {
@ -2755,7 +2773,12 @@ impl Parser {
if first { first = false; }
else { self.expect(&token::COMMA); }
etc = *self.token == token::UNDERSCORE || *self.token == token::DOTDOT;
if *self.token == token::UNDERSCORE {
// NOTE #5830 activate after snapshot
// self.obsolete(*self.span, ObsoleteStructWildcard);
}
if etc {
self.bump();
if *self.token != token::RBRACE {
self.fatal(
@ -3016,9 +3039,19 @@ impl Parser {
_ => false,
}
};
if is_star {
let is_dotdot = do self.look_ahead(1) |t| {
match *t {
token::DOTDOT => true,
_ => false,
}
};
if is_star | is_dotdot {
// This is a "top constructor only" pat
self.bump();
if is_star {
// NOTE #5830 activate after snapshot
// self.obsolete(*self.span, ObsoleteEnumWildcard);
}
self.bump();
self.expect(&token::RPAREN);
pat = PatEnum(enum_path, None);

View file

@ -1613,6 +1613,7 @@ pub fn print_pat(s: @ps, pat: &ast::Pat) {
is that it doesn't matter */
match pat.node {
ast::PatWild => word(s.s, "_"),
ast::PatWildMulti => word(s.s, ".."),
ast::PatIdent(binding_mode, ref path, sub) => {
match binding_mode {
ast::BindByRef(mutbl) => {
@ -1701,7 +1702,12 @@ pub fn print_pat(s: @ps, pat: &ast::Pat) {
}
for &p in slice.iter() {
if !before.is_empty() { word_space(s, ","); }
word(s.s, "..");
match p {
@ast::Pat { node: ast::PatWildMulti, _ } => {
// this case is handled by print_pat
}
_ => word(s.s, ".."),
}
print_pat(s, p);
if !after.is_empty() { word_space(s, ","); }
}

View file

@ -375,7 +375,7 @@ pub fn walk_pat<E:Clone, V:Visitor<E>>(visitor: &mut V, pattern: &Pat, env: E) {
visitor.visit_expr(lower_bound, env.clone());
visitor.visit_expr(upper_bound, env)
}
PatWild => (),
PatWild | PatWildMulti => (),
PatVec(ref prepattern, ref slice_pattern, ref postpatterns) => {
for prepattern in prepattern.iter() {
visitor.visit_pat(*prepattern, env.clone())

View file

@ -0,0 +1,50 @@
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
struct Foo(int, int, int, int);
struct Bar{a: int, b: int, c: int, d: int}
pub fn main() {
let Foo(..) = Foo(5, 5, 5, 5);
let Foo(*) = Foo(5, 5, 5, 5);
let Bar{..} = Bar{a: 5, b: 5, c: 5, d: 5};
let Bar{_} = Bar{a: 5, b: 5, c: 5, d: 5};
//let (..) = (5, 5, 5, 5);
//let Foo(a, b, ..) = Foo(5, 5, 5, 5);
//let Foo(.., d) = Foo(5, 5, 5, 5);
//let (a, b, ..) = (5, 5, 5, 5);
//let (.., c, d) = (5, 5, 5, 5);
let Bar{b: b, ..} = Bar{a: 5, b: 5, c: 5, d: 5};
let Bar{b: b, _} = Bar{a: 5, b: 5, c: 5, d: 5};
match [5, 5, 5, 5] {
[..] => { }
}
match [5, 5, 5, 5] {
[a, ..] => { }
}
match [5, 5, 5, 5] {
[.., b] => { }
}
match [5, 5, 5, 5] {
[a, .., b] => { }
}
match [5, 5, 5] {
[.._] => { }
}
match [5, 5, 5] {
[a, .._] => { }
}
match [5, 5, 5] {
[.._, a] => { }
}
match [5, 5, 5] {
[a, .._, b] => { }
}
}