diff options
| author | Matthias Krüger <matthias.krueger@famsik.de> | 2024-05-10 16:10:45 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-05-10 16:10:45 +0200 |
| commit | f605174ea7826fa3db67aa0b707758440656b44c (patch) | |
| tree | 057aa06a9919ea2484b4e89ee428b86f68282bea /compiler/rustc_parse/src | |
| parent | c768a0e99f93f150b58fc926e0e761c3e226cfc6 (diff) | |
| parent | 0ad3c5da72469c848e321ddee207f9a5dfbf9876 (diff) | |
| download | rust-f605174ea7826fa3db67aa0b707758440656b44c.tar.gz rust-f605174ea7826fa3db67aa0b707758440656b44c.zip | |
Rollup merge of #124778 - fmease:fix-diag-msg-parse-meta-item, r=nnethercote
Fix parse error message for meta items Addresses https://github.com/rust-lang/rust/issues/122796#issuecomment-2010803906, cc [``@]Thomasdezeeuw.`` For attrs inside of a macro like `#[doc(alias = $ident)]` or `#[cfg(feature = $ident)]` where `$ident` is a macro metavariable of fragment kind `ident`, we used to say the following when expanded (with `$ident` ⟼ `ident`): ``` error: expected unsuffixed literal or identifier, found `ident` --> weird.rs:6:19 | 6 | #[cfg(feature = $ident)] | ^^^^^^ ... 11 | m!(id); | ------ in this macro invocation | = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) ``` This was incorrect and caused confusion, justifiably so (see #122796). In this position, we only accept/expect *unsuffixed literals* which consist of numeric & string literals as well as the boolean literals / the keywords / the reserved identifiers `false` & `true` **but not** arbitrary identifiers. Furthermore, we used to suggest garbage when encountering unexpected non-identifier tokens: ``` error: expected unsuffixed literal, found `-` --> weird.rs:16:17 | 16 | #[cfg(feature = -1)] | ^ | help: surround the identifier with quotation marks to parse it as a string | 16 | #[cfg(feature =" "-1)] | + + ``` Now we no longer do.
Diffstat (limited to 'compiler/rustc_parse/src')
| -rw-r--r-- | compiler/rustc_parse/src/errors.rs | 14 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/attr.rs | 56 |
2 files changed, 33 insertions, 37 deletions
diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index d06f03a7c17..2f68a299f26 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -978,21 +978,13 @@ pub(crate) struct InvalidMetaItem { #[primary_span] pub span: Span, pub token: Token, -} - -#[derive(Diagnostic)] -#[diag(parse_invalid_meta_item_unquoted_ident)] -pub(crate) struct InvalidMetaItemUnquotedIdent { - #[primary_span] - pub span: Span, - pub token: Token, #[subdiagnostic] - pub sugg: InvalidMetaItemSuggQuoteIdent, + pub quote_ident_sugg: Option<InvalidMetaItemQuoteIdentSugg>, } #[derive(Subdiagnostic)] -#[multipart_suggestion(parse_suggestion, applicability = "machine-applicable")] -pub(crate) struct InvalidMetaItemSuggQuoteIdent { +#[multipart_suggestion(parse_quote_ident_sugg, applicability = "machine-applicable")] +pub(crate) struct InvalidMetaItemQuoteIdentSugg { #[suggestion_part(code = "\"")] pub before: Span, #[suggestion_part(code = "\"")] diff --git a/compiler/rustc_parse/src/parser/attr.rs b/compiler/rustc_parse/src/parser/attr.rs index ab5f51eedc3..d5d8060d909 100644 --- a/compiler/rustc_parse/src/parser/attr.rs +++ b/compiler/rustc_parse/src/parser/attr.rs @@ -1,7 +1,4 @@ -use crate::errors::{ - InvalidMetaItem, InvalidMetaItemSuggQuoteIdent, InvalidMetaItemUnquotedIdent, - SuffixedLiteralInAttribute, -}; +use crate::errors; use crate::fluent_generated as fluent; use crate::maybe_whole; @@ -318,7 +315,7 @@ impl<'a> Parser<'a> { debug!("checking if {:?} is unsuffixed", lit); if !lit.kind.is_unsuffixed() { - self.dcx().emit_err(SuffixedLiteralInAttribute { span: lit.span }); + self.dcx().emit_err(errors::SuffixedLiteralInAttribute { span: lit.span }); } Ok(lit) @@ -356,10 +353,11 @@ impl<'a> Parser<'a> { Ok(nmis) } - /// Matches the following grammar (per RFC 1559). + /// Parse a meta item per RFC 1559. + /// /// ```ebnf - /// meta_item : PATH ( '=' UNSUFFIXED_LIT | '(' meta_item_inner? ')' )? ; - /// meta_item_inner : (meta_item | UNSUFFIXED_LIT) (',' meta_item_inner)? ; + /// MetaItem = SimplePath ( '=' UNSUFFIXED_LIT | '(' MetaSeq? ')' )? ; + /// MetaSeq = MetaItemInner (',' MetaItemInner)* ','? ; /// ``` pub fn parse_meta_item(&mut self) -> PResult<'a, ast::MetaItem> { // We can't use `maybe_whole` here because it would bump in the `None` @@ -387,7 +385,6 @@ impl<'a> Parser<'a> { Ok(if self.eat(&token::Eq) { ast::MetaItemKind::NameValue(self.parse_unsuffixed_meta_item_lit()?) } else if self.check(&token::OpenDelim(Delimiter::Parenthesis)) { - // Matches `meta_seq = ( COMMASEP(meta_item_inner) )`. let (list, _) = self.parse_paren_comma_seq(|p| p.parse_meta_item_inner())?; ast::MetaItemKind::List(list) } else { @@ -395,38 +392,45 @@ impl<'a> Parser<'a> { }) } - /// Matches `meta_item_inner : (meta_item | UNSUFFIXED_LIT) ;`. + /// Parse an inner meta item per RFC 1559. + /// + /// ```ebnf + /// MetaItemInner = UNSUFFIXED_LIT | MetaItem ; + /// ``` 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(), + Err(err) => err.cancel(), // we provide a better error below } match self.parse_meta_item() { Ok(mi) => return Ok(ast::NestedMetaItem::MetaItem(mi)), - Err(err) => err.cancel(), + Err(err) => err.cancel(), // we provide a better error below } - let token = self.token.clone(); + let mut err = errors::InvalidMetaItem { + span: self.token.span, + token: self.token.clone(), + quote_ident_sugg: None, + }; - // Check for unquoted idents in meta items, e.g.: #[cfg(key = foo)] - // `from_expansion()` ensures we don't suggest for cases such as - // `#[cfg(feature = $expr)]` in macros - if self.prev_token == token::Eq && !self.token.span.from_expansion() { + // Suggest quoting idents, e.g. in `#[cfg(key = value)]`. We don't use `Token::ident` and + // don't `uninterpolate` the token to avoid suggesting anything butchered or questionable + // when macro metavariables are involved. + if self.prev_token == token::Eq + && let token::Ident(..) = self.token.kind + { let before = self.token.span.shrink_to_lo(); - while matches!(self.token.kind, token::Ident(..)) { + while let token::Ident(..) = self.token.kind { self.bump(); } - let after = self.prev_token.span.shrink_to_hi(); - let sugg = InvalidMetaItemSuggQuoteIdent { before, after }; - return Err(self.dcx().create_err(InvalidMetaItemUnquotedIdent { - span: token.span, - token, - sugg, - })); + err.quote_ident_sugg = Some(errors::InvalidMetaItemQuoteIdentSugg { + before, + after: self.prev_token.span.shrink_to_hi(), + }); } - Err(self.dcx().create_err(InvalidMetaItem { span: token.span, token })) + Err(self.dcx().create_err(err)) } } |
