Implement RFC 1925

This commit is contained in:
Matt Ickstadt 2017-08-26 17:09:31 -05:00
parent ed532c0d93
commit f866152991
7 changed files with 81 additions and 2 deletions

View File

@ -0,0 +1,21 @@
# `match_beginning_vert`
The tracking issue for this feature is [#44101].
With this feature enabled, you are allowed to add a '|' to the beginning of a
match arm:
```rust
#![feature(match_beginning_vert)]
enum Foo { A, B }
fn main() {
let x = Foo::A;
match x {
| A | B => {},
}
}
```
[#44101]: https://github.com/rust-lang/rust/issues/44101

View File

@ -810,6 +810,7 @@ pub struct Arm {
pub pats: Vec<P<Pat>>, pub pats: Vec<P<Pat>>,
pub guard: Option<P<Expr>>, pub guard: Option<P<Expr>>,
pub body: P<Expr>, pub body: P<Expr>,
pub beginning_vert: Option<Span>, // For RFC 1925 feature gate
} }
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]

View File

@ -878,7 +878,8 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
attrs: vec![], attrs: vec![],
pats, pats,
guard: None, guard: None,
body: expr body: expr,
beginning_vert: None,
} }
} }

View File

@ -379,6 +379,9 @@ declare_features! (
// allow `#[must_use]` on functions (RFC 1940) // allow `#[must_use]` on functions (RFC 1940)
(active, fn_must_use, "1.21.0", Some(43302)), (active, fn_must_use, "1.21.0", Some(43302)),
// allow '|' at beginning of match arms (RFC 1925)
(active, match_beginning_vert, "1.21.0", Some(44101)),
); );
declare_features! ( declare_features! (
@ -1435,6 +1438,14 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
visit::walk_expr(self, e); visit::walk_expr(self, e);
} }
fn visit_arm(&mut self, arm: &'a ast::Arm) {
if let Some(span) = arm.beginning_vert {
gate_feature_post!(&self, match_beginning_vert,
span,
"Use of a '|' at the beginning of a match arm is experimental")
}
}
fn visit_pat(&mut self, pattern: &'a ast::Pat) { fn visit_pat(&mut self, pattern: &'a ast::Pat) {
match pattern.node { match pattern.node {
PatKind::Slice(_, Some(_), ref last) if !last.is_empty() => { PatKind::Slice(_, Some(_), ref last) if !last.is_empty() => {

View File

@ -344,12 +344,14 @@ pub fn fold_thin_attrs<T: Folder>(attrs: ThinVec<Attribute>, fld: &mut T) -> Thi
fold_attrs(attrs.into(), fld).into() fold_attrs(attrs.into(), fld).into()
} }
pub fn noop_fold_arm<T: Folder>(Arm {attrs, pats, guard, body}: Arm, fld: &mut T) -> Arm { pub fn noop_fold_arm<T: Folder>(Arm {attrs, pats, guard, body, beginning_vert}: Arm,
fld: &mut T) -> Arm {
Arm { Arm {
attrs: fold_attrs(attrs, fld), attrs: fold_attrs(attrs, fld),
pats: pats.move_map(|x| fld.fold_pat(x)), pats: pats.move_map(|x| fld.fold_pat(x)),
guard: guard.map(|x| fld.fold_expr(x)), guard: guard.map(|x| fld.fold_expr(x)),
body: fld.fold_expr(body), body: fld.fold_expr(body),
beginning_vert,
} }
} }

View File

@ -3155,6 +3155,12 @@ impl<'a> Parser<'a> {
maybe_whole!(self, NtArm, |x| x); maybe_whole!(self, NtArm, |x| x);
let attrs = self.parse_outer_attributes()?; let attrs = self.parse_outer_attributes()?;
// Allow a '|' before the pats (RFC 1925)
let beginning_vert = if self.eat(&token::BinOp(token::Or)) {
Some(self.prev_span)
} else {
None
};
let pats = self.parse_pats()?; let pats = self.parse_pats()?;
let guard = if self.eat_keyword(keywords::If) { let guard = if self.eat_keyword(keywords::If) {
Some(self.parse_expr()?) Some(self.parse_expr()?)
@ -3178,6 +3184,7 @@ impl<'a> Parser<'a> {
pats, pats,
guard, guard,
body: expr, body: expr,
beginning_vert,
}) })
} }

View File

@ -0,0 +1,36 @@
// Copyright 2017 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.
#[allow(dead_code)]
enum Foo {
A,
B,
C,
D,
E,
}
use Foo::*;
fn main() {
let x = Foo::A;
match x {
| A => println!("A"),
//~^ ERROR: Use of a '|' at the beginning of a match arm is experimental (see issue #44101)
| B | C => println!("BC!"),
//~^ ERROR: Use of a '|' at the beginning of a match arm is experimental (see issue #44101)
| _ => {},
//~^ ERROR: Use of a '|' at the beginning of a match arm is experimental (see issue #44101)
};
match x {
A | B | C => println!("ABC!"),
_ => {},
};
}