diff --git a/src/librustc/front/config.rs b/src/librustc/front/config.rs index 888a8f6bd8d85..8dcc97c936cbb 100644 --- a/src/librustc/front/config.rs +++ b/src/librustc/front/config.rs @@ -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::P { }) } +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()); } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 116411c9e0510..4a93fed8d039b 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -440,6 +440,7 @@ pub enum Decl_ { #[deriving(Clone, Eq, TotalEq, Encodable, Decodable, Hash)] pub struct Arm { + pub attrs: Vec, pub pats: Vec<@Pat>, pub guard: Option<@Expr>, pub body: @Expr, diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index e1174ea6cc434..b0dbd8b635ac6 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -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 diff --git a/src/libsyntax/ext/deriving/primitive.rs b/src/libsyntax/ext/deriving/primitive.rs index e42a3c67e34ea..8a95290acdf29 100644 --- a/src/libsyntax/ext/deriving/primitive.rs +++ b/src/libsyntax/ext/deriving/primitive.rs @@ -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), diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 04b289b9fca46..9f05db5f807c4 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -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), diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 8808312bed759..f30d756d854f4 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -2539,6 +2539,7 @@ impl<'a> Parser<'a> { self.commit_expr_expecting(discriminant, token::LBRACE); let mut arms: Vec = 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(); diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index f768bf22ce0ce..b0130f127a381 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -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 { diff --git a/src/test/run-pass/cfg-match-arm.rs b/src/test/run-pass/cfg-match-arm.rs new file mode 100644 index 0000000000000..9858b804b7b3a --- /dev/null +++ b/src/test/run-pass/cfg-match-arm.rs @@ -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 or the MIT license +// , 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() {}