Skip to content

Commit 46ef620

Browse files
committedSep 28, 2017
Auto merge of #44528 - tmnilsson:attr_proc_macro_cfg_process, r=jseyfried
Apply attr proc macros before cfg processing Fixes #39336. r? @jseyfried
2 parents 3c96d40 + 0f97b6b commit 46ef620

File tree

5 files changed

+146
-14
lines changed

5 files changed

+146
-14
lines changed
 

‎src/libsyntax/ext/expand.rs

+25-14
Original file line numberDiff line numberDiff line change
@@ -308,7 +308,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
308308
err.emit();
309309
}
310310

311-
let item = item
311+
let item = self.fully_configure(item)
312312
.map_attrs(|mut attrs| { attrs.retain(|a| a.path != "derive"); attrs });
313313
let item_with_markers =
314314
add_derived_markers(&mut self.cx, item.span(), &traits, item.clone());
@@ -400,6 +400,27 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
400400
result
401401
}
402402

403+
fn fully_configure(&mut self, item: Annotatable) -> Annotatable {
404+
let mut cfg = StripUnconfigured {
405+
should_test: self.cx.ecfg.should_test,
406+
sess: self.cx.parse_sess,
407+
features: self.cx.ecfg.features,
408+
};
409+
// Since the item itself has already been configured by the InvocationCollector,
410+
// we know that fold result vector will contain exactly one element
411+
match item {
412+
Annotatable::Item(item) => {
413+
Annotatable::Item(cfg.fold_item(item).pop().unwrap())
414+
}
415+
Annotatable::TraitItem(item) => {
416+
Annotatable::TraitItem(item.map(|item| cfg.fold_trait_item(item).pop().unwrap()))
417+
}
418+
Annotatable::ImplItem(item) => {
419+
Annotatable::ImplItem(item.map(|item| cfg.fold_impl_item(item).pop().unwrap()))
420+
}
421+
}
422+
}
423+
403424
fn expand_invoc(&mut self, invoc: Invocation, ext: Rc<SyntaxExtension>) -> Expansion {
404425
let result = match invoc.kind {
405426
InvocationKind::Bang { .. } => self.expand_bang_invoc(invoc, ext),
@@ -740,15 +761,6 @@ struct InvocationCollector<'a, 'b: 'a> {
740761
monotonic: bool,
741762
}
742763

743-
macro_rules! fully_configure {
744-
($this:ident, $node:ident, $noop_fold:ident) => {
745-
match $noop_fold($node, &mut $this.cfg).pop() {
746-
Some(node) => node,
747-
None => return SmallVector::new(),
748-
}
749-
}
750-
}
751-
752764
impl<'a, 'b> InvocationCollector<'a, 'b> {
753765
fn collect(&mut self, expansion_kind: ExpansionKind, kind: InvocationKind) -> Expansion {
754766
let mark = Mark::fresh(self.cx.current_expansion.mark);
@@ -900,7 +912,7 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
900912

901913
let (attr, traits, mut item) = self.classify_item(item);
902914
if attr.is_some() || !traits.is_empty() {
903-
let item = Annotatable::Item(fully_configure!(self, item, noop_fold_item));
915+
let item = Annotatable::Item(item);
904916
return self.collect_attr(attr, traits, item, ExpansionKind::Items).make_items();
905917
}
906918

@@ -974,8 +986,7 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
974986

975987
let (attr, traits, item) = self.classify_item(item);
976988
if attr.is_some() || !traits.is_empty() {
977-
let item =
978-
Annotatable::TraitItem(P(fully_configure!(self, item, noop_fold_trait_item)));
989+
let item = Annotatable::TraitItem(P(item));
979990
return self.collect_attr(attr, traits, item, ExpansionKind::TraitItems)
980991
.make_trait_items()
981992
}
@@ -995,7 +1006,7 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
9951006

9961007
let (attr, traits, item) = self.classify_item(item);
9971008
if attr.is_some() || !traits.is_empty() {
998-
let item = Annotatable::ImplItem(P(fully_configure!(self, item, noop_fold_impl_item)));
1009+
let item = Annotatable::ImplItem(P(item));
9991010
return self.collect_attr(attr, traits, item, ExpansionKind::ImplItems)
10001011
.make_impl_items();
10011012
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// aux-build:attr-cfg.rs
12+
// ignore-stage1
13+
// revisions: foo bar
14+
15+
#![feature(proc_macro)]
16+
17+
extern crate attr_cfg;
18+
use attr_cfg::attr_cfg;
19+
20+
#[attr_cfg]
21+
fn outer() -> u8 {
22+
#[cfg(foo)]
23+
fn inner() -> u8 { 1 }
24+
25+
#[cfg(bar)]
26+
fn inner() -> u8 { 2 }
27+
28+
inner()
29+
}
30+
31+
#[cfg(foo)]
32+
fn main() {
33+
assert_eq!(outer(), 1);
34+
}
35+
36+
#[cfg(bar)]
37+
fn main() {
38+
assert_eq!(outer(), 2);
39+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// no-prefer-dynamic
12+
#![feature(proc_macro)]
13+
#![crate_type = "proc-macro"]
14+
15+
extern crate proc_macro;
16+
17+
use proc_macro::TokenStream;
18+
19+
#[proc_macro_attribute]
20+
pub fn attr_cfg(args: TokenStream, input: TokenStream) -> TokenStream {
21+
let input_str = input.to_string();
22+
23+
assert_eq!(input_str, "fn outer() -> u8 {
24+
#[cfg(foo)]
25+
fn inner() -> u8 { 1 }
26+
#[cfg(bar)]
27+
fn inner() -> u8 { 2 }
28+
inner()
29+
}");
30+
31+
input
32+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// no-prefer-dynamic
12+
#![feature(proc_macro)]
13+
#![crate_type = "proc-macro"]
14+
15+
extern crate proc_macro;
16+
17+
use proc_macro::TokenStream;
18+
19+
#[proc_macro_derive(Foo, attributes(foo))]
20+
pub fn derive(input: TokenStream) -> TokenStream {
21+
assert!(!input.to_string().contains("#[cfg(any())]"));
22+
"".parse().unwrap()
23+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// aux-build:derive-attr-cfg.rs
12+
// ignore-stage1
13+
14+
#![feature(proc_macro)]
15+
16+
extern crate derive_attr_cfg;
17+
use derive_attr_cfg::Foo;
18+
19+
#[derive(Foo)]
20+
#[foo]
21+
struct S {
22+
#[cfg(any())]
23+
x: i32
24+
}
25+
26+
fn main() {
27+
}

0 commit comments

Comments
 (0)
Please sign in to comment.