Port cfg!() macro to the new attribute parsing system

Signed-off-by: Jonathan Brouwer <jonathantbrouwer@gmail.com>
This commit is contained in:
Jonathan Brouwer 2025-10-21 20:13:41 +02:00
parent 001be2fab4
commit b78800fd5d
No known key found for this signature in database
GPG Key ID: 13619B051B673C52
10 changed files with 83 additions and 51 deletions

View File

@ -50,7 +50,7 @@ pub fn parse_cfg<'c, S: Stage>(
parse_cfg_entry(cx, single).ok()
}
pub(crate) fn parse_cfg_entry<S: Stage>(
pub fn parse_cfg_entry<S: Stage>(
cx: &mut AcceptContext<'_, '_, S>,
item: &MetaItemOrLitParser<'_>,
) -> Result<CfgEntry, ErrorGuaranteed> {

View File

@ -106,7 +106,7 @@ mod target_checking;
pub mod validate_attr;
pub use attributes::cfg::{
CFG_TEMPLATE, EvalConfigResult, eval_config_entry, parse_cfg, parse_cfg_attr,
CFG_TEMPLATE, EvalConfigResult, eval_config_entry, parse_cfg, parse_cfg_attr, parse_cfg_entry,
};
pub use attributes::cfg_old::*;
pub use attributes::util::{is_builtin_attr, is_doc_alias_attrs_contain_symbol, parse_version};

View File

@ -2,13 +2,16 @@
//! a literal `true` or `false` based on whether the given cfg matches the
//! current compilation environment.
use rustc_ast::token;
use rustc_ast::tokenstream::TokenStream;
use rustc_errors::PResult;
use rustc_ast::{AttrStyle, CRATE_NODE_ID, token};
use rustc_attr_parsing as attr;
use rustc_attr_parsing::parser::MetaItemOrLitParser;
use rustc_attr_parsing::{AttributeParser, CFG_TEMPLATE, ShouldEmit, parse_cfg_entry};
use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacEager, MacroExpanderResult};
use rustc_hir::AttrPath;
use rustc_hir::attrs::CfgEntry;
use rustc_parse::exp;
use rustc_span::Span;
use {rustc_ast as ast, rustc_attr_parsing as attr};
use rustc_span::{ErrorGuaranteed, Ident, Span};
use crate::errors;
@ -21,38 +24,48 @@ pub(crate) fn expand_cfg(
ExpandResult::Ready(match parse_cfg(cx, sp, tts) {
Ok(cfg) => {
let matches_cfg = attr::cfg_matches(
let matches_cfg = attr::eval_config_entry(
cx.sess,
&cfg,
&cx.sess,
cx.current_expansion.lint_node_id,
Some(cx.ecfg.features),
);
ShouldEmit::ErrorsAndLints,
)
.as_bool();
MacEager::expr(cx.expr_bool(sp, matches_cfg))
}
Err(err) => {
let guar = err.emit();
DummyResult::any(sp, guar)
}
Err(guar) => DummyResult::any(sp, guar),
})
}
fn parse_cfg<'a>(
cx: &ExtCtxt<'a>,
span: Span,
tts: TokenStream,
) -> PResult<'a, ast::MetaItemInner> {
let mut p = cx.new_parser_from_tts(tts);
if p.token == token::Eof {
return Err(cx.dcx().create_err(errors::RequiresCfgPattern { span }));
fn parse_cfg(cx: &ExtCtxt<'_>, span: Span, tts: TokenStream) -> Result<CfgEntry, ErrorGuaranteed> {
let mut parser = cx.new_parser_from_tts(tts);
if parser.token == token::Eof {
return Err(cx.dcx().emit_err(errors::RequiresCfgPattern { span }));
}
let cfg = p.parse_meta_item_inner()?;
let meta = MetaItemOrLitParser::parse_single(&mut parser, ShouldEmit::ErrorsAndLints)
.map_err(|diag| diag.emit())?;
let cfg = AttributeParser::parse_single_args(
cx.sess,
span,
span,
AttrStyle::Inner,
AttrPath { segments: vec![Ident::from_str("cfg")].into_boxed_slice(), span },
span,
CRATE_NODE_ID,
Some(cx.ecfg.features),
ShouldEmit::ErrorsAndLints,
&meta,
parse_cfg_entry,
&CFG_TEMPLATE,
)?;
let _ = p.eat(exp!(Comma));
let _ = parser.eat(exp!(Comma));
if !p.eat(exp!(Eof)) {
return Err(cx.dcx().create_err(errors::OneCfgPattern { span }));
if !parser.eat(exp!(Eof)) {
return Err(cx.dcx().emit_err(errors::OneCfgPattern { span }));
}
Ok(cfg)

View File

@ -1,18 +1,22 @@
The `not` cfg-predicate was malformed.
Erroneous code example:
Erroneous code example (using `cargo doc`):
```compile_fail,E0536
```ignore, E0536 (only triggers on cargo doc)
#![feature(doc_cfg)]
#[doc(cfg(not()))]
pub fn main() {
if cfg!(not()) { }
}
```
The `not` predicate expects one cfg-pattern. Example:
```
#![feature(doc_cfg)]
#[doc(cfg(not(target_os = "linux")))] // ok!
pub fn main() {
if cfg!(not(target_os = "linux")) { } // ok!
}
```

View File

@ -1,6 +1,6 @@
fn main() {
cfg!(); //~ ERROR macro requires a cfg-pattern
cfg!(123); //~ ERROR literal in `cfg` predicate value must be a boolean
cfg!(foo = 123); //~ ERROR literal in `cfg` predicate value must be a string
cfg!(123); //~ ERROR malformed `cfg` attribute input
cfg!(foo = 123); //~ ERROR malformed `cfg` attribute input
cfg!(foo, bar); //~ ERROR expected 1 cfg-pattern
}

View File

@ -4,17 +4,27 @@ error: macro requires a cfg-pattern as an argument
LL | cfg!();
| ^^^^^^ cfg-pattern required
error[E0565]: literal in `cfg` predicate value must be a boolean
--> $DIR/cfg.rs:3:10
error[E0539]: malformed `cfg` attribute input
--> $DIR/cfg.rs:3:5
|
LL | cfg!(123);
| ^^^
| ^^^^^---^
| | |
| | expected a valid identifier here
| help: must be of the form: `cfg(predicate)`
|
= note: for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg-attribute>
error[E0565]: literal in `cfg` predicate value must be a string
--> $DIR/cfg.rs:4:16
error[E0539]: malformed `cfg` attribute input
--> $DIR/cfg.rs:4:5
|
LL | cfg!(foo = 123);
| ^^^
| ^^^^^^^^^^^---^
| | |
| | expected a string literal here
| help: must be of the form: `cfg(predicate)`
|
= note: for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg-attribute>
error: expected 1 cfg-pattern
--> $DIR/cfg.rs:5:5
@ -24,4 +34,4 @@ LL | cfg!(foo, bar);
error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0565`.
For more information about this error, try `rustc --explain E0539`.

View File

@ -1,3 +0,0 @@
pub fn main() {
if cfg!(not()) { } //~ ERROR E0536
}

View File

@ -1,9 +0,0 @@
error[E0536]: expected 1 cfg-pattern
--> $DIR/E0536.rs:2:13
|
LL | if cfg!(not()) { }
| ^^^^^
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0536`.

3
tests/ui/span/E0805.rs Normal file
View File

@ -0,0 +1,3 @@
pub fn main() {
if cfg!(not()) { } //~ ERROR E0805
}

View File

@ -0,0 +1,14 @@
error[E0805]: malformed `cfg` attribute input
--> $DIR/E0805.rs:2:8
|
LL | if cfg!(not()) { }
| ^^^^^^^^--^
| | |
| | expected a single argument here
| help: must be of the form: `cfg(predicate)`
|
= note: for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg-attribute>
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0805`.