diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 68ddfdc404a..6e7a8203b61 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -308,7 +308,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { err.emit(); } - let item = item + let item = self.fully_configure(item) .map_attrs(|mut attrs| { attrs.retain(|a| a.path != "derive"); attrs }); let item_with_markers = add_derived_markers(&mut self.cx, item.span(), &traits, item.clone()); @@ -400,6 +400,27 @@ impl<'a, 'b> MacroExpander<'a, 'b> { result } + fn fully_configure(&mut self, item: Annotatable) -> Annotatable { + let mut cfg = StripUnconfigured { + should_test: self.cx.ecfg.should_test, + sess: self.cx.parse_sess, + features: self.cx.ecfg.features, + }; + // Since the item itself has already been configured by the InvocationCollector, + // we know that fold result vector will contain exactly one element + match item { + Annotatable::Item(item) => { + Annotatable::Item(cfg.fold_item(item).pop().unwrap()) + } + Annotatable::TraitItem(item) => { + Annotatable::TraitItem(item.map(|item| cfg.fold_trait_item(item).pop().unwrap())) + } + Annotatable::ImplItem(item) => { + Annotatable::ImplItem(item.map(|item| cfg.fold_impl_item(item).pop().unwrap())) + } + } + } + fn expand_invoc(&mut self, invoc: Invocation, ext: Rc) -> Expansion { let result = match invoc.kind { InvocationKind::Bang { .. } => self.expand_bang_invoc(invoc, ext), @@ -740,15 +761,6 @@ struct InvocationCollector<'a, 'b: 'a> { monotonic: bool, } -macro_rules! fully_configure { - ($this:ident, $node:ident, $noop_fold:ident) => { - match $noop_fold($node, &mut $this.cfg).pop() { - Some(node) => node, - None => return SmallVector::new(), - } - } -} - impl<'a, 'b> InvocationCollector<'a, 'b> { fn collect(&mut self, expansion_kind: ExpansionKind, kind: InvocationKind) -> Expansion { let mark = Mark::fresh(self.cx.current_expansion.mark); @@ -900,7 +912,7 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> { let (attr, traits, mut item) = self.classify_item(item); if attr.is_some() || !traits.is_empty() { - let item = Annotatable::Item(fully_configure!(self, item, noop_fold_item)); + let item = Annotatable::Item(item); return self.collect_attr(attr, traits, item, ExpansionKind::Items).make_items(); } @@ -974,8 +986,7 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> { let (attr, traits, item) = self.classify_item(item); if attr.is_some() || !traits.is_empty() { - let item = - Annotatable::TraitItem(P(fully_configure!(self, item, noop_fold_trait_item))); + let item = Annotatable::TraitItem(P(item)); return self.collect_attr(attr, traits, item, ExpansionKind::TraitItems) .make_trait_items() } @@ -995,7 +1006,7 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> { let (attr, traits, item) = self.classify_item(item); if attr.is_some() || !traits.is_empty() { - let item = Annotatable::ImplItem(P(fully_configure!(self, item, noop_fold_impl_item))); + let item = Annotatable::ImplItem(P(item)); return self.collect_attr(attr, traits, item, ExpansionKind::ImplItems) .make_impl_items(); } diff --git a/src/test/run-pass-fulldeps/proc-macro/attr-cfg.rs b/src/test/run-pass-fulldeps/proc-macro/attr-cfg.rs new file mode 100644 index 00000000000..5a28d756df5 --- /dev/null +++ b/src/test/run-pass-fulldeps/proc-macro/attr-cfg.rs @@ -0,0 +1,39 @@ +// Copyright 2016 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. + +// aux-build:attr-cfg.rs +// ignore-stage1 +// revisions: foo bar + +#![feature(proc_macro)] + +extern crate attr_cfg; +use attr_cfg::attr_cfg; + +#[attr_cfg] +fn outer() -> u8 { + #[cfg(foo)] + fn inner() -> u8 { 1 } + + #[cfg(bar)] + fn inner() -> u8 { 2 } + + inner() +} + +#[cfg(foo)] +fn main() { + assert_eq!(outer(), 1); +} + +#[cfg(bar)] +fn main() { + assert_eq!(outer(), 2); +} diff --git a/src/test/run-pass-fulldeps/proc-macro/auxiliary/attr-cfg.rs b/src/test/run-pass-fulldeps/proc-macro/auxiliary/attr-cfg.rs new file mode 100644 index 00000000000..9145c46cfc7 --- /dev/null +++ b/src/test/run-pass-fulldeps/proc-macro/auxiliary/attr-cfg.rs @@ -0,0 +1,32 @@ +// Copyright 2016 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. + +// no-prefer-dynamic +#![feature(proc_macro)] +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_attribute] +pub fn attr_cfg(args: TokenStream, input: TokenStream) -> TokenStream { + let input_str = input.to_string(); + + assert_eq!(input_str, "fn outer() -> u8 { + #[cfg(foo)] + fn inner() -> u8 { 1 } + #[cfg(bar)] + fn inner() -> u8 { 2 } + inner() +}"); + + input +} diff --git a/src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-attr-cfg.rs b/src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-attr-cfg.rs new file mode 100644 index 00000000000..787a4a470e2 --- /dev/null +++ b/src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-attr-cfg.rs @@ -0,0 +1,23 @@ +// Copyright 2016 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. + +// no-prefer-dynamic +#![feature(proc_macro)] +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_derive(Foo, attributes(foo))] +pub fn derive(input: TokenStream) -> TokenStream { + assert!(!input.to_string().contains("#[cfg(any())]")); + "".parse().unwrap() +} diff --git a/src/test/run-pass-fulldeps/proc-macro/derive-attr-cfg.rs b/src/test/run-pass-fulldeps/proc-macro/derive-attr-cfg.rs new file mode 100644 index 00000000000..b94c45248da --- /dev/null +++ b/src/test/run-pass-fulldeps/proc-macro/derive-attr-cfg.rs @@ -0,0 +1,27 @@ +// Copyright 2016 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. + +// aux-build:derive-attr-cfg.rs +// ignore-stage1 + +#![feature(proc_macro)] + +extern crate derive_attr_cfg; +use derive_attr_cfg::Foo; + +#[derive(Foo)] +#[foo] +struct S { + #[cfg(any())] + x: i32 +} + +fn main() { +}