Allow attributes on match arms

RFC: 0008-match-arm-attributes
This commit is contained in:
Steven Fackler 2014-04-22 21:54:48 -07:00
parent 3d05e7f9cd
commit 1452c9c04a
8 changed files with 66 additions and 3 deletions

View File

@ -1,4 +1,4 @@
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
@ -36,6 +36,9 @@ impl<'a> fold::Folder for Context<'a> {
fn fold_item_underscore(&mut self, item: &ast::Item_) -> ast::Item_ {
fold_item_underscore(self, item)
}
fn fold_expr(&mut self, expr: @ast::Expr) -> @ast::Expr {
fold_expr(self, expr)
}
}
pub fn strip_items(krate: ast::Crate,
@ -189,6 +192,24 @@ fn fold_block(cx: &mut Context, b: ast::P<ast::Block>) -> ast::P<ast::Block> {
})
}
fn fold_expr(cx: &mut Context, expr: @ast::Expr) -> @ast::Expr {
let expr = match expr.node {
ast::ExprMatch(ref m, ref arms) => {
let arms = arms.iter()
.filter(|a| (cx.in_cfg)(a.attrs.as_slice()))
.map(|a| a.clone())
.collect();
@ast::Expr {
id: expr.id,
span: expr.span.clone(),
node: ast::ExprMatch(m.clone(), arms),
}
}
_ => expr.clone()
};
fold::noop_fold_expr(expr, cx)
}
fn item_in_cfg(cx: &mut Context, item: &ast::Item) -> bool {
return (cx.in_cfg)(item.attrs.as_slice());
}

View File

@ -440,6 +440,7 @@ pub enum Decl_ {
#[deriving(Clone, Eq, TotalEq, Encodable, Decodable, Hash)]
pub struct Arm {
pub attrs: Vec<Attribute>,
pub pats: Vec<@Pat>,
pub guard: Option<@Expr>,
pub body: @Expr,

View File

@ -726,6 +726,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
fn arm(&self, _span: Span, pats: Vec<@ast::Pat> , expr: @ast::Expr) -> ast::Arm {
ast::Arm {
attrs: vec!(),
pats: pats,
guard: None,
body: expr

View File

@ -110,6 +110,7 @@ fn cs_from(name: &str, cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure
// arm for `_ if $guard => $body`
let arm = ast::Arm {
attrs: vec!(),
pats: vec!(cx.pat_wild(span)),
guard: Some(guard),
body: body,
@ -129,6 +130,7 @@ fn cs_from(name: &str, cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure
// arm for `_ => None`
let arm = ast::Arm {
attrs: vec!(),
pats: vec!(cx.pat_wild(trait_span)),
guard: None,
body: cx.expr_none(trait_span),

View File

@ -119,6 +119,7 @@ pub trait Folder {
fn fold_arm(&mut self, a: &Arm) -> Arm {
Arm {
attrs: a.attrs.iter().map(|x| fold_attribute_(*x, self)).collect(),
pats: a.pats.iter().map(|x| self.fold_pat(*x)).collect(),
guard: a.guard.map(|x| self.fold_expr(x)),
body: self.fold_expr(a.body),

View File

@ -2539,6 +2539,7 @@ impl<'a> Parser<'a> {
self.commit_expr_expecting(discriminant, token::LBRACE);
let mut arms: Vec<Arm> = Vec::new();
while self.token != token::RBRACE {
let attrs = self.parse_outer_attributes();
let pats = self.parse_pats();
let mut guard = None;
if self.eat_keyword(keywords::If) {
@ -2557,7 +2558,12 @@ impl<'a> Parser<'a> {
self.eat(&token::COMMA);
}
arms.push(ast::Arm { pats: pats, guard: guard, body: expr });
arms.push(ast::Arm {
attrs: attrs,
pats: pats,
guard: guard,
body: expr
});
}
let hi = self.span.hi;
self.bump();

View File

@ -1286,9 +1286,14 @@ impl<'a> State<'a> {
try!(self.bopen());
let len = arms.len();
for (i, arm) in arms.iter().enumerate() {
try!(space(&mut self.s));
// I have no idea why this check is necessary, but here it
// is :(
if arm.attrs.is_empty() {
try!(space(&mut self.s));
}
try!(self.cbox(indent_unit));
try!(self.ibox(0u));
try!(self.print_outer_attributes(arm.attrs.as_slice()));
let mut first = true;
for p in arm.pats.iter() {
if first {

View File

@ -0,0 +1,26 @@
// Copyright 2014 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.
enum Foo {
Bar,
Baz,
}
fn foo(f: Foo) {
match f {
Bar => {},
#[cfg(not(asdfa))]
Baz => {},
#[cfg(afsd)]
Basdfwe => {}
}
}
pub fn main() {}