From a5814a5c6135357ea7f838fe9f73d207ea303a74 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Sun, 9 Nov 2025 15:44:05 +0100 Subject: [PATCH 1/3] Move `parse_cfg_select` to `rustc_builtin_macros` Signed-off-by: Jonathan Brouwer --- .../src/attributes/cfg_select.rs | 59 ++++++++++++ .../rustc_attr_parsing/src/attributes/mod.rs | 1 + compiler/rustc_attr_parsing/src/lib.rs | 1 + .../rustc_builtin_macros/src/cfg_select.rs | 2 +- compiler/rustc_parse/src/parser/cfg_select.rs | 93 +++++-------------- 5 files changed, 84 insertions(+), 72 deletions(-) create mode 100644 compiler/rustc_attr_parsing/src/attributes/cfg_select.rs diff --git a/compiler/rustc_attr_parsing/src/attributes/cfg_select.rs b/compiler/rustc_attr_parsing/src/attributes/cfg_select.rs new file mode 100644 index 0000000000000..7ee92d6926720 --- /dev/null +++ b/compiler/rustc_attr_parsing/src/attributes/cfg_select.rs @@ -0,0 +1,59 @@ +use rustc_ast::token::Token; +use rustc_ast::tokenstream::TokenStream; +use rustc_ast::{MetaItemInner, token}; +use rustc_errors::PResult; +use rustc_parse::exp; +use rustc_parse::parser::Parser; +use rustc_span::Span; + +pub enum CfgSelectPredicate { + Cfg(MetaItemInner), + Wildcard(Token), +} + +#[derive(Default)] +pub struct CfgSelectBranches { + /// All the conditional branches. + pub reachable: Vec<(MetaItemInner, TokenStream, Span)>, + /// The first wildcard `_ => { ... }` branch. + pub wildcard: Option<(Token, TokenStream, Span)>, + /// All branches after the first wildcard, including further wildcards. + /// These branches are kept for formatting. + pub unreachable: Vec<(CfgSelectPredicate, TokenStream, Span)>, +} + +pub fn parse_cfg_select<'a>(p: &mut Parser<'a>) -> PResult<'a, CfgSelectBranches> { + let mut branches = CfgSelectBranches::default(); + + while p.token != token::Eof { + if p.eat_keyword(exp!(Underscore)) { + let underscore = p.prev_token; + p.expect(exp!(FatArrow))?; + + let tts = p.parse_delimited_token_tree()?; + let span = underscore.span.to(p.token.span); + + match branches.wildcard { + None => branches.wildcard = Some((underscore, tts, span)), + Some(_) => { + branches.unreachable.push((CfgSelectPredicate::Wildcard(underscore), tts, span)) + } + } + } else { + let meta_item = p.parse_meta_item_inner()?; + p.expect(exp!(FatArrow))?; + + let tts = p.parse_delimited_token_tree()?; + let span = meta_item.span().to(p.token.span); + + match branches.wildcard { + None => branches.reachable.push((meta_item, tts, span)), + Some(_) => { + branches.unreachable.push((CfgSelectPredicate::Cfg(meta_item), tts, span)) + } + } + } + } + + Ok(branches) +} diff --git a/compiler/rustc_attr_parsing/src/attributes/mod.rs b/compiler/rustc_attr_parsing/src/attributes/mod.rs index 093969586596d..65e0957ca9005 100644 --- a/compiler/rustc_attr_parsing/src/attributes/mod.rs +++ b/compiler/rustc_attr_parsing/src/attributes/mod.rs @@ -33,6 +33,7 @@ pub(crate) mod allow_unstable; pub(crate) mod body; pub(crate) mod cfg; pub(crate) mod cfg_old; +pub(crate) mod cfg_select; pub(crate) mod codegen_attrs; pub(crate) mod confusables; pub(crate) mod crate_level; diff --git a/compiler/rustc_attr_parsing/src/lib.rs b/compiler/rustc_attr_parsing/src/lib.rs index 473935abdcd50..046cca4c742b0 100644 --- a/compiler/rustc_attr_parsing/src/lib.rs +++ b/compiler/rustc_attr_parsing/src/lib.rs @@ -106,6 +106,7 @@ pub use attributes::cfg::{ CFG_TEMPLATE, EvalConfigResult, eval_config_entry, parse_cfg, parse_cfg_attr, parse_cfg_entry, }; pub use attributes::cfg_old::*; +pub use attributes::cfg_select::*; pub use attributes::util::{is_builtin_attr, is_doc_alias_attrs_contain_symbol, parse_version}; pub use context::{Early, Late, OmitDoc, ShouldEmit}; pub use interface::AttributeParser; diff --git a/compiler/rustc_builtin_macros/src/cfg_select.rs b/compiler/rustc_builtin_macros/src/cfg_select.rs index f22d5f255c292..9bb222b1b87a2 100644 --- a/compiler/rustc_builtin_macros/src/cfg_select.rs +++ b/compiler/rustc_builtin_macros/src/cfg_select.rs @@ -1,7 +1,7 @@ use rustc_ast::tokenstream::TokenStream; use rustc_attr_parsing as attr; +use rustc_attr_parsing::{CfgSelectBranches, CfgSelectPredicate, parse_cfg_select}; use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacroExpanderResult}; -use rustc_parse::parser::cfg_select::{CfgSelectBranches, CfgSelectPredicate, parse_cfg_select}; use rustc_span::{Ident, Span, sym}; use crate::errors::{CfgSelectNoMatches, CfgSelectUnreachable}; diff --git a/compiler/rustc_parse/src/parser/cfg_select.rs b/compiler/rustc_parse/src/parser/cfg_select.rs index 08a71db4de853..9692d2c708938 100644 --- a/compiler/rustc_parse/src/parser/cfg_select.rs +++ b/compiler/rustc_parse/src/parser/cfg_select.rs @@ -1,83 +1,34 @@ -use rustc_ast::token::Token; +use rustc_ast::token; use rustc_ast::tokenstream::{TokenStream, TokenTree}; use rustc_ast::util::classify; -use rustc_ast::{MetaItemInner, token}; use rustc_errors::PResult; -use rustc_span::Span; use crate::exp; use crate::parser::{AttrWrapper, ForceCollect, Parser, Restrictions, Trailing, UsePreAttrPos}; -pub enum CfgSelectPredicate { - Cfg(MetaItemInner), - Wildcard(Token), -} - -#[derive(Default)] -pub struct CfgSelectBranches { - /// All the conditional branches. - pub reachable: Vec<(MetaItemInner, TokenStream, Span)>, - /// The first wildcard `_ => { ... }` branch. - pub wildcard: Option<(Token, TokenStream, Span)>, - /// All branches after the first wildcard, including further wildcards. - /// These branches are kept for formatting. - pub unreachable: Vec<(CfgSelectPredicate, TokenStream, Span)>, -} - -/// Parses a `TokenTree` consisting either of `{ /* ... */ }` (and strip the braces) or an -/// expression followed by a comma (and strip the comma). -fn parse_token_tree<'a>(p: &mut Parser<'a>) -> PResult<'a, TokenStream> { - if p.token == token::OpenBrace { - // Strip the outer '{' and '}'. - match p.parse_token_tree() { - TokenTree::Token(..) => unreachable!("because of the expect above"), - TokenTree::Delimited(.., tts) => return Ok(tts), - } - } - let expr = p.collect_tokens(None, AttrWrapper::empty(), ForceCollect::Yes, |p, _| { - p.parse_expr_res(Restrictions::STMT_EXPR, AttrWrapper::empty()) - .map(|(expr, _)| (expr, Trailing::No, UsePreAttrPos::No)) - })?; - if !classify::expr_is_complete(&expr) && p.token != token::CloseBrace && p.token != token::Eof { - p.expect(exp!(Comma))?; - } else { - let _ = p.eat(exp!(Comma)); - } - Ok(TokenStream::from_ast(&expr)) -} - -pub fn parse_cfg_select<'a>(p: &mut Parser<'a>) -> PResult<'a, CfgSelectBranches> { - let mut branches = CfgSelectBranches::default(); - - while p.token != token::Eof { - if p.eat_keyword(exp!(Underscore)) { - let underscore = p.prev_token; - p.expect(exp!(FatArrow))?; - - let tts = parse_token_tree(p)?; - let span = underscore.span.to(p.token.span); - - match branches.wildcard { - None => branches.wildcard = Some((underscore, tts, span)), - Some(_) => { - branches.unreachable.push((CfgSelectPredicate::Wildcard(underscore), tts, span)) - } +impl<'a> Parser<'a> { + /// Parses a `TokenTree` consisting either of `{ /* ... */ }` (and strip the braces) or an + /// expression followed by a comma (and strip the comma). + pub fn parse_delimited_token_tree(&mut self) -> PResult<'a, TokenStream> { + if self.token == token::OpenBrace { + // Strip the outer '{' and '}'. + match self.parse_token_tree() { + TokenTree::Token(..) => unreachable!("because of the expect above"), + TokenTree::Delimited(.., tts) => return Ok(tts), } + } + let expr = self.collect_tokens(None, AttrWrapper::empty(), ForceCollect::Yes, |p, _| { + p.parse_expr_res(Restrictions::STMT_EXPR, AttrWrapper::empty()) + .map(|(expr, _)| (expr, Trailing::No, UsePreAttrPos::No)) + })?; + if !classify::expr_is_complete(&expr) + && self.token != token::CloseBrace + && self.token != token::Eof + { + self.expect(exp!(Comma))?; } else { - let meta_item = p.parse_meta_item_inner()?; - p.expect(exp!(FatArrow))?; - - let tts = parse_token_tree(p)?; - let span = meta_item.span().to(p.token.span); - - match branches.wildcard { - None => branches.reachable.push((meta_item, tts, span)), - Some(_) => { - branches.unreachable.push((CfgSelectPredicate::Cfg(meta_item), tts, span)) - } - } + let _ = self.eat(exp!(Comma)); } + Ok(TokenStream::from_ast(&expr)) } - - Ok(branches) } From c111ccc45d301323e738e8fbc0e0f4b8c06d773c Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Sat, 8 Nov 2025 21:31:34 +0100 Subject: [PATCH 2/3] Add more tests for `cfg_select` parsing Signed-off-by: Jonathan Brouwer --- tests/ui/macros/cfg_select.rs | 35 +++++++++++++++++ tests/ui/macros/cfg_select.stderr | 64 ++++++++++++++++++++++++++++++- 2 files changed, 98 insertions(+), 1 deletion(-) diff --git a/tests/ui/macros/cfg_select.rs b/tests/ui/macros/cfg_select.rs index 9241141ef9a6c..54011f13df8c6 100644 --- a/tests/ui/macros/cfg_select.rs +++ b/tests/ui/macros/cfg_select.rs @@ -60,3 +60,38 @@ cfg_select! { cfg_select! {} //~^ ERROR none of the predicates in this `cfg_select` evaluated to true + +cfg_select! { + => {} + //~^ ERROR expected unsuffixed literal, found `=>` +} + +cfg_select! { + () => {} + //~^ ERROR expected unsuffixed literal, found `(` +} + +cfg_select! { //~ ERROR none of the predicates in this `cfg_select` evaluated to true + "str" => {} + //~^ ERROR literal in `cfg` predicate value must be a boolean +} + +cfg_select! { + a::b => {} + //~^ ERROR `cfg` predicate key must be an identifier +} + +cfg_select! { //~ ERROR none of the predicates in this `cfg_select` evaluated to true + a() => {} + //~^ ERROR invalid predicate `a` [E0537] +} + +cfg_select! { + a + 1 => {} + //~^ ERROR expected one of `(`, `::`, `=>`, or `=`, found `+` +} + +cfg_select! { + cfg!() => {} + //~^ ERROR expected one of `(`, `::`, `=>`, or `=`, found `!` +} diff --git a/tests/ui/macros/cfg_select.stderr b/tests/ui/macros/cfg_select.stderr index 7280f35c16f93..78145a14649c6 100644 --- a/tests/ui/macros/cfg_select.stderr +++ b/tests/ui/macros/cfg_select.stderr @@ -21,5 +21,67 @@ error: none of the predicates in this `cfg_select` evaluated to true LL | cfg_select! {} | ^^^^^^^^^^^^^^ -error: aborting due to 2 previous errors; 1 warning emitted +error: expected unsuffixed literal, found `=>` + --> $DIR/cfg_select.rs:65:5 + | +LL | => {} + | ^^ + +error: expected unsuffixed literal, found `(` + --> $DIR/cfg_select.rs:70:5 + | +LL | () => {} + | ^ + +error[E0565]: literal in `cfg` predicate value must be a boolean + --> $DIR/cfg_select.rs:75:5 + | +LL | "str" => {} + | ^^^^^ + +error: none of the predicates in this `cfg_select` evaluated to true + --> $DIR/cfg_select.rs:74:1 + | +LL | / cfg_select! { +LL | | "str" => {} +LL | | +LL | | } + | |_^ + +error: `cfg` predicate key must be an identifier + --> $DIR/cfg_select.rs:80:5 + | +LL | a::b => {} + | ^^^^ + +error[E0537]: invalid predicate `a` + --> $DIR/cfg_select.rs:85:5 + | +LL | a() => {} + | ^^^ + +error: none of the predicates in this `cfg_select` evaluated to true + --> $DIR/cfg_select.rs:84:1 + | +LL | / cfg_select! { +LL | | a() => {} +LL | | +LL | | } + | |_^ + +error: expected one of `(`, `::`, `=>`, or `=`, found `+` + --> $DIR/cfg_select.rs:90:7 + | +LL | a + 1 => {} + | ^ expected one of `(`, `::`, `=>`, or `=` + +error: expected one of `(`, `::`, `=>`, or `=`, found `!` + --> $DIR/cfg_select.rs:95:8 + | +LL | cfg!() => {} + | ^ expected one of `(`, `::`, `=>`, or `=` + +error: aborting due to 11 previous errors; 1 warning emitted +Some errors have detailed explanations: E0537, E0565. +For more information about an error, try `rustc --explain E0537`. From 90f36afc1b06ed0a05a32fa4655c8558e72f1710 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Sat, 8 Nov 2025 21:43:58 +0100 Subject: [PATCH 3/3] Port `cfg_select!` to the new attribute parsing system Signed-off-by: Jonathan Brouwer --- .../src/attributes/cfg_select.rs | 62 ++++++++++++---- .../rustc_builtin_macros/src/cfg_select.rs | 74 ++++++++++--------- .../rustc_hir/src/attrs/data_structures.rs | 12 +++ tests/ui/macros/cfg_select.rs | 12 +-- tests/ui/macros/cfg_select.stderr | 34 +++------ 5 files changed, 113 insertions(+), 81 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/cfg_select.rs b/compiler/rustc_attr_parsing/src/attributes/cfg_select.rs index 7ee92d6926720..8006fb963b198 100644 --- a/compiler/rustc_attr_parsing/src/attributes/cfg_select.rs +++ b/compiler/rustc_attr_parsing/src/attributes/cfg_select.rs @@ -1,20 +1,26 @@ use rustc_ast::token::Token; use rustc_ast::tokenstream::TokenStream; -use rustc_ast::{MetaItemInner, token}; -use rustc_errors::PResult; +use rustc_ast::{AttrStyle, NodeId, token}; +use rustc_feature::{AttributeTemplate, Features}; +use rustc_hir::AttrPath; +use rustc_hir::attrs::CfgEntry; use rustc_parse::exp; use rustc_parse::parser::Parser; -use rustc_span::Span; +use rustc_session::Session; +use rustc_span::{ErrorGuaranteed, Ident, Span}; + +use crate::parser::MetaItemOrLitParser; +use crate::{AttributeParser, ParsedDescription, ShouldEmit, parse_cfg_entry}; pub enum CfgSelectPredicate { - Cfg(MetaItemInner), + Cfg(CfgEntry), Wildcard(Token), } #[derive(Default)] pub struct CfgSelectBranches { /// All the conditional branches. - pub reachable: Vec<(MetaItemInner, TokenStream, Span)>, + pub reachable: Vec<(CfgEntry, TokenStream, Span)>, /// The first wildcard `_ => { ... }` branch. pub wildcard: Option<(Token, TokenStream, Span)>, /// All branches after the first wildcard, including further wildcards. @@ -22,15 +28,20 @@ pub struct CfgSelectBranches { pub unreachable: Vec<(CfgSelectPredicate, TokenStream, Span)>, } -pub fn parse_cfg_select<'a>(p: &mut Parser<'a>) -> PResult<'a, CfgSelectBranches> { +pub fn parse_cfg_select( + p: &mut Parser<'_>, + sess: &Session, + features: Option<&Features>, + lint_node_id: NodeId, +) -> Result { let mut branches = CfgSelectBranches::default(); while p.token != token::Eof { if p.eat_keyword(exp!(Underscore)) { let underscore = p.prev_token; - p.expect(exp!(FatArrow))?; + p.expect(exp!(FatArrow)).map_err(|e| e.emit())?; - let tts = p.parse_delimited_token_tree()?; + let tts = p.parse_delimited_token_tree().map_err(|e| e.emit())?; let span = underscore.span.to(p.token.span); match branches.wildcard { @@ -40,17 +51,36 @@ pub fn parse_cfg_select<'a>(p: &mut Parser<'a>) -> PResult<'a, CfgSelectBranches } } } else { - let meta_item = p.parse_meta_item_inner()?; - p.expect(exp!(FatArrow))?; + let meta = MetaItemOrLitParser::parse_single(p, ShouldEmit::ErrorsAndLints) + .map_err(|diag| diag.emit())?; + let cfg_span = meta.span(); + let cfg = AttributeParser::parse_single_args( + sess, + cfg_span, + cfg_span, + AttrStyle::Inner, + AttrPath { + segments: vec![Ident::from_str("cfg_select")].into_boxed_slice(), + span: cfg_span, + }, + ParsedDescription::Macro, + cfg_span, + lint_node_id, + features, + ShouldEmit::ErrorsAndLints, + &meta, + parse_cfg_entry, + &AttributeTemplate::default(), + )?; + + p.expect(exp!(FatArrow)).map_err(|e| e.emit())?; - let tts = p.parse_delimited_token_tree()?; - let span = meta_item.span().to(p.token.span); + let tts = p.parse_delimited_token_tree().map_err(|e| e.emit())?; + let span = cfg_span.to(p.token.span); match branches.wildcard { - None => branches.reachable.push((meta_item, tts, span)), - Some(_) => { - branches.unreachable.push((CfgSelectPredicate::Cfg(meta_item), tts, span)) - } + None => branches.reachable.push((cfg, tts, span)), + Some(_) => branches.unreachable.push((CfgSelectPredicate::Cfg(cfg), tts, span)), } } } diff --git a/compiler/rustc_builtin_macros/src/cfg_select.rs b/compiler/rustc_builtin_macros/src/cfg_select.rs index 9bb222b1b87a2..f2e454c3d4373 100644 --- a/compiler/rustc_builtin_macros/src/cfg_select.rs +++ b/compiler/rustc_builtin_macros/src/cfg_select.rs @@ -1,6 +1,8 @@ use rustc_ast::tokenstream::TokenStream; use rustc_attr_parsing as attr; -use rustc_attr_parsing::{CfgSelectBranches, CfgSelectPredicate, parse_cfg_select}; +use rustc_attr_parsing::{ + CfgSelectBranches, CfgSelectPredicate, EvalConfigResult, ShouldEmit, parse_cfg_select, +}; use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacroExpanderResult}; use rustc_span::{Ident, Span, sym}; @@ -9,11 +11,11 @@ use crate::errors::{CfgSelectNoMatches, CfgSelectUnreachable}; /// Selects the first arm whose predicate evaluates to true. fn select_arm(ecx: &ExtCtxt<'_>, branches: CfgSelectBranches) -> Option<(TokenStream, Span)> { for (cfg, tt, arm_span) in branches.reachable { - if attr::cfg_matches( - &cfg, + if let EvalConfigResult::True = attr::eval_config_entry( &ecx.sess, + &cfg, ecx.current_expansion.lint_node_id, - Some(ecx.ecfg.features), + ShouldEmit::ErrorsAndLints, ) { return Some((tt, arm_span)); } @@ -27,37 +29,41 @@ pub(super) fn expand_cfg_select<'cx>( sp: Span, tts: TokenStream, ) -> MacroExpanderResult<'cx> { - ExpandResult::Ready(match parse_cfg_select(&mut ecx.new_parser_from_tts(tts)) { - Ok(branches) => { - if let Some((underscore, _, _)) = branches.wildcard { - // Warn for every unreachable predicate. We store the fully parsed branch for rustfmt. - for (predicate, _, _) in &branches.unreachable { - let span = match predicate { - CfgSelectPredicate::Wildcard(underscore) => underscore.span, - CfgSelectPredicate::Cfg(cfg) => cfg.span(), - }; - let err = CfgSelectUnreachable { span, wildcard_span: underscore.span }; - ecx.dcx().emit_warn(err); + ExpandResult::Ready( + match parse_cfg_select( + &mut ecx.new_parser_from_tts(tts), + ecx.sess, + Some(ecx.ecfg.features), + ecx.current_expansion.lint_node_id, + ) { + Ok(branches) => { + if let Some((underscore, _, _)) = branches.wildcard { + // Warn for every unreachable predicate. We store the fully parsed branch for rustfmt. + for (predicate, _, _) in &branches.unreachable { + let span = match predicate { + CfgSelectPredicate::Wildcard(underscore) => underscore.span, + CfgSelectPredicate::Cfg(cfg) => cfg.span(), + }; + let err = CfgSelectUnreachable { span, wildcard_span: underscore.span }; + ecx.dcx().emit_warn(err); + } } - } - if let Some((tts, arm_span)) = select_arm(ecx, branches) { - return ExpandResult::from_tts( - ecx, - tts, - sp, - arm_span, - Ident::with_dummy_span(sym::cfg_select), - ); - } else { - // Emit a compiler error when none of the predicates matched. - let guar = ecx.dcx().emit_err(CfgSelectNoMatches { span: sp }); - DummyResult::any(sp, guar) + if let Some((tts, arm_span)) = select_arm(ecx, branches) { + return ExpandResult::from_tts( + ecx, + tts, + sp, + arm_span, + Ident::with_dummy_span(sym::cfg_select), + ); + } else { + // Emit a compiler error when none of the predicates matched. + let guar = ecx.dcx().emit_err(CfgSelectNoMatches { span: sp }); + DummyResult::any(sp, guar) + } } - } - Err(err) => { - let guar = err.emit(); - DummyResult::any(sp, guar) - } - }) + Err(guar) => DummyResult::any(sp, guar), + }, + ) } diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs index b1b872808c8f8..592825cf4220c 100644 --- a/compiler/rustc_hir/src/attrs/data_structures.rs +++ b/compiler/rustc_hir/src/attrs/data_structures.rs @@ -194,6 +194,18 @@ pub enum CfgEntry { Version(Option, Span), } +impl CfgEntry { + pub fn span(&self) -> Span { + let (CfgEntry::All(_, span) + | CfgEntry::Any(_, span) + | CfgEntry::Not(_, span) + | CfgEntry::Bool(_, span) + | CfgEntry::NameValue { span, .. } + | CfgEntry::Version(_, span)) = self; + *span + } +} + /// Possible values for the `#[linkage]` attribute, allowing to specify the /// linkage type for a `MonoItem`. /// diff --git a/tests/ui/macros/cfg_select.rs b/tests/ui/macros/cfg_select.rs index 54011f13df8c6..2a627cc05b93b 100644 --- a/tests/ui/macros/cfg_select.rs +++ b/tests/ui/macros/cfg_select.rs @@ -63,25 +63,25 @@ cfg_select! {} cfg_select! { => {} - //~^ ERROR expected unsuffixed literal, found `=>` + //~^ ERROR expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found `=>` } cfg_select! { () => {} - //~^ ERROR expected unsuffixed literal, found `(` + //~^ ERROR expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found `(` } -cfg_select! { //~ ERROR none of the predicates in this `cfg_select` evaluated to true +cfg_select! { "str" => {} - //~^ ERROR literal in `cfg` predicate value must be a boolean + //~^ ERROR malformed `cfg_select` macro input [E0539] } cfg_select! { a::b => {} - //~^ ERROR `cfg` predicate key must be an identifier + //~^ ERROR malformed `cfg_select` macro input [E0539] } -cfg_select! { //~ ERROR none of the predicates in this `cfg_select` evaluated to true +cfg_select! { a() => {} //~^ ERROR invalid predicate `a` [E0537] } diff --git a/tests/ui/macros/cfg_select.stderr b/tests/ui/macros/cfg_select.stderr index 78145a14649c6..3a5d2b0a1e1ee 100644 --- a/tests/ui/macros/cfg_select.stderr +++ b/tests/ui/macros/cfg_select.stderr @@ -21,38 +21,31 @@ error: none of the predicates in this `cfg_select` evaluated to true LL | cfg_select! {} | ^^^^^^^^^^^^^^ -error: expected unsuffixed literal, found `=>` +error: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found `=>` --> $DIR/cfg_select.rs:65:5 | LL | => {} | ^^ -error: expected unsuffixed literal, found `(` +error: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found `(` --> $DIR/cfg_select.rs:70:5 | LL | () => {} | ^ -error[E0565]: literal in `cfg` predicate value must be a boolean +error[E0539]: malformed `cfg_select` macro input --> $DIR/cfg_select.rs:75:5 | LL | "str" => {} - | ^^^^^ - -error: none of the predicates in this `cfg_select` evaluated to true - --> $DIR/cfg_select.rs:74:1 + | ^^^^^ expected a valid identifier here | -LL | / cfg_select! { -LL | | "str" => {} -LL | | -LL | | } - | |_^ -error: `cfg` predicate key must be an identifier +error[E0539]: malformed `cfg_select` macro input --> $DIR/cfg_select.rs:80:5 | LL | a::b => {} - | ^^^^ + | ^^^^ expected a valid identifier here + | error[E0537]: invalid predicate `a` --> $DIR/cfg_select.rs:85:5 @@ -60,15 +53,6 @@ error[E0537]: invalid predicate `a` LL | a() => {} | ^^^ -error: none of the predicates in this `cfg_select` evaluated to true - --> $DIR/cfg_select.rs:84:1 - | -LL | / cfg_select! { -LL | | a() => {} -LL | | -LL | | } - | |_^ - error: expected one of `(`, `::`, `=>`, or `=`, found `+` --> $DIR/cfg_select.rs:90:7 | @@ -81,7 +65,7 @@ error: expected one of `(`, `::`, `=>`, or `=`, found `!` LL | cfg!() => {} | ^ expected one of `(`, `::`, `=>`, or `=` -error: aborting due to 11 previous errors; 1 warning emitted +error: aborting due to 9 previous errors; 1 warning emitted -Some errors have detailed explanations: E0537, E0565. +Some errors have detailed explanations: E0537, E0539. For more information about an error, try `rustc --explain E0537`.