auto merge of #12812 : sfackler/rust/attr-arm, r=alexcrichton
This is really only useful for #[cfg()]. For example: ```rust enum Foo { Bar, Baz, #[cfg(blob)] Blob } fn match_foos(f: &Foo) { match *f { Bar => {} Baz => {} #[cfg(blob)] Blob => {} } } ``` This is a kind of weird place to allow attributes, so it should probably be discussed before merging.
This commit is contained in:
commit
867898977d
@ -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());
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -112,6 +112,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,
|
||||
@ -131,6 +132,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),
|
||||
|
@ -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),
|
||||
|
@ -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();
|
||||
|
@ -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 {
|
||||
|
26
src/test/run-pass/cfg-match-arm.rs
Normal file
26
src/test/run-pass/cfg-match-arm.rs
Normal 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() {}
|
Loading…
x
Reference in New Issue
Block a user