Fix parse error message for meta items
This commit is contained in:
parent
7c4ac0603e
commit
0ad3c5da72
@ -401,10 +401,8 @@ parse_invalid_logical_operator = `{$incorrect}` is not a logical operator
|
||||
.use_amp_amp_for_conjunction = use `&&` to perform logical conjunction
|
||||
.use_pipe_pipe_for_disjunction = use `||` to perform logical disjunction
|
||||
|
||||
parse_invalid_meta_item = expected unsuffixed literal or identifier, found `{$token}`
|
||||
|
||||
parse_invalid_meta_item_unquoted_ident = expected unsuffixed literal, found `{$token}`
|
||||
.suggestion = surround the identifier with quotation marks to parse it as a string
|
||||
parse_invalid_meta_item = expected unsuffixed literal, found `{$token}`
|
||||
.quote_ident_sugg = surround the identifier with quotation marks to make it into a string literal
|
||||
|
||||
parse_invalid_offset_of = offset_of expects dot-separated field and variant names
|
||||
|
||||
|
@ -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 = "\"")]
|
||||
|
@ -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 @@ pub(crate) fn parse_unsuffixed_meta_item_lit(&mut self) -> PResult<'a, ast::Meta
|
||||
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 @@ pub(crate) fn parse_meta_seq_top(&mut self) -> PResult<'a, ThinVec<ast::NestedMe
|
||||
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 @@ pub(crate) fn parse_meta_item_kind(&mut self) -> PResult<'a, ast::MetaItemKind>
|
||||
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 @@ pub(crate) fn parse_meta_item_kind(&mut self) -> PResult<'a, ast::MetaItemKind>
|
||||
})
|
||||
}
|
||||
|
||||
/// 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))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
macro_rules! pass_nonterminal {
|
||||
($n:expr) => {
|
||||
#[repr(align($n))]
|
||||
//~^ ERROR expected unsuffixed literal or identifier, found `n!()`
|
||||
//~^ ERROR expected unsuffixed literal, found `n!()`
|
||||
struct S;
|
||||
};
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
error: expected unsuffixed literal or identifier, found `n!()`
|
||||
error: expected unsuffixed literal, found `n!()`
|
||||
--> $DIR/nonterminal-expansion.rs:7:22
|
||||
|
|
||||
LL | #[repr(align($n))]
|
||||
|
@ -28,8 +28,8 @@
|
||||
macro_rules! generate_s10 {
|
||||
($expr: expr) => {
|
||||
#[cfg(feature = $expr)]
|
||||
//~^ ERROR expected unsuffixed literal or identifier, found `concat!("nonexistent")`
|
||||
//~| ERROR expected unsuffixed literal or identifier, found `concat!("nonexistent")`
|
||||
//~^ ERROR expected unsuffixed literal, found `concat!("nonexistent")`
|
||||
//~| ERROR expected unsuffixed literal, found `concat!("nonexistent")`
|
||||
struct S10;
|
||||
}
|
||||
}
|
||||
|
@ -54,7 +54,7 @@ LL | #[cfg(a = b"hi")]
|
||||
| |
|
||||
| help: consider removing the prefix
|
||||
|
||||
error: expected unsuffixed literal or identifier, found `concat!("nonexistent")`
|
||||
error: expected unsuffixed literal, found `concat!("nonexistent")`
|
||||
--> $DIR/cfg-attr-syntax-validation.rs:30:25
|
||||
|
|
||||
LL | #[cfg(feature = $expr)]
|
||||
@ -65,7 +65,7 @@ LL | generate_s10!(concat!("nonexistent"));
|
||||
|
|
||||
= note: this error originates in the macro `generate_s10` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: expected unsuffixed literal or identifier, found `concat!("nonexistent")`
|
||||
error: expected unsuffixed literal, found `concat!("nonexistent")`
|
||||
--> $DIR/cfg-attr-syntax-validation.rs:30:25
|
||||
|
|
||||
LL | #[cfg(feature = $expr)]
|
||||
|
@ -4,7 +4,7 @@ error: expected unsuffixed literal, found `test`
|
||||
LL | #[deprecated(note = test)]
|
||||
| ^^^^
|
||||
|
|
||||
help: surround the identifier with quotation marks to parse it as a string
|
||||
help: surround the identifier with quotation marks to make it into a string literal
|
||||
|
|
||||
LL | #[deprecated(note = "test")]
|
||||
| + +
|
||||
|
@ -1,12 +1,17 @@
|
||||
macro_rules! mac {
|
||||
($attr_item: meta) => {
|
||||
#[cfg($attr_item)]
|
||||
//~^ ERROR expected unsuffixed literal or identifier, found `an(arbitrary token stream)`
|
||||
//~| ERROR expected unsuffixed literal or identifier, found `an(arbitrary token stream)`
|
||||
//~^ ERROR expected unsuffixed literal, found `an(arbitrary token stream)`
|
||||
//~| ERROR expected unsuffixed literal, found `an(arbitrary token stream)`
|
||||
struct S;
|
||||
}
|
||||
}
|
||||
|
||||
mac!(an(arbitrary token stream));
|
||||
|
||||
#[cfg(feature = -1)]
|
||||
//~^ ERROR expected unsuffixed literal, found `-`
|
||||
//~| ERROR expected unsuffixed literal, found `-`
|
||||
fn handler() {}
|
||||
|
||||
fn main() {}
|
||||
|
@ -1,4 +1,10 @@
|
||||
error: expected unsuffixed literal or identifier, found `an(arbitrary token stream)`
|
||||
error: expected unsuffixed literal, found `-`
|
||||
--> $DIR/attr-bad-meta-4.rs:12:17
|
||||
|
|
||||
LL | #[cfg(feature = -1)]
|
||||
| ^
|
||||
|
||||
error: expected unsuffixed literal, found `an(arbitrary token stream)`
|
||||
--> $DIR/attr-bad-meta-4.rs:3:15
|
||||
|
|
||||
LL | #[cfg($attr_item)]
|
||||
@ -9,7 +15,7 @@ LL | mac!(an(arbitrary token stream));
|
||||
|
|
||||
= note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: expected unsuffixed literal or identifier, found `an(arbitrary token stream)`
|
||||
error: expected unsuffixed literal, found `an(arbitrary token stream)`
|
||||
--> $DIR/attr-bad-meta-4.rs:3:15
|
||||
|
|
||||
LL | #[cfg($attr_item)]
|
||||
@ -21,5 +27,13 @@ LL | mac!(an(arbitrary token stream));
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
= note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error: expected unsuffixed literal, found `-`
|
||||
--> $DIR/attr-bad-meta-4.rs:12:17
|
||||
|
|
||||
LL | #[cfg(feature = -1)]
|
||||
| ^
|
||||
|
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
|
@ -1,17 +0,0 @@
|
||||
//@ compile-flags: -Zdeduplicate-diagnostics=yes
|
||||
//@ run-rustfix
|
||||
|
||||
#![allow(unexpected_cfgs)]
|
||||
|
||||
fn main() {
|
||||
#[cfg(key="foo")]
|
||||
//~^ ERROR expected unsuffixed literal, found `foo`
|
||||
//~| HELP surround the identifier with quotation marks to parse it as a string
|
||||
println!();
|
||||
#[cfg(key="bar")]
|
||||
println!();
|
||||
#[cfg(key="foo bar baz")]
|
||||
//~^ ERROR expected unsuffixed literal, found `foo`
|
||||
//~| HELP surround the identifier with quotation marks to parse it as a string
|
||||
println!();
|
||||
}
|
@ -1,17 +1,25 @@
|
||||
//@ compile-flags: -Zdeduplicate-diagnostics=yes
|
||||
//@ run-rustfix
|
||||
|
||||
#![allow(unexpected_cfgs)]
|
||||
|
||||
fn main() {
|
||||
#[cfg(key=foo)]
|
||||
//~^ ERROR expected unsuffixed literal, found `foo`
|
||||
//~| HELP surround the identifier with quotation marks to parse it as a string
|
||||
//~| HELP surround the identifier with quotation marks to make it into a string literal
|
||||
println!();
|
||||
#[cfg(key="bar")]
|
||||
println!();
|
||||
#[cfg(key=foo bar baz)]
|
||||
//~^ ERROR expected unsuffixed literal, found `foo`
|
||||
//~| HELP surround the identifier with quotation marks to parse it as a string
|
||||
//~| HELP surround the identifier with quotation marks to make it into a string literal
|
||||
println!();
|
||||
}
|
||||
|
||||
// Don't suggest surrounding `$name` or `nickname` with quotes:
|
||||
|
||||
macro_rules! make {
|
||||
($name:ident) => { #[doc(alias = $name)] pub struct S; }
|
||||
//~^ ERROR expected unsuffixed literal, found `nickname`
|
||||
}
|
||||
|
||||
make!(nickname); //~ NOTE in this expansion
|
||||
|
@ -1,24 +1,35 @@
|
||||
error: expected unsuffixed literal, found `foo`
|
||||
--> $DIR/attr-unquoted-ident.rs:7:15
|
||||
--> $DIR/attr-unquoted-ident.rs:6:15
|
||||
|
|
||||
LL | #[cfg(key=foo)]
|
||||
| ^^^
|
||||
|
|
||||
help: surround the identifier with quotation marks to parse it as a string
|
||||
help: surround the identifier with quotation marks to make it into a string literal
|
||||
|
|
||||
LL | #[cfg(key="foo")]
|
||||
| + +
|
||||
|
||||
error: expected unsuffixed literal, found `foo`
|
||||
--> $DIR/attr-unquoted-ident.rs:13:15
|
||||
--> $DIR/attr-unquoted-ident.rs:12:15
|
||||
|
|
||||
LL | #[cfg(key=foo bar baz)]
|
||||
| ^^^
|
||||
|
|
||||
help: surround the identifier with quotation marks to parse it as a string
|
||||
help: surround the identifier with quotation marks to make it into a string literal
|
||||
|
|
||||
LL | #[cfg(key="foo bar baz")]
|
||||
| + +
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error: expected unsuffixed literal, found `nickname`
|
||||
--> $DIR/attr-unquoted-ident.rs:21:38
|
||||
|
|
||||
LL | ($name:ident) => { #[doc(alias = $name)] pub struct S; }
|
||||
| ^^^^^
|
||||
...
|
||||
LL | make!(nickname);
|
||||
| --------------- in this macro invocation
|
||||
|
|
||||
= note: this error originates in the macro `make` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user