Skip to content

Commit 6aa985c

Browse files
authored
Unrolled build for rust-lang#124778
Rollup merge of rust-lang#124778 - fmease:fix-diag-msg-parse-meta-item, r=nnethercote Fix parse error message for meta items Addresses rust-lang#122796 (comment), 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 rust-lang#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.
2 parents 66f8770 + 0ad3c5d commit 6aa985c

13 files changed

+93
-78
lines changed

compiler/rustc_parse/messages.ftl

+2-4
Original file line numberDiff line numberDiff line change
@@ -401,10 +401,8 @@ parse_invalid_logical_operator = `{$incorrect}` is not a logical operator
401401
.use_amp_amp_for_conjunction = use `&&` to perform logical conjunction
402402
.use_pipe_pipe_for_disjunction = use `||` to perform logical disjunction
403403
404-
parse_invalid_meta_item = expected unsuffixed literal or identifier, found `{$token}`
405-
406-
parse_invalid_meta_item_unquoted_ident = expected unsuffixed literal, found `{$token}`
407-
.suggestion = surround the identifier with quotation marks to parse it as a string
404+
parse_invalid_meta_item = expected unsuffixed literal, found `{$token}`
405+
.quote_ident_sugg = surround the identifier with quotation marks to make it into a string literal
408406
409407
parse_invalid_offset_of = offset_of expects dot-separated field and variant names
410408

compiler/rustc_parse/src/errors.rs

+3-11
Original file line numberDiff line numberDiff line change
@@ -978,21 +978,13 @@ pub(crate) struct InvalidMetaItem {
978978
#[primary_span]
979979
pub span: Span,
980980
pub token: Token,
981-
}
982-
983-
#[derive(Diagnostic)]
984-
#[diag(parse_invalid_meta_item_unquoted_ident)]
985-
pub(crate) struct InvalidMetaItemUnquotedIdent {
986-
#[primary_span]
987-
pub span: Span,
988-
pub token: Token,
989981
#[subdiagnostic]
990-
pub sugg: InvalidMetaItemSuggQuoteIdent,
982+
pub quote_ident_sugg: Option<InvalidMetaItemQuoteIdentSugg>,
991983
}
992984

993985
#[derive(Subdiagnostic)]
994-
#[multipart_suggestion(parse_suggestion, applicability = "machine-applicable")]
995-
pub(crate) struct InvalidMetaItemSuggQuoteIdent {
986+
#[multipart_suggestion(parse_quote_ident_sugg, applicability = "machine-applicable")]
987+
pub(crate) struct InvalidMetaItemQuoteIdentSugg {
996988
#[suggestion_part(code = "\"")]
997989
pub before: Span,
998990
#[suggestion_part(code = "\"")]

compiler/rustc_parse/src/parser/attr.rs

+30-26
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
1-
use crate::errors::{
2-
InvalidMetaItem, InvalidMetaItemSuggQuoteIdent, InvalidMetaItemUnquotedIdent,
3-
SuffixedLiteralInAttribute,
4-
};
1+
use crate::errors;
52
use crate::fluent_generated as fluent;
63
use crate::maybe_whole;
74

@@ -318,7 +315,7 @@ impl<'a> Parser<'a> {
318315
debug!("checking if {:?} is unsuffixed", lit);
319316

320317
if !lit.kind.is_unsuffixed() {
321-
self.dcx().emit_err(SuffixedLiteralInAttribute { span: lit.span });
318+
self.dcx().emit_err(errors::SuffixedLiteralInAttribute { span: lit.span });
322319
}
323320

324321
Ok(lit)
@@ -356,10 +353,11 @@ impl<'a> Parser<'a> {
356353
Ok(nmis)
357354
}
358355

359-
/// Matches the following grammar (per RFC 1559).
356+
/// Parse a meta item per RFC 1559.
357+
///
360358
/// ```ebnf
361-
/// meta_item : PATH ( '=' UNSUFFIXED_LIT | '(' meta_item_inner? ')' )? ;
362-
/// meta_item_inner : (meta_item | UNSUFFIXED_LIT) (',' meta_item_inner)? ;
359+
/// MetaItem = SimplePath ( '=' UNSUFFIXED_LIT | '(' MetaSeq? ')' )? ;
360+
/// MetaSeq = MetaItemInner (',' MetaItemInner)* ','? ;
363361
/// ```
364362
pub fn parse_meta_item(&mut self) -> PResult<'a, ast::MetaItem> {
365363
// We can't use `maybe_whole` here because it would bump in the `None`
@@ -387,46 +385,52 @@ impl<'a> Parser<'a> {
387385
Ok(if self.eat(&token::Eq) {
388386
ast::MetaItemKind::NameValue(self.parse_unsuffixed_meta_item_lit()?)
389387
} else if self.check(&token::OpenDelim(Delimiter::Parenthesis)) {
390-
// Matches `meta_seq = ( COMMASEP(meta_item_inner) )`.
391388
let (list, _) = self.parse_paren_comma_seq(|p| p.parse_meta_item_inner())?;
392389
ast::MetaItemKind::List(list)
393390
} else {
394391
ast::MetaItemKind::Word
395392
})
396393
}
397394

398-
/// Matches `meta_item_inner : (meta_item | UNSUFFIXED_LIT) ;`.
395+
/// Parse an inner meta item per RFC 1559.
396+
///
397+
/// ```ebnf
398+
/// MetaItemInner = UNSUFFIXED_LIT | MetaItem ;
399+
/// ```
399400
fn parse_meta_item_inner(&mut self) -> PResult<'a, ast::NestedMetaItem> {
400401
match self.parse_unsuffixed_meta_item_lit() {
401402
Ok(lit) => return Ok(ast::NestedMetaItem::Lit(lit)),
402-
Err(err) => err.cancel(),
403+
Err(err) => err.cancel(), // we provide a better error below
403404
}
404405

405406
match self.parse_meta_item() {
406407
Ok(mi) => return Ok(ast::NestedMetaItem::MetaItem(mi)),
407-
Err(err) => err.cancel(),
408+
Err(err) => err.cancel(), // we provide a better error below
408409
}
409410

410-
let token = self.token.clone();
411+
let mut err = errors::InvalidMetaItem {
412+
span: self.token.span,
413+
token: self.token.clone(),
414+
quote_ident_sugg: None,
415+
};
411416

412-
// Check for unquoted idents in meta items, e.g.: #[cfg(key = foo)]
413-
// `from_expansion()` ensures we don't suggest for cases such as
414-
// `#[cfg(feature = $expr)]` in macros
415-
if self.prev_token == token::Eq && !self.token.span.from_expansion() {
417+
// Suggest quoting idents, e.g. in `#[cfg(key = value)]`. We don't use `Token::ident` and
418+
// don't `uninterpolate` the token to avoid suggesting anything butchered or questionable
419+
// when macro metavariables are involved.
420+
if self.prev_token == token::Eq
421+
&& let token::Ident(..) = self.token.kind
422+
{
416423
let before = self.token.span.shrink_to_lo();
417-
while matches!(self.token.kind, token::Ident(..)) {
424+
while let token::Ident(..) = self.token.kind {
418425
self.bump();
419426
}
420-
let after = self.prev_token.span.shrink_to_hi();
421-
let sugg = InvalidMetaItemSuggQuoteIdent { before, after };
422-
return Err(self.dcx().create_err(InvalidMetaItemUnquotedIdent {
423-
span: token.span,
424-
token,
425-
sugg,
426-
}));
427+
err.quote_ident_sugg = Some(errors::InvalidMetaItemQuoteIdentSugg {
428+
before,
429+
after: self.prev_token.span.shrink_to_hi(),
430+
});
427431
}
428432

429-
Err(self.dcx().create_err(InvalidMetaItem { span: token.span, token }))
433+
Err(self.dcx().create_err(err))
430434
}
431435
}
432436

tests/ui/attributes/nonterminal-expansion.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
macro_rules! pass_nonterminal {
66
($n:expr) => {
77
#[repr(align($n))]
8-
//~^ ERROR expected unsuffixed literal or identifier, found `n!()`
8+
//~^ ERROR expected unsuffixed literal, found `n!()`
99
struct S;
1010
};
1111
}

tests/ui/attributes/nonterminal-expansion.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error: expected unsuffixed literal or identifier, found `n!()`
1+
error: expected unsuffixed literal, found `n!()`
22
--> $DIR/nonterminal-expansion.rs:7:22
33
|
44
LL | #[repr(align($n))]

tests/ui/conditional-compilation/cfg-attr-syntax-validation.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ struct S9;
2828
macro_rules! generate_s10 {
2929
($expr: expr) => {
3030
#[cfg(feature = $expr)]
31-
//~^ ERROR expected unsuffixed literal or identifier, found `concat!("nonexistent")`
32-
//~| ERROR expected unsuffixed literal or identifier, found `concat!("nonexistent")`
31+
//~^ ERROR expected unsuffixed literal, found `concat!("nonexistent")`
32+
//~| ERROR expected unsuffixed literal, found `concat!("nonexistent")`
3333
struct S10;
3434
}
3535
}

tests/ui/conditional-compilation/cfg-attr-syntax-validation.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ LL | #[cfg(a = b"hi")]
5454
| |
5555
| help: consider removing the prefix
5656

57-
error: expected unsuffixed literal or identifier, found `concat!("nonexistent")`
57+
error: expected unsuffixed literal, found `concat!("nonexistent")`
5858
--> $DIR/cfg-attr-syntax-validation.rs:30:25
5959
|
6060
LL | #[cfg(feature = $expr)]
@@ -65,7 +65,7 @@ LL | generate_s10!(concat!("nonexistent"));
6565
|
6666
= note: this error originates in the macro `generate_s10` (in Nightly builds, run with -Z macro-backtrace for more info)
6767

68-
error: expected unsuffixed literal or identifier, found `concat!("nonexistent")`
68+
error: expected unsuffixed literal, found `concat!("nonexistent")`
6969
--> $DIR/cfg-attr-syntax-validation.rs:30:25
7070
|
7171
LL | #[cfg(feature = $expr)]

tests/ui/deprecation/issue-66340-deprecated-attr-non-meta-grammar.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ error: expected unsuffixed literal, found `test`
44
LL | #[deprecated(note = test)]
55
| ^^^^
66
|
7-
help: surround the identifier with quotation marks to parse it as a string
7+
help: surround the identifier with quotation marks to make it into a string literal
88
|
99
LL | #[deprecated(note = "test")]
1010
| + +
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,17 @@
11
macro_rules! mac {
22
($attr_item: meta) => {
33
#[cfg($attr_item)]
4-
//~^ ERROR expected unsuffixed literal or identifier, found `an(arbitrary token stream)`
5-
//~| ERROR expected unsuffixed literal or identifier, found `an(arbitrary token stream)`
4+
//~^ ERROR expected unsuffixed literal, found `an(arbitrary token stream)`
5+
//~| ERROR expected unsuffixed literal, found `an(arbitrary token stream)`
66
struct S;
77
}
88
}
99

1010
mac!(an(arbitrary token stream));
1111

12+
#[cfg(feature = -1)]
13+
//~^ ERROR expected unsuffixed literal, found `-`
14+
//~| ERROR expected unsuffixed literal, found `-`
15+
fn handler() {}
16+
1217
fn main() {}

tests/ui/parser/attribute/attr-bad-meta-4.stderr

+17-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
1-
error: expected unsuffixed literal or identifier, found `an(arbitrary token stream)`
1+
error: expected unsuffixed literal, found `-`
2+
--> $DIR/attr-bad-meta-4.rs:12:17
3+
|
4+
LL | #[cfg(feature = -1)]
5+
| ^
6+
7+
error: expected unsuffixed literal, found `an(arbitrary token stream)`
28
--> $DIR/attr-bad-meta-4.rs:3:15
39
|
410
LL | #[cfg($attr_item)]
@@ -9,7 +15,7 @@ LL | mac!(an(arbitrary token stream));
915
|
1016
= note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info)
1117

12-
error: expected unsuffixed literal or identifier, found `an(arbitrary token stream)`
18+
error: expected unsuffixed literal, found `an(arbitrary token stream)`
1319
--> $DIR/attr-bad-meta-4.rs:3:15
1420
|
1521
LL | #[cfg($attr_item)]
@@ -21,5 +27,13 @@ LL | mac!(an(arbitrary token stream));
2127
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
2228
= note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info)
2329

24-
error: aborting due to 2 previous errors
30+
error: expected unsuffixed literal, found `-`
31+
--> $DIR/attr-bad-meta-4.rs:12:17
32+
|
33+
LL | #[cfg(feature = -1)]
34+
| ^
35+
|
36+
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
37+
38+
error: aborting due to 4 previous errors
2539

tests/ui/parser/attribute/attr-unquoted-ident.fixed

-17
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,25 @@
11
//@ compile-flags: -Zdeduplicate-diagnostics=yes
2-
//@ run-rustfix
32

43
#![allow(unexpected_cfgs)]
54

65
fn main() {
76
#[cfg(key=foo)]
87
//~^ ERROR expected unsuffixed literal, found `foo`
9-
//~| HELP surround the identifier with quotation marks to parse it as a string
8+
//~| HELP surround the identifier with quotation marks to make it into a string literal
109
println!();
1110
#[cfg(key="bar")]
1211
println!();
1312
#[cfg(key=foo bar baz)]
1413
//~^ ERROR expected unsuffixed literal, found `foo`
15-
//~| HELP surround the identifier with quotation marks to parse it as a string
14+
//~| HELP surround the identifier with quotation marks to make it into a string literal
1615
println!();
1716
}
17+
18+
// Don't suggest surrounding `$name` or `nickname` with quotes:
19+
20+
macro_rules! make {
21+
($name:ident) => { #[doc(alias = $name)] pub struct S; }
22+
//~^ ERROR expected unsuffixed literal, found `nickname`
23+
}
24+
25+
make!(nickname); //~ NOTE in this expansion
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,35 @@
11
error: expected unsuffixed literal, found `foo`
2-
--> $DIR/attr-unquoted-ident.rs:7:15
2+
--> $DIR/attr-unquoted-ident.rs:6:15
33
|
44
LL | #[cfg(key=foo)]
55
| ^^^
66
|
7-
help: surround the identifier with quotation marks to parse it as a string
7+
help: surround the identifier with quotation marks to make it into a string literal
88
|
99
LL | #[cfg(key="foo")]
1010
| + +
1111

1212
error: expected unsuffixed literal, found `foo`
13-
--> $DIR/attr-unquoted-ident.rs:13:15
13+
--> $DIR/attr-unquoted-ident.rs:12:15
1414
|
1515
LL | #[cfg(key=foo bar baz)]
1616
| ^^^
1717
|
18-
help: surround the identifier with quotation marks to parse it as a string
18+
help: surround the identifier with quotation marks to make it into a string literal
1919
|
2020
LL | #[cfg(key="foo bar baz")]
2121
| + +
2222

23-
error: aborting due to 2 previous errors
23+
error: expected unsuffixed literal, found `nickname`
24+
--> $DIR/attr-unquoted-ident.rs:21:38
25+
|
26+
LL | ($name:ident) => { #[doc(alias = $name)] pub struct S; }
27+
| ^^^^^
28+
...
29+
LL | make!(nickname);
30+
| --------------- in this macro invocation
31+
|
32+
= note: this error originates in the macro `make` (in Nightly builds, run with -Z macro-backtrace for more info)
33+
34+
error: aborting due to 3 previous errors
2435

0 commit comments

Comments
 (0)