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:
commit
7fc3e82aae
@ -97,7 +97,7 @@ fn pat(&mut self, pat: @ast::Pat, pred: CFGIndex) -> CFGIndex {
|
||||
ast::PatEnum(_, None) |
|
||||
ast::PatLit(*) |
|
||||
ast::PatRange(*) |
|
||||
ast::PatWild => {
|
||||
ast::PatWild | ast::PatWildMulti => {
|
||||
self.add_node(pat.id, [pred])
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -876,7 +876,7 @@ pub fn cat_pattern(&self,
|
||||
op(cmt, pat);
|
||||
|
||||
match pat.node {
|
||||
ast::PatWild => {
|
||||
ast::PatWild | ast::PatWildMulti => {
|
||||
// _
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -2429,7 +2429,7 @@ fn walk_pattern(cx: &mut CrateContext,
|
||||
}
|
||||
}
|
||||
|
||||
ast::PatWild => {
|
||||
ast::PatWild | ast::PatWildMulti => {
|
||||
scope_map.insert(pat.id, scope_stack.last().scope_metadata);
|
||||
}
|
||||
|
||||
|
@ -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) => {
|
||||
|
@ -1219,7 +1219,7 @@ fn link_ref_bindings_in_pat(
|
||||
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);
|
||||
|
||||
|
@ -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, \
|
||||
|
@ -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).
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -174,6 +174,7 @@ fn fold_arm(&self, a: &Arm) -> Arm {
|
||||
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),
|
||||
|
@ -39,6 +39,9 @@ pub enum ObsoleteSyntax {
|
||||
ObsoleteConstPointer,
|
||||
ObsoleteEmptyImpl,
|
||||
ObsoleteLoopAsContinue,
|
||||
ObsoleteEnumWildcard,
|
||||
ObsoleteStructWildcard,
|
||||
ObsoleteVecDotDotWildcard
|
||||
}
|
||||
|
||||
impl to_bytes::IterBytes for ObsoleteSyntax {
|
||||
@ -113,6 +116,18 @@ fn obsolete(&self, sp: Span, kind: ObsoleteSyntax) {
|
||||
"`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);
|
||||
|
@ -43,7 +43,7 @@
|
||||
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 @@ fn parse_pat_vec_elements(
|
||||
}
|
||||
}
|
||||
|
||||
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 @@ fn parse_pat_fields(&self) -> (~[ast::FieldPat], bool) {
|
||||
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 @@ pub fn parse_pat(&self) -> @Pat {
|
||||
_ => 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);
|
||||
|
@ -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 @@ fn print_field(s: @ps, f: &ast::FieldPat) {
|
||||
}
|
||||
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, ","); }
|
||||
}
|
||||
|
@ -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())
|
||||
|
50
src/test/run-pass/ignore-all-the-things.rs
Normal file
50
src/test/run-pass/ignore-all-the-things.rs
Normal 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] => { }
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user