diff --git a/compiler/rustc_attr_parsing/src/attributes/cfg.rs b/compiler/rustc_attr_parsing/src/attributes/cfg.rs index 7f703782a854..c9d4e2e83000 100644 --- a/compiler/rustc_attr_parsing/src/attributes/cfg.rs +++ b/compiler/rustc_attr_parsing/src/attributes/cfg.rs @@ -50,7 +50,7 @@ pub fn parse_cfg<'c, S: Stage>( parse_cfg_entry(cx, single).ok() } -pub(crate) fn parse_cfg_entry( +pub fn parse_cfg_entry( cx: &mut AcceptContext<'_, '_, S>, item: &MetaItemOrLitParser<'_>, ) -> Result { diff --git a/compiler/rustc_attr_parsing/src/lib.rs b/compiler/rustc_attr_parsing/src/lib.rs index bcd0d674c75f..9579b0eae804 100644 --- a/compiler/rustc_attr_parsing/src/lib.rs +++ b/compiler/rustc_attr_parsing/src/lib.rs @@ -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}; diff --git a/compiler/rustc_builtin_macros/src/cfg.rs b/compiler/rustc_builtin_macros/src/cfg.rs index 85b8ef79c050..5ac23f992054 100644 --- a/compiler/rustc_builtin_macros/src/cfg.rs +++ b/compiler/rustc_builtin_macros/src/cfg.rs @@ -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 { + 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) diff --git a/compiler/rustc_error_codes/src/error_codes/E0536.md b/compiler/rustc_error_codes/src/error_codes/E0536.md index f00d17739448..c1f43fa741cf 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0536.md +++ b/compiler/rustc_error_codes/src/error_codes/E0536.md @@ -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! + } ``` diff --git a/tests/ui/macros/cfg.rs b/tests/ui/macros/cfg.rs index 50998572274e..4b817f682a29 100644 --- a/tests/ui/macros/cfg.rs +++ b/tests/ui/macros/cfg.rs @@ -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 } diff --git a/tests/ui/macros/cfg.stderr b/tests/ui/macros/cfg.stderr index ad3f9b188ddb..cdbbea16cbe9 100644 --- a/tests/ui/macros/cfg.stderr +++ b/tests/ui/macros/cfg.stderr @@ -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 -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 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`. diff --git a/tests/ui/span/E0536.rs b/tests/ui/span/E0536.rs deleted file mode 100644 index ae0733633541..000000000000 --- a/tests/ui/span/E0536.rs +++ /dev/null @@ -1,3 +0,0 @@ -pub fn main() { - if cfg!(not()) { } //~ ERROR E0536 -} diff --git a/tests/ui/span/E0536.stderr b/tests/ui/span/E0536.stderr deleted file mode 100644 index 6c25f9140a1a..000000000000 --- a/tests/ui/span/E0536.stderr +++ /dev/null @@ -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`. diff --git a/tests/ui/span/E0805.rs b/tests/ui/span/E0805.rs new file mode 100644 index 000000000000..097f5cd8e586 --- /dev/null +++ b/tests/ui/span/E0805.rs @@ -0,0 +1,3 @@ +pub fn main() { + if cfg!(not()) { } //~ ERROR E0805 +} diff --git a/tests/ui/span/E0805.stderr b/tests/ui/span/E0805.stderr new file mode 100644 index 000000000000..544af096ccc7 --- /dev/null +++ b/tests/ui/span/E0805.stderr @@ -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 + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0805`.