diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs index 762ebc47ca9d0..37f70c218698c 100644 --- a/compiler/rustc_attr/src/builtin.rs +++ b/compiler/rustc_attr/src/builtin.rs @@ -523,7 +523,7 @@ pub struct Condition { /// Tests if a cfg-pattern matches the cfg set pub fn cfg_matches( - cfg: &ast::MetaItem, + cfg: &ast::NestedMetaItem, sess: &Session, lint_node_id: NodeId, features: Option<&Features>, @@ -594,12 +594,26 @@ pub fn parse_version(s: Symbol) -> Option { /// Evaluate a cfg-like condition (with `any` and `all`), using `eval` to /// evaluate individual items. pub fn eval_condition( - cfg: &ast::MetaItem, + cfg: &ast::NestedMetaItem, sess: &Session, features: Option<&Features>, eval: &mut impl FnMut(Condition) -> bool, ) -> bool { let dcx = sess.dcx(); + + let cfg = match cfg { + ast::NestedMetaItem::MetaItem(meta_item) => meta_item, + _ => { + dcx.emit_err(session_diagnostics::UnsupportedLiteral { + span: cfg.span(), + reason: UnsupportedLiteralReason::Generic, + is_bytestr: false, + start_point_span: sess.source_map().start_point(cfg.span()), + }); + return false; + } + }; + match &cfg.kind { ast::MetaItemKind::List(mis) if cfg.name_or_empty() == sym::version => { try_gate_cfg(sym::version, cfg.span, sess, features); @@ -653,23 +667,19 @@ pub fn eval_condition( .iter() // We don't use any() here, because we want to evaluate all cfg condition // as eval_condition can (and does) extra checks - .fold(false, |res, mi| { - res | eval_condition(mi.meta_item().unwrap(), sess, features, eval) - }), + .fold(false, |res, mi| res | eval_condition(mi, sess, features, eval)), sym::all => mis .iter() // We don't use all() here, because we want to evaluate all cfg condition // as eval_condition can (and does) extra checks - .fold(true, |res, mi| { - res & eval_condition(mi.meta_item().unwrap(), sess, features, eval) - }), + .fold(true, |res, mi| res & eval_condition(mi, sess, features, eval)), sym::not => { let [mi] = mis.as_slice() else { dcx.emit_err(session_diagnostics::ExpectedOneCfgPattern { span: cfg.span }); return false; }; - !eval_condition(mi.meta_item().unwrap(), sess, features, eval) + !eval_condition(mi, sess, features, eval) } sym::target => { if let Some(features) = features @@ -690,7 +700,12 @@ pub fn eval_condition( seg.ident.name = Symbol::intern(&format!("target_{}", seg.ident.name)); } - res & eval_condition(&mi, sess, features, eval) + res & eval_condition( + &ast::NestedMetaItem::MetaItem(mi), + sess, + features, + eval, + ) }) } _ => { diff --git a/compiler/rustc_builtin_macros/src/cfg.rs b/compiler/rustc_builtin_macros/src/cfg.rs index cf1d5c68eadd0..940c94b1cfc89 100644 --- a/compiler/rustc_builtin_macros/src/cfg.rs +++ b/compiler/rustc_builtin_macros/src/cfg.rs @@ -6,7 +6,6 @@ use rustc_ast::token; use rustc_ast::tokenstream::TokenStream; use rustc_errors::PResult; use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacEager, MacroExpanderResult}; -use rustc_parse::parser::attr::AllowLeadingUnsafe; use rustc_span::Span; use {rustc_ast as ast, rustc_attr as attr}; @@ -36,14 +35,18 @@ pub(crate) fn expand_cfg( }) } -fn parse_cfg<'a>(cx: &ExtCtxt<'a>, span: Span, tts: TokenStream) -> PResult<'a, ast::MetaItem> { +fn parse_cfg<'a>( + cx: &ExtCtxt<'a>, + span: Span, + tts: TokenStream, +) -> PResult<'a, ast::NestedMetaItem> { let mut p = cx.new_parser_from_tts(tts); if p.token == token::Eof { return Err(cx.dcx().create_err(errors::RequiresCfgPattern { span })); } - let cfg = p.parse_meta_item(AllowLeadingUnsafe::No)?; + let cfg = p.parse_meta_item_inner()?; let _ = p.eat(&token::Comma); diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index 162d14272a555..3129b9ac20344 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -156,7 +156,7 @@ pub struct NativeLib { pub kind: NativeLibKind, pub name: Symbol, pub filename: Option, - pub cfg: Option, + pub cfg: Option, pub verbatim: bool, pub dll_imports: Vec, } diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs index 3208837427736..8ea4f901368ec 100644 --- a/compiler/rustc_expand/src/config.rs +++ b/compiler/rustc_expand/src/config.rs @@ -5,7 +5,9 @@ use rustc_ast::token::{Delimiter, Token, TokenKind}; use rustc_ast::tokenstream::{ AttrTokenStream, AttrTokenTree, LazyAttrTokenStream, Spacing, TokenTree, }; -use rustc_ast::{self as ast, AttrStyle, Attribute, HasAttrs, HasTokens, MetaItem, NodeId}; +use rustc_ast::{ + self as ast, AttrStyle, Attribute, HasAttrs, HasTokens, MetaItem, NestedMetaItem, NodeId, +}; use rustc_attr as attr; use rustc_data_structures::flat_map_in_place::FlatMapInPlace; use rustc_feature::{ @@ -449,7 +451,7 @@ impl<'a> StripUnconfigured<'a> { } } -pub fn parse_cfg<'a>(meta_item: &'a MetaItem, sess: &Session) -> Option<&'a MetaItem> { +pub fn parse_cfg<'a>(meta_item: &'a MetaItem, sess: &Session) -> Option<&'a NestedMetaItem> { let span = meta_item.span; match meta_item.meta_item_list() { None => { @@ -464,9 +466,9 @@ pub fn parse_cfg<'a>(meta_item: &'a MetaItem, sess: &Session) -> Option<&'a Meta sess.dcx().emit_err(InvalidCfg::MultiplePredicates { span: l.span() }); None } - Some([single]) => match single.meta_item() { - Some(meta_item) => Some(meta_item), - None => { + Some([single]) => match single.is_meta_item() { + true => Some(single), + false => { sess.dcx().emit_err(InvalidCfg::PredicateLiteral { span: single.span() }); None } diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs index 82b907d2501fe..373b109189e7b 100644 --- a/compiler/rustc_metadata/src/native_libs.rs +++ b/compiler/rustc_metadata/src/native_libs.rs @@ -1,7 +1,7 @@ use std::ops::ControlFlow; use std::path::{Path, PathBuf}; -use rustc_ast::{CRATE_NODE_ID, NestedMetaItem}; +use rustc_ast::CRATE_NODE_ID; use rustc_attr as attr; use rustc_data_structures::fx::FxHashSet; use rustc_middle::query::LocalCrate; @@ -304,7 +304,12 @@ impl<'tcx> Collector<'tcx> { sess.dcx().emit_err(errors::LinkCfgForm { span: item.span() }); continue; }; - let [NestedMetaItem::MetaItem(link_cfg)] = link_cfg else { + let [link_cfg] = link_cfg else { + sess.dcx() + .emit_err(errors::LinkCfgSinglePredicate { span: item.span() }); + continue; + }; + if !link_cfg.is_meta_item() { sess.dcx() .emit_err(errors::LinkCfgSinglePredicate { span: item.span() }); continue; diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs index f7a8b8780edc4..da02f98d0e5bd 100644 --- a/compiler/rustc_parse/src/lib.rs +++ b/compiler/rustc_parse/src/lib.rs @@ -18,7 +18,7 @@ use std::path::Path; use rustc_ast as ast; use rustc_ast::tokenstream::TokenStream; -use rustc_ast::{AttrItem, Attribute, MetaItem, token}; +use rustc_ast::{AttrItem, Attribute, NestedMetaItem, token}; use rustc_ast_pretty::pprust; use rustc_data_structures::sync::Lrc; use rustc_errors::{Diag, FatalError, PResult}; @@ -160,7 +160,7 @@ pub fn fake_token_stream_for_crate(psess: &ParseSess, krate: &ast::Crate) -> Tok pub fn parse_cfg_attr( cfg_attr: &Attribute, psess: &ParseSess, -) -> Option<(MetaItem, Vec<(AttrItem, Span)>)> { +) -> Option<(NestedMetaItem, Vec<(AttrItem, Span)>)> { const CFG_ATTR_GRAMMAR_HELP: &str = "#[cfg_attr(condition, attribute, other_attribute, ...)]"; const CFG_ATTR_NOTE_REF: &str = "for more information, visit \ "; diff --git a/compiler/rustc_parse/src/parser/attr.rs b/compiler/rustc_parse/src/parser/attr.rs index c65cf3f40f658..4aa56cb7624a6 100644 --- a/compiler/rustc_parse/src/parser/attr.rs +++ b/compiler/rustc_parse/src/parser/attr.rs @@ -356,8 +356,10 @@ impl<'a> Parser<'a> { } /// Parses `cfg_attr(pred, attr_item_list)` where `attr_item_list` is comma-delimited. - pub fn parse_cfg_attr(&mut self) -> PResult<'a, (ast::MetaItem, Vec<(ast::AttrItem, Span)>)> { - let cfg_predicate = self.parse_meta_item(AllowLeadingUnsafe::No)?; + pub fn parse_cfg_attr( + &mut self, + ) -> PResult<'a, (ast::NestedMetaItem, Vec<(ast::AttrItem, Span)>)> { + let cfg_predicate = self.parse_meta_item_inner()?; self.expect(&token::Comma)?; // Presumably, the majority of the time there will only be one attr. @@ -452,7 +454,7 @@ impl<'a> Parser<'a> { /// ```ebnf /// MetaItemInner = UNSUFFIXED_LIT | MetaItem ; /// ``` - fn parse_meta_item_inner(&mut self) -> PResult<'a, ast::NestedMetaItem> { + pub fn parse_meta_item_inner(&mut self) -> PResult<'a, ast::NestedMetaItem> { match self.parse_unsuffixed_meta_item_lit() { Ok(lit) => return Ok(ast::NestedMetaItem::Lit(lit)), Err(err) => err.cancel(), // we provide a better error below diff --git a/compiler/rustc_session/src/cstore.rs b/compiler/rustc_session/src/cstore.rs index 66ad70d8d18be..b936a299b0973 100644 --- a/compiler/rustc_session/src/cstore.rs +++ b/compiler/rustc_session/src/cstore.rs @@ -72,7 +72,7 @@ pub struct NativeLib { pub name: Symbol, /// If packed_bundled_libs enabled, actual filename of library is stored. pub filename: Option, - pub cfg: Option, + pub cfg: Option, pub foreign_module: Option, pub verbatim: Option, pub dll_imports: Vec, diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs index 2c7ca50f9549c..f2efc5ee47d2b 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs @@ -1,7 +1,7 @@ use std::iter; use std::path::PathBuf; -use rustc_ast::{AttrArgs, AttrArgsEq, AttrKind, Attribute, MetaItem, NestedMetaItem}; +use rustc_ast::{AttrArgs, AttrArgsEq, AttrKind, Attribute, NestedMetaItem}; use rustc_data_structures::fx::FxHashMap; use rustc_errors::codes::*; use rustc_errors::{ErrorGuaranteed, struct_span_code_err}; @@ -282,7 +282,7 @@ pub struct OnUnimplementedFormatString { #[derive(Debug)] pub struct OnUnimplementedDirective { - pub condition: Option, + pub condition: Option, pub subcommands: Vec, pub message: Option, pub label: Option, @@ -413,9 +413,7 @@ impl<'tcx> OnUnimplementedDirective { } else { let cond = item_iter .next() - .ok_or_else(|| tcx.dcx().emit_err(EmptyOnClauseInOnUnimplemented { span }))? - .meta_item() - .ok_or_else(|| tcx.dcx().emit_err(InvalidOnClauseInOnUnimplemented { span }))?; + .ok_or_else(|| tcx.dcx().emit_err(EmptyOnClauseInOnUnimplemented { span }))?; attr::eval_condition(cond, &tcx.sess, Some(tcx.features()), &mut |cfg| { if let Some(value) = cfg.value && let Err(guar) = parse_value(value, cfg.span) @@ -558,8 +556,8 @@ impl<'tcx> OnUnimplementedDirective { IgnoredDiagnosticOption::maybe_emit_warning( tcx, item_def_id, - directive.condition.as_ref().map(|i| i.span), - aggr.condition.as_ref().map(|i| i.span), + directive.condition.as_ref().map(|i| i.span()), + aggr.condition.as_ref().map(|i| i.span()), "condition", ); IgnoredDiagnosticOption::maybe_emit_warning( diff --git a/tests/ui/macros/cfg.rs b/tests/ui/macros/cfg.rs index 2aac50a9d011a..387cc0ba8e25c 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 expected identifier + cfg!(123); //~ ERROR unsupported literal cfg!(foo = 123); //~ ERROR literal in `cfg` predicate value must be a string cfg!(foo, bar); //~ ERROR expected 1 cfg-pattern } diff --git a/tests/ui/macros/cfg.stderr b/tests/ui/macros/cfg.stderr index 2633d5f720d70..5c21497dc5dd6 100644 --- a/tests/ui/macros/cfg.stderr +++ b/tests/ui/macros/cfg.stderr @@ -6,11 +6,11 @@ LL | cfg!(); | = note: this error originates in the macro `cfg` (in Nightly builds, run with -Z macro-backtrace for more info) -error: expected identifier, found `123` +error[E0565]: unsupported literal --> $DIR/cfg.rs:3:10 | LL | cfg!(123); - | ^^^ expected identifier + | ^^^ error[E0565]: literal in `cfg` predicate value must be a string --> $DIR/cfg.rs:4:16