Implement built-in attribute macro #[cfg_eval]
This commit is contained in:
parent
069e612e73
commit
5dad6c2575
11 changed files with 259 additions and 0 deletions
29
compiler/rustc_builtin_macros/src/cfg_eval.rs
Normal file
29
compiler/rustc_builtin_macros/src/cfg_eval.rs
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
use crate::util::check_builtin_macro_attribute;
|
||||||
|
|
||||||
|
use rustc_ast::{self as ast, AstLike};
|
||||||
|
use rustc_expand::base::{Annotatable, ExtCtxt};
|
||||||
|
use rustc_expand::config::StripUnconfigured;
|
||||||
|
use rustc_span::symbol::sym;
|
||||||
|
use rustc_span::Span;
|
||||||
|
|
||||||
|
pub fn expand(
|
||||||
|
ecx: &mut ExtCtxt<'_>,
|
||||||
|
_span: Span,
|
||||||
|
meta_item: &ast::MetaItem,
|
||||||
|
item: Annotatable,
|
||||||
|
) -> Vec<Annotatable> {
|
||||||
|
check_builtin_macro_attribute(ecx, meta_item, sym::cfg_eval);
|
||||||
|
|
||||||
|
let mut visitor =
|
||||||
|
StripUnconfigured { sess: ecx.sess, features: ecx.ecfg.features, modified: false };
|
||||||
|
let mut item = visitor.fully_configure(item);
|
||||||
|
if visitor.modified {
|
||||||
|
// Erase the tokens if cfg-stripping modified the item
|
||||||
|
// This will cause us to synthesize fake tokens
|
||||||
|
// when `nt_to_tokenstream` is called on this item.
|
||||||
|
if let Some(tokens) = item.tokens_mut() {
|
||||||
|
*tokens = None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
vec![item]
|
||||||
|
}
|
|
@ -24,6 +24,7 @@ mod asm;
|
||||||
mod assert;
|
mod assert;
|
||||||
mod cfg;
|
mod cfg;
|
||||||
mod cfg_accessible;
|
mod cfg_accessible;
|
||||||
|
mod cfg_eval;
|
||||||
mod compile_error;
|
mod compile_error;
|
||||||
mod concat;
|
mod concat;
|
||||||
mod concat_idents;
|
mod concat_idents;
|
||||||
|
@ -89,6 +90,7 @@ pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) {
|
||||||
register_attr! {
|
register_attr! {
|
||||||
bench: test::expand_bench,
|
bench: test::expand_bench,
|
||||||
cfg_accessible: cfg_accessible::Expander,
|
cfg_accessible: cfg_accessible::Expander,
|
||||||
|
cfg_eval: cfg_eval::expand,
|
||||||
derive: derive::Expander,
|
derive: derive::Expander,
|
||||||
global_allocator: global_allocator::expand,
|
global_allocator: global_allocator::expand,
|
||||||
test: test::expand_test,
|
test: test::expand_test,
|
||||||
|
|
|
@ -344,6 +344,7 @@ symbols! {
|
||||||
cfg_attr,
|
cfg_attr,
|
||||||
cfg_attr_multi,
|
cfg_attr_multi,
|
||||||
cfg_doctest,
|
cfg_doctest,
|
||||||
|
cfg_eval,
|
||||||
cfg_panic,
|
cfg_panic,
|
||||||
cfg_sanitize,
|
cfg_sanitize,
|
||||||
cfg_target_feature,
|
cfg_target_feature,
|
||||||
|
|
|
@ -1452,6 +1452,18 @@ pub(crate) mod builtin {
|
||||||
/* compiler built-in */
|
/* compiler built-in */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Expands all `#[cfg]` and `#[cfg_attr]` attributes in the code fragment it's applied to.
|
||||||
|
#[cfg(not(bootstrap))]
|
||||||
|
#[unstable(
|
||||||
|
feature = "cfg_eval",
|
||||||
|
issue = "82679",
|
||||||
|
reason = "`cfg_eval` is a recently implemented feature"
|
||||||
|
)]
|
||||||
|
#[rustc_builtin_macro]
|
||||||
|
pub macro cfg_eval($($tt:tt)*) {
|
||||||
|
/* compiler built-in */
|
||||||
|
}
|
||||||
|
|
||||||
/// Unstable implementation detail of the `rustc` compiler, do not use.
|
/// Unstable implementation detail of the `rustc` compiler, do not use.
|
||||||
#[rustc_builtin_macro]
|
#[rustc_builtin_macro]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
|
|
@ -81,3 +81,12 @@ pub use crate::macros::builtin::derive;
|
||||||
)]
|
)]
|
||||||
#[doc(no_inline)]
|
#[doc(no_inline)]
|
||||||
pub use crate::macros::builtin::cfg_accessible;
|
pub use crate::macros::builtin::cfg_accessible;
|
||||||
|
|
||||||
|
#[cfg(not(bootstrap))]
|
||||||
|
#[unstable(
|
||||||
|
feature = "cfg_eval",
|
||||||
|
issue = "82679",
|
||||||
|
reason = "`cfg_eval` is a recently implemented feature"
|
||||||
|
)]
|
||||||
|
#[doc(no_inline)]
|
||||||
|
pub use crate::macros::builtin::cfg_eval;
|
||||||
|
|
|
@ -234,6 +234,7 @@
|
||||||
#![feature(box_syntax)]
|
#![feature(box_syntax)]
|
||||||
#![feature(c_variadic)]
|
#![feature(c_variadic)]
|
||||||
#![feature(cfg_accessible)]
|
#![feature(cfg_accessible)]
|
||||||
|
#![cfg_attr(not(bootstrap), feature(cfg_eval))]
|
||||||
#![feature(cfg_target_has_atomic)]
|
#![feature(cfg_target_has_atomic)]
|
||||||
#![feature(cfg_target_thread_local)]
|
#![feature(cfg_target_thread_local)]
|
||||||
#![feature(char_error_internals)]
|
#![feature(char_error_internals)]
|
||||||
|
|
|
@ -67,6 +67,15 @@ pub use core::prelude::v1::derive;
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub use core::prelude::v1::cfg_accessible;
|
pub use core::prelude::v1::cfg_accessible;
|
||||||
|
|
||||||
|
#[cfg(not(bootstrap))]
|
||||||
|
#[unstable(
|
||||||
|
feature = "cfg_eval",
|
||||||
|
issue = "82679",
|
||||||
|
reason = "`cfg_eval` is a recently implemented feature"
|
||||||
|
)]
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub use core::prelude::v1::cfg_eval;
|
||||||
|
|
||||||
// The file so far is equivalent to src/libcore/prelude/v1.rs,
|
// The file so far is equivalent to src/libcore/prelude/v1.rs,
|
||||||
// and below to src/liballoc/prelude.rs.
|
// and below to src/liballoc/prelude.rs.
|
||||||
// Those files are duplicated rather than using glob imports
|
// Those files are duplicated rather than using glob imports
|
||||||
|
|
9
src/test/ui/proc-macro/cfg-eval-fail.rs
Normal file
9
src/test/ui/proc-macro/cfg-eval-fail.rs
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
#![feature(cfg_eval)]
|
||||||
|
#![feature(stmt_expr_attributes)]
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let _ = #[cfg_eval] #[cfg(FALSE)] 0;
|
||||||
|
//~^ ERROR removing an expression is not supported in this position
|
||||||
|
//~| ERROR removing an expression is not supported in this position
|
||||||
|
//~| ERROR removing an expression is not supported in this position
|
||||||
|
}
|
20
src/test/ui/proc-macro/cfg-eval-fail.stderr
Normal file
20
src/test/ui/proc-macro/cfg-eval-fail.stderr
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
error: removing an expression is not supported in this position
|
||||||
|
--> $DIR/cfg-eval-fail.rs:5:25
|
||||||
|
|
|
||||||
|
LL | let _ = #[cfg_eval] #[cfg(FALSE)] 0;
|
||||||
|
| ^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: removing an expression is not supported in this position
|
||||||
|
--> $DIR/cfg-eval-fail.rs:5:25
|
||||||
|
|
|
||||||
|
LL | let _ = #[cfg_eval] #[cfg(FALSE)] 0;
|
||||||
|
| ^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: removing an expression is not supported in this position
|
||||||
|
--> $DIR/cfg-eval-fail.rs:5:25
|
||||||
|
|
|
||||||
|
LL | let _ = #[cfg_eval] #[cfg(FALSE)] 0;
|
||||||
|
| ^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: aborting due to 3 previous errors
|
||||||
|
|
32
src/test/ui/proc-macro/cfg-eval.rs
Normal file
32
src/test/ui/proc-macro/cfg-eval.rs
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
// check-pass
|
||||||
|
// compile-flags: -Z span-debug
|
||||||
|
// aux-build:test-macros.rs
|
||||||
|
|
||||||
|
#![feature(cfg_eval)]
|
||||||
|
#![feature(proc_macro_hygiene)]
|
||||||
|
#![feature(stmt_expr_attributes)]
|
||||||
|
|
||||||
|
#![no_std] // Don't load unnecessary hygiene information from std
|
||||||
|
extern crate std;
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
extern crate test_macros;
|
||||||
|
|
||||||
|
#[cfg_eval]
|
||||||
|
#[print_attr]
|
||||||
|
struct S1 {
|
||||||
|
#[cfg(FALSE)]
|
||||||
|
field_false: u8,
|
||||||
|
#[cfg(all(/*true*/))]
|
||||||
|
#[cfg_attr(FALSE, unknown_attr)]
|
||||||
|
#[cfg_attr(all(/*true*/), allow())]
|
||||||
|
field_true: u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg_eval]
|
||||||
|
#[cfg(FALSE)]
|
||||||
|
struct S2 {}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let _ = #[cfg_eval] #[print_attr](#[cfg(FALSE)] 0, #[cfg(all(/*true*/))] 1);
|
||||||
|
}
|
135
src/test/ui/proc-macro/cfg-eval.stdout
Normal file
135
src/test/ui/proc-macro/cfg-eval.stdout
Normal file
|
@ -0,0 +1,135 @@
|
||||||
|
PRINT-ATTR INPUT (DISPLAY): struct S1 { #[cfg(all())] #[allow()] field_true : u8, }
|
||||||
|
PRINT-ATTR INPUT (DEBUG): TokenStream [
|
||||||
|
Ident {
|
||||||
|
ident: "struct",
|
||||||
|
span: $DIR/cfg-eval.rs:17:1: 24:2 (#0),
|
||||||
|
},
|
||||||
|
Ident {
|
||||||
|
ident: "S1",
|
||||||
|
span: $DIR/cfg-eval.rs:17:1: 24:2 (#0),
|
||||||
|
},
|
||||||
|
Group {
|
||||||
|
delimiter: Brace,
|
||||||
|
stream: TokenStream [
|
||||||
|
Punct {
|
||||||
|
ch: '#',
|
||||||
|
spacing: Alone,
|
||||||
|
span: $DIR/cfg-eval.rs:17:1: 24:2 (#0),
|
||||||
|
},
|
||||||
|
Group {
|
||||||
|
delimiter: Bracket,
|
||||||
|
stream: TokenStream [
|
||||||
|
Ident {
|
||||||
|
ident: "cfg",
|
||||||
|
span: $DIR/cfg-eval.rs:17:1: 24:2 (#0),
|
||||||
|
},
|
||||||
|
Group {
|
||||||
|
delimiter: Parenthesis,
|
||||||
|
stream: TokenStream [
|
||||||
|
Ident {
|
||||||
|
ident: "all",
|
||||||
|
span: $DIR/cfg-eval.rs:17:1: 24:2 (#0),
|
||||||
|
},
|
||||||
|
Group {
|
||||||
|
delimiter: Parenthesis,
|
||||||
|
stream: TokenStream [],
|
||||||
|
span: $DIR/cfg-eval.rs:17:1: 24:2 (#0),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
span: $DIR/cfg-eval.rs:17:1: 24:2 (#0),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
span: $DIR/cfg-eval.rs:17:1: 24:2 (#0),
|
||||||
|
},
|
||||||
|
Punct {
|
||||||
|
ch: '#',
|
||||||
|
spacing: Alone,
|
||||||
|
span: $DIR/cfg-eval.rs:17:1: 24:2 (#0),
|
||||||
|
},
|
||||||
|
Group {
|
||||||
|
delimiter: Bracket,
|
||||||
|
stream: TokenStream [
|
||||||
|
Ident {
|
||||||
|
ident: "allow",
|
||||||
|
span: $DIR/cfg-eval.rs:17:1: 24:2 (#0),
|
||||||
|
},
|
||||||
|
Group {
|
||||||
|
delimiter: Parenthesis,
|
||||||
|
stream: TokenStream [],
|
||||||
|
span: $DIR/cfg-eval.rs:17:1: 24:2 (#0),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
span: $DIR/cfg-eval.rs:17:1: 24:2 (#0),
|
||||||
|
},
|
||||||
|
Ident {
|
||||||
|
ident: "field_true",
|
||||||
|
span: $DIR/cfg-eval.rs:17:1: 24:2 (#0),
|
||||||
|
},
|
||||||
|
Punct {
|
||||||
|
ch: ':',
|
||||||
|
spacing: Alone,
|
||||||
|
span: $DIR/cfg-eval.rs:17:1: 24:2 (#0),
|
||||||
|
},
|
||||||
|
Ident {
|
||||||
|
ident: "u8",
|
||||||
|
span: $DIR/cfg-eval.rs:17:1: 24:2 (#0),
|
||||||
|
},
|
||||||
|
Punct {
|
||||||
|
ch: ',',
|
||||||
|
spacing: Alone,
|
||||||
|
span: $DIR/cfg-eval.rs:17:1: 24:2 (#0),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
span: $DIR/cfg-eval.rs:17:1: 24:2 (#0),
|
||||||
|
},
|
||||||
|
]
|
||||||
|
PRINT-ATTR INPUT (DISPLAY): (#[cfg(all())] 1,)
|
||||||
|
PRINT-ATTR INPUT (DEBUG): TokenStream [
|
||||||
|
Group {
|
||||||
|
delimiter: Parenthesis,
|
||||||
|
stream: TokenStream [
|
||||||
|
Punct {
|
||||||
|
ch: '#',
|
||||||
|
spacing: Alone,
|
||||||
|
span: $DIR/cfg-eval.rs:31:38: 31:80 (#0),
|
||||||
|
},
|
||||||
|
Group {
|
||||||
|
delimiter: Bracket,
|
||||||
|
stream: TokenStream [
|
||||||
|
Ident {
|
||||||
|
ident: "cfg",
|
||||||
|
span: $DIR/cfg-eval.rs:31:38: 31:80 (#0),
|
||||||
|
},
|
||||||
|
Group {
|
||||||
|
delimiter: Parenthesis,
|
||||||
|
stream: TokenStream [
|
||||||
|
Ident {
|
||||||
|
ident: "all",
|
||||||
|
span: $DIR/cfg-eval.rs:31:38: 31:80 (#0),
|
||||||
|
},
|
||||||
|
Group {
|
||||||
|
delimiter: Parenthesis,
|
||||||
|
stream: TokenStream [],
|
||||||
|
span: $DIR/cfg-eval.rs:31:38: 31:80 (#0),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
span: $DIR/cfg-eval.rs:31:38: 31:80 (#0),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
span: $DIR/cfg-eval.rs:31:38: 31:80 (#0),
|
||||||
|
},
|
||||||
|
Literal {
|
||||||
|
kind: Integer,
|
||||||
|
symbol: "1",
|
||||||
|
suffix: None,
|
||||||
|
span: $DIR/cfg-eval.rs:31:38: 31:80 (#0),
|
||||||
|
},
|
||||||
|
Punct {
|
||||||
|
ch: ',',
|
||||||
|
spacing: Alone,
|
||||||
|
span: $DIR/cfg-eval.rs:31:38: 31:80 (#0),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
span: $DIR/cfg-eval.rs:31:38: 31:80 (#0),
|
||||||
|
},
|
||||||
|
]
|
Loading…
Add table
Add a link
Reference in a new issue