diff --git a/compiler/rustc_attr_parsing/src/attributes/cfg.rs b/compiler/rustc_attr_parsing/src/attributes/cfg.rs index dab9e7666c23a..47b46cd69d84c 100644 --- a/compiler/rustc_attr_parsing/src/attributes/cfg.rs +++ b/compiler/rustc_attr_parsing/src/attributes/cfg.rs @@ -12,13 +12,14 @@ use rustc_session::config::ExpectedValues; use rustc_session::lint::BuiltinLintDiag; use rustc_session::lint::builtin::UNEXPECTED_CFGS; use rustc_session::parse::{ParseSess, feature_err}; -use rustc_span::{Span, Symbol, sym}; +use rustc_span::{ErrorGuaranteed, Span, Symbol, sym}; use thin_vec::ThinVec; use crate::context::{AcceptContext, ShouldEmit, Stage}; use crate::parser::{ArgParser, MetaItemListParser, MetaItemOrLitParser, NameValueParser}; use crate::session_diagnostics::{ AttributeParseError, AttributeParseErrorReason, CfgAttrBadDelim, MetaBadDelimSugg, + ParsedDescription, }; use crate::{ AttributeParser, CfgMatchesLintEmitter, fluent_generated, parse_version, session_diagnostics, @@ -47,20 +48,19 @@ pub fn parse_cfg<'c, S: Stage>( cx.expected_single_argument(list.span); return None; }; - parse_cfg_entry(cx, single) + parse_cfg_entry(cx, single).ok() } -pub(crate) fn parse_cfg_entry( +pub fn parse_cfg_entry( cx: &mut AcceptContext<'_, '_, S>, item: &MetaItemOrLitParser<'_>, -) -> Option { - Some(match item { +) -> Result { + Ok(match item { MetaItemOrLitParser::MetaItemParser(meta) => match meta.args() { ArgParser::List(list) => match meta.path().word_sym() { Some(sym::not) => { let Some(single) = list.single() else { - cx.expected_single_argument(list.span); - return None; + return Err(cx.expected_single_argument(list.span)); }; CfgEntry::Not(Box::new(parse_cfg_entry(cx, single)?), list.span) } @@ -75,29 +75,24 @@ pub(crate) fn parse_cfg_entry( Some(sym::target) => parse_cfg_entry_target(cx, list, meta.span())?, Some(sym::version) => parse_cfg_entry_version(cx, list, meta.span())?, _ => { - cx.emit_err(session_diagnostics::InvalidPredicate { + return Err(cx.emit_err(session_diagnostics::InvalidPredicate { span: meta.span(), predicate: meta.path().to_string(), - }); - return None; + })); } }, a @ (ArgParser::NoArgs | ArgParser::NameValue(_)) => { let Some(name) = meta.path().word_sym() else { - cx.expected_identifier(meta.path().span()); - return None; + return Err(cx.expected_identifier(meta.path().span())); }; parse_name_value(name, meta.path().span(), a.name_value(), meta.span(), cx)? } }, MetaItemOrLitParser::Lit(lit) => match lit.kind { LitKind::Bool(b) => CfgEntry::Bool(b, lit.span), - _ => { - cx.expected_identifier(lit.span); - return None; - } + _ => return Err(cx.expected_identifier(lit.span)), }, - MetaItemOrLitParser::Err(_, _) => return None, + MetaItemOrLitParser::Err(_, err) => return Err(*err), }) } @@ -105,19 +100,22 @@ fn parse_cfg_entry_version( cx: &mut AcceptContext<'_, '_, S>, list: &MetaItemListParser<'_>, meta_span: Span, -) -> Option { +) -> Result { try_gate_cfg(sym::version, meta_span, cx.sess(), cx.features_option()); let Some(version) = list.single() else { - cx.emit_err(session_diagnostics::ExpectedSingleVersionLiteral { span: list.span }); - return None; + return Err( + cx.emit_err(session_diagnostics::ExpectedSingleVersionLiteral { span: list.span }) + ); }; let Some(version_lit) = version.lit() else { - cx.emit_err(session_diagnostics::ExpectedVersionLiteral { span: version.span() }); - return None; + return Err( + cx.emit_err(session_diagnostics::ExpectedVersionLiteral { span: version.span() }) + ); }; let Some(version_str) = version_lit.value_str() else { - cx.emit_err(session_diagnostics::ExpectedVersionLiteral { span: version_lit.span }); - return None; + return Err( + cx.emit_err(session_diagnostics::ExpectedVersionLiteral { span: version_lit.span }) + ); }; let min_version = parse_version(version_str).or_else(|| { @@ -127,14 +125,14 @@ fn parse_cfg_entry_version( None }); - Some(CfgEntry::Version(min_version, list.span)) + Ok(CfgEntry::Version(min_version, list.span)) } fn parse_cfg_entry_target( cx: &mut AcceptContext<'_, '_, S>, list: &MetaItemListParser<'_>, meta_span: Span, -) -> Option { +) -> Result { if let Some(features) = cx.features_option() && !features.cfg_target_compact() { @@ -161,17 +159,16 @@ fn parse_cfg_entry_target( // Then, parse it as a name-value item let Some(name) = sub_item.path().word_sym() else { - cx.expected_identifier(sub_item.path().span()); - return None; + return Err(cx.expected_identifier(sub_item.path().span())); }; let name = Symbol::intern(&format!("target_{name}")); - if let Some(cfg) = + if let Ok(cfg) = parse_name_value(name, sub_item.path().span(), Some(nv), sub_item.span(), cx) { result.push(cfg); } } - Some(CfgEntry::All(result, list.span)) + Ok(CfgEntry::All(result, list.span)) } fn parse_name_value( @@ -180,21 +177,22 @@ fn parse_name_value( value: Option<&NameValueParser>, span: Span, cx: &mut AcceptContext<'_, '_, S>, -) -> Option { +) -> Result { try_gate_cfg(name, span, cx.sess(), cx.features_option()); let value = match value { None => None, Some(value) => { let Some(value_str) = value.value_as_str() else { - cx.expected_string_literal(value.value_span, Some(value.value_as_lit())); - return None; + return Err( + cx.expected_string_literal(value.value_span, Some(value.value_as_lit())) + ); }; Some((value_str, value.value_span)) } }; - Some(CfgEntry::NameValue { name, name_span, value, span }) + Ok(CfgEntry::NameValue { name, name_span, value, span }) } pub fn eval_config_entry( @@ -355,7 +353,8 @@ pub fn parse_cfg_attr( span, attr_span: cfg_attr.span, template: CFG_ATTR_TEMPLATE, - attribute: AttrPath::from_ast(&cfg_attr.get_normal_item().path), + path: AttrPath::from_ast(&cfg_attr.get_normal_item().path), + description: ParsedDescription::Attribute, reason, suggestions: CFG_ATTR_TEMPLATE.suggestions(Some(cfg_attr.style), sym::cfg_attr), }); @@ -398,6 +397,7 @@ fn parse_cfg_attr_internal<'a>( .into_boxed_slice(), span: attribute.span, }, + ParsedDescription::Attribute, pred_span, CRATE_NODE_ID, features, @@ -406,7 +406,8 @@ fn parse_cfg_attr_internal<'a>( parse_cfg_entry, &CFG_ATTR_TEMPLATE, ) - .ok_or_else(|| { + .map_err(|_err: ErrorGuaranteed| { + // We have an `ErrorGuaranteed` so this delayed bug cannot fail, but we need a `Diag` for the `PResult` so we make one anyways let mut diag = sess.dcx().struct_err( "cfg_entry parsing failing with `ShouldEmit::ErrorsAndLints` should emit a error.", ); diff --git a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs index 797d04b914dd5..065ed8959fc75 100644 --- a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs @@ -396,7 +396,7 @@ impl LinkParser { ) .emit(); } - *cfg = parse_cfg_entry(cx, link_cfg); + *cfg = parse_cfg_entry(cx, link_cfg).ok(); true } diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index 15904fd7d3348..773527c96a3a9 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -71,7 +71,9 @@ use crate::attributes::traits::{ use crate::attributes::transparency::TransparencyParser; use crate::attributes::{AttributeParser as _, Combine, Single, WithoutArgs}; use crate::parser::{ArgParser, PathParser}; -use crate::session_diagnostics::{AttributeParseError, AttributeParseErrorReason, UnknownMetaItem}; +use crate::session_diagnostics::{ + AttributeParseError, AttributeParseErrorReason, ParsedDescription, UnknownMetaItem, +}; use crate::target_checking::AllowedTargets; type GroupType = LazyLock>; @@ -353,6 +355,10 @@ pub struct AcceptContext<'f, 'sess, S: Stage> { /// Whether it is an inner or outer attribute pub(crate) attr_style: AttrStyle, + /// A description of the thing we are parsing using this attribute parser + /// We are not only using these parsers for attributes, but also for macros such as the `cfg!()` macro. + pub(crate) parsed_description: ParsedDescription, + /// The expected structure of the attribute. /// /// Used in reporting errors to give a hint to users what the attribute *should* look like. @@ -431,7 +437,8 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> { span, attr_span: self.attr_span, template: self.template.clone(), - attribute: self.attr_path.clone(), + path: self.attr_path.clone(), + description: self.parsed_description, reason: AttributeParseErrorReason::ExpectedStringLiteral { byte_string: actual_literal.and_then(|i| { i.kind.is_bytestr().then(|| self.sess().source_map().start_point(i.span)) @@ -446,7 +453,8 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> { span, attr_span: self.attr_span, template: self.template.clone(), - attribute: self.attr_path.clone(), + path: self.attr_path.clone(), + description: self.parsed_description, reason: AttributeParseErrorReason::ExpectedIntegerLiteral, suggestions: self.suggestions(), }) @@ -457,7 +465,8 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> { span, attr_span: self.attr_span, template: self.template.clone(), - attribute: self.attr_path.clone(), + path: self.attr_path.clone(), + description: self.parsed_description, reason: AttributeParseErrorReason::ExpectedList, suggestions: self.suggestions(), }) @@ -468,7 +477,8 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> { span: args_span, attr_span: self.attr_span, template: self.template.clone(), - attribute: self.attr_path.clone(), + path: self.attr_path.clone(), + description: self.parsed_description, reason: AttributeParseErrorReason::ExpectedNoArgs, suggestions: self.suggestions(), }) @@ -480,7 +490,8 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> { span, attr_span: self.attr_span, template: self.template.clone(), - attribute: self.attr_path.clone(), + path: self.attr_path.clone(), + description: self.parsed_description, reason: AttributeParseErrorReason::ExpectedIdentifier, suggestions: self.suggestions(), }) @@ -493,7 +504,8 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> { span, attr_span: self.attr_span, template: self.template.clone(), - attribute: self.attr_path.clone(), + path: self.attr_path.clone(), + description: self.parsed_description, reason: AttributeParseErrorReason::ExpectedNameValue(name), suggestions: self.suggestions(), }) @@ -505,7 +517,8 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> { span, attr_span: self.attr_span, template: self.template.clone(), - attribute: self.attr_path.clone(), + path: self.attr_path.clone(), + description: self.parsed_description, reason: AttributeParseErrorReason::DuplicateKey(key), suggestions: self.suggestions(), }) @@ -518,7 +531,8 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> { span, attr_span: self.attr_span, template: self.template.clone(), - attribute: self.attr_path.clone(), + path: self.attr_path.clone(), + description: self.parsed_description, reason: AttributeParseErrorReason::UnexpectedLiteral, suggestions: self.suggestions(), }) @@ -529,7 +543,8 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> { span, attr_span: self.attr_span, template: self.template.clone(), - attribute: self.attr_path.clone(), + path: self.attr_path.clone(), + description: self.parsed_description, reason: AttributeParseErrorReason::ExpectedSingleArgument, suggestions: self.suggestions(), }) @@ -540,7 +555,8 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> { span, attr_span: self.attr_span, template: self.template.clone(), - attribute: self.attr_path.clone(), + path: self.attr_path.clone(), + description: self.parsed_description, reason: AttributeParseErrorReason::ExpectedAtLeastOneArgument, suggestions: self.suggestions(), }) @@ -556,7 +572,8 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> { span, attr_span: self.attr_span, template: self.template.clone(), - attribute: self.attr_path.clone(), + path: self.attr_path.clone(), + description: self.parsed_description, reason: AttributeParseErrorReason::ExpectedSpecificArgument { possibilities, strings: false, @@ -577,7 +594,8 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> { span, attr_span: self.attr_span, template: self.template.clone(), - attribute: self.attr_path.clone(), + path: self.attr_path.clone(), + description: self.parsed_description, reason: AttributeParseErrorReason::ExpectedSpecificArgument { possibilities, strings: false, @@ -597,7 +615,8 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> { span, attr_span: self.attr_span, template: self.template.clone(), - attribute: self.attr_path.clone(), + path: self.attr_path.clone(), + description: self.parsed_description, reason: AttributeParseErrorReason::ExpectedSpecificArgument { possibilities, strings: true, diff --git a/compiler/rustc_attr_parsing/src/interface.rs b/compiler/rustc_attr_parsing/src/interface.rs index 953b0ebfaf04f..b7a6a1ef6d667 100644 --- a/compiler/rustc_attr_parsing/src/interface.rs +++ b/compiler/rustc_attr_parsing/src/interface.rs @@ -12,6 +12,7 @@ use rustc_span::{DUMMY_SP, Span, Symbol, sym}; use crate::context::{AcceptContext, FinalizeContext, SharedContext, Stage}; use crate::parser::{ArgParser, MetaItemParser, PathParser}; +use crate::session_diagnostics::ParsedDescription; use crate::{Early, Late, OmitDoc, ShouldEmit}; /// Context created once, for example as part of the ast lowering @@ -145,6 +146,7 @@ impl<'sess> AttributeParser<'sess, Early> { normal_attr.item.span(), attr.style, path.get_attribute_path(), + ParsedDescription::Attribute, target_span, target_node_id, features, @@ -163,14 +165,15 @@ impl<'sess> AttributeParser<'sess, Early> { inner_span: Span, attr_style: AttrStyle, attr_path: AttrPath, + parsed_description: ParsedDescription, target_span: Span, target_node_id: NodeId, features: Option<&'sess Features>, emit_errors: ShouldEmit, args: &I, - parse_fn: fn(cx: &mut AcceptContext<'_, '_, Early>, item: &I) -> Option, + parse_fn: fn(cx: &mut AcceptContext<'_, '_, Early>, item: &I) -> T, template: &AttributeTemplate, - ) -> Option { + ) -> T { let mut parser = Self { features, tools: Vec::new(), @@ -190,6 +193,7 @@ impl<'sess> AttributeParser<'sess, Early> { attr_span, inner_span, attr_style, + parsed_description, template, attr_path, }; @@ -310,6 +314,7 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> { attr_span: lower_span(attr.span), inner_span: lower_span(attr.get_normal_item().span()), attr_style: attr.style, + parsed_description: ParsedDescription::Attribute, template: &accept.template, attr_path: path.get_attribute_path(), }; diff --git a/compiler/rustc_attr_parsing/src/lib.rs b/compiler/rustc_attr_parsing/src/lib.rs index bcd0d674c75f1..2e0c5be587bba 100644 --- a/compiler/rustc_attr_parsing/src/lib.rs +++ b/compiler/rustc_attr_parsing/src/lib.rs @@ -106,12 +106,13 @@ 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}; pub use context::{Early, Late, OmitDoc, ShouldEmit}; pub use interface::AttributeParser; pub use lints::emit_attribute_lint; +pub use session_diagnostics::ParsedDescription; rustc_fluent_macro::fluent_messages! { "../messages.ftl" } diff --git a/compiler/rustc_attr_parsing/src/session_diagnostics.rs b/compiler/rustc_attr_parsing/src/session_diagnostics.rs index 82bd29218313e..8d783503f7be0 100644 --- a/compiler/rustc_attr_parsing/src/session_diagnostics.rs +++ b/compiler/rustc_attr_parsing/src/session_diagnostics.rs @@ -610,20 +610,35 @@ pub(crate) enum AttributeParseErrorReason<'a> { ExpectedIdentifier, } +/// A description of a thing that can be parsed using an attribute parser. +#[derive(Copy, Clone)] +pub enum ParsedDescription { + /// Used when parsing attributes. + Attribute, + /// Used when parsing some macros, such as the `cfg!()` macro. + Macro, +} + pub(crate) struct AttributeParseError<'a> { pub(crate) span: Span, pub(crate) attr_span: Span, pub(crate) template: AttributeTemplate, - pub(crate) attribute: AttrPath, + pub(crate) path: AttrPath, + pub(crate) description: ParsedDescription, pub(crate) reason: AttributeParseErrorReason<'a>, pub(crate) suggestions: Vec, } impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for AttributeParseError<'_> { fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> { - let name = self.attribute.to_string(); + let name = self.path.to_string(); + + let description = match self.description { + ParsedDescription::Attribute => "attribute", + ParsedDescription::Macro => "macro", + }; - let mut diag = Diag::new(dcx, level, format!("malformed `{name}` attribute input")); + let mut diag = Diag::new(dcx, level, format!("malformed `{name}` {description} input")); diag.span(self.attr_span); diag.code(E0539); match self.reason { @@ -724,12 +739,12 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for AttributeParseError<'_> { diag.span_label( self.span, format!( - "this attribute is only valid with {quote}{x}{quote} as an argument" + "this {description} is only valid with {quote}{x}{quote} as an argument" ), ); } [first, second] => { - diag.span_label(self.span, format!("this attribute is only valid with either {quote}{first}{quote} or {quote}{second}{quote} as an argument")); + diag.span_label(self.span, format!("this {description} is only valid with either {quote}{first}{quote} or {quote}{second}{quote} as an argument")); } [first @ .., second_to_last, last] => { let mut res = String::new(); @@ -740,7 +755,7 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for AttributeParseError<'_> { "{quote}{second_to_last}{quote} or {quote}{last}{quote}" )); - diag.span_label(self.span, format!("this attribute is only valid with one of the following arguments: {res}")); + diag.span_label(self.span, format!("this {description} is only valid with one of the following arguments: {res}")); } } } @@ -756,9 +771,9 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for AttributeParseError<'_> { diag.span_suggestions( self.attr_span, if self.suggestions.len() == 1 { - "must be of the form" + "must be of the form".to_string() } else { - "try changing it to one of the following valid forms of the attribute" + format!("try changing it to one of the following valid forms of the {description}") }, self.suggestions, Applicability::HasPlaceholders, diff --git a/compiler/rustc_builtin_macros/src/cfg.rs b/compiler/rustc_builtin_macros/src/cfg.rs index 85b8ef79c0504..387399668111e 100644 --- a/compiler/rustc_builtin_macros/src/cfg.rs +++ b/compiler/rustc_builtin_macros/src/cfg.rs @@ -2,13 +2,18 @@ //! 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, ParsedDescription, 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 +26,49 @@ 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 }, + ParsedDescription::Macro, + 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 f00d177394489..c1f43fa741cfa 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 50998572274ec..d992ec82e2fd2 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` macro input + cfg!(foo = 123); //~ ERROR malformed `cfg` macro input cfg!(foo, bar); //~ ERROR expected 1 cfg-pattern } diff --git a/tests/ui/macros/cfg.stderr b/tests/ui/macros/cfg.stderr index ad3f9b188ddb9..a153ed9921b33 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` macro 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` macro 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 ae07336335419..0000000000000 --- 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 6c25f9140a1ab..0000000000000 --- 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 0000000000000..097f5cd8e586e --- /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 0000000000000..58c0e31ce0840 --- /dev/null +++ b/tests/ui/span/E0805.stderr @@ -0,0 +1,14 @@ +error[E0805]: malformed `cfg` macro 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`.