Auto merge of #44528 - tmnilsson:attr_proc_macro_cfg_process, r=jseyfried
Apply attr proc macros before cfg processing Fixes #39336. r? @jseyfried
This commit is contained in:
commit
46ef6208f8
@ -308,7 +308,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
|||||||
err.emit();
|
err.emit();
|
||||||
}
|
}
|
||||||
|
|
||||||
let item = item
|
let item = self.fully_configure(item)
|
||||||
.map_attrs(|mut attrs| { attrs.retain(|a| a.path != "derive"); attrs });
|
.map_attrs(|mut attrs| { attrs.retain(|a| a.path != "derive"); attrs });
|
||||||
let item_with_markers =
|
let item_with_markers =
|
||||||
add_derived_markers(&mut self.cx, item.span(), &traits, item.clone());
|
add_derived_markers(&mut self.cx, item.span(), &traits, item.clone());
|
||||||
@ -400,6 +400,27 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
|||||||
result
|
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<SyntaxExtension>) -> Expansion {
|
fn expand_invoc(&mut self, invoc: Invocation, ext: Rc<SyntaxExtension>) -> Expansion {
|
||||||
let result = match invoc.kind {
|
let result = match invoc.kind {
|
||||||
InvocationKind::Bang { .. } => self.expand_bang_invoc(invoc, ext),
|
InvocationKind::Bang { .. } => self.expand_bang_invoc(invoc, ext),
|
||||||
@ -740,15 +761,6 @@ struct InvocationCollector<'a, 'b: 'a> {
|
|||||||
monotonic: bool,
|
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> {
|
impl<'a, 'b> InvocationCollector<'a, 'b> {
|
||||||
fn collect(&mut self, expansion_kind: ExpansionKind, kind: InvocationKind) -> Expansion {
|
fn collect(&mut self, expansion_kind: ExpansionKind, kind: InvocationKind) -> Expansion {
|
||||||
let mark = Mark::fresh(self.cx.current_expansion.mark);
|
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);
|
let (attr, traits, mut item) = self.classify_item(item);
|
||||||
if attr.is_some() || !traits.is_empty() {
|
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();
|
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);
|
let (attr, traits, item) = self.classify_item(item);
|
||||||
if attr.is_some() || !traits.is_empty() {
|
if attr.is_some() || !traits.is_empty() {
|
||||||
let item =
|
let item = Annotatable::TraitItem(P(item));
|
||||||
Annotatable::TraitItem(P(fully_configure!(self, item, noop_fold_trait_item)));
|
|
||||||
return self.collect_attr(attr, traits, item, ExpansionKind::TraitItems)
|
return self.collect_attr(attr, traits, item, ExpansionKind::TraitItems)
|
||||||
.make_trait_items()
|
.make_trait_items()
|
||||||
}
|
}
|
||||||
@ -995,7 +1006,7 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
|
|||||||
|
|
||||||
let (attr, traits, item) = self.classify_item(item);
|
let (attr, traits, item) = self.classify_item(item);
|
||||||
if attr.is_some() || !traits.is_empty() {
|
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)
|
return self.collect_attr(attr, traits, item, ExpansionKind::ImplItems)
|
||||||
.make_impl_items();
|
.make_impl_items();
|
||||||
}
|
}
|
||||||
|
39
src/test/run-pass-fulldeps/proc-macro/attr-cfg.rs
Normal file
39
src/test/run-pass-fulldeps/proc-macro/attr-cfg.rs
Normal file
@ -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 <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.
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
}
|
32
src/test/run-pass-fulldeps/proc-macro/auxiliary/attr-cfg.rs
Normal file
32
src/test/run-pass-fulldeps/proc-macro/auxiliary/attr-cfg.rs
Normal file
@ -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 <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.
|
||||||
|
|
||||||
|
// 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
|
||||||
|
}
|
@ -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 <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.
|
||||||
|
|
||||||
|
// 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()
|
||||||
|
}
|
27
src/test/run-pass-fulldeps/proc-macro/derive-attr-cfg.rs
Normal file
27
src/test/run-pass-fulldeps/proc-macro/derive-attr-cfg.rs
Normal file
@ -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 <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.
|
||||||
|
|
||||||
|
// 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() {
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user