Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 06732aa

Browse files
committed
Add metavariables to TokenDescription.
Pasted metavariables are wrapped in invisible delimiters, which pretty-print as empty strings, and changing that can break some proc macros. But error messages saying "expected identifer, found ``" are bad. So this commit adds support for metavariables in `TokenDescription` so they print as "metavariable" in error messages, instead of "``". It's not used meaningfully yet, but will be needed to get rid of interpolated tokens.
1 parent 4d7009f commit 06732aa

File tree

3 files changed

+61
-17
lines changed

3 files changed

+61
-17
lines changed

compiler/rustc_parse/messages.ftl

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,9 @@ parse_expected_identifier_found_doc_comment = expected identifier, found doc com
207207
parse_expected_identifier_found_doc_comment_str = expected identifier, found doc comment `{$token}`
208208
parse_expected_identifier_found_keyword = expected identifier, found keyword
209209
parse_expected_identifier_found_keyword_str = expected identifier, found keyword `{$token}`
210+
parse_expected_identifier_found_metavar = expected identifier, found metavariable
211+
# This one deliberately doesn't print a token.
212+
parse_expected_identifier_found_metavar_str = expected identifier, found metavariable
210213
parse_expected_identifier_found_reserved_identifier = expected identifier, found reserved identifier
211214
parse_expected_identifier_found_reserved_identifier_str = expected identifier, found reserved identifier `{$token}`
212215
parse_expected_identifier_found_reserved_keyword = expected identifier, found reserved keyword
@@ -218,6 +221,8 @@ parse_expected_mut_or_const_in_raw_pointer_type = expected `mut` or `const` keyw
218221
219222
parse_expected_semi_found_doc_comment_str = expected `;`, found doc comment `{$token}`
220223
parse_expected_semi_found_keyword_str = expected `;`, found keyword `{$token}`
224+
# This one deliberately doesn't print a token.
225+
parse_expected_semi_found_metavar_str = expected `;`, found metavariable
221226
parse_expected_semi_found_reserved_identifier_str = expected `;`, found reserved identifier `{$token}`
222227
parse_expected_semi_found_reserved_keyword_str = expected `;`, found reserved keyword `{$token}`
223228
parse_expected_semi_found_str = expected `;`, found `{$token}`
@@ -847,6 +852,8 @@ parse_unexpected_token_after_not_logical = use `!` to perform logical negation
847852
parse_unexpected_token_after_struct_name = expected `where`, `{"{"}`, `(`, or `;` after struct name
848853
parse_unexpected_token_after_struct_name_found_doc_comment = expected `where`, `{"{"}`, `(`, or `;` after struct name, found doc comment `{$token}`
849854
parse_unexpected_token_after_struct_name_found_keyword = expected `where`, `{"{"}`, `(`, or `;` after struct name, found keyword `{$token}`
855+
# This one deliberately doesn't print a token.
856+
parse_unexpected_token_after_struct_name_found_metavar = expected `where`, `{"{"}`, `(`, or `;` after struct name, found metavar
850857
parse_unexpected_token_after_struct_name_found_other = expected `where`, `{"{"}`, `(`, or `;` after struct name, found `{$token}`
851858
852859
parse_unexpected_token_after_struct_name_found_reserved_identifier = expected `where`, `{"{"}`, `(`, or `;` after struct name, found reserved identifier `{$token}`

compiler/rustc_parse/src/errors.rs

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1085,6 +1085,8 @@ pub(crate) enum ExpectedIdentifierFound {
10851085
ReservedKeyword(#[primary_span] Span),
10861086
#[label(parse_expected_identifier_found_doc_comment)]
10871087
DocComment(#[primary_span] Span),
1088+
#[label(parse_expected_identifier_found_metavar)]
1089+
MetaVar(#[primary_span] Span),
10881090
#[label(parse_expected_identifier)]
10891091
Other(#[primary_span] Span),
10901092
}
@@ -1098,6 +1100,7 @@ impl ExpectedIdentifierFound {
10981100
Some(TokenDescription::Keyword) => ExpectedIdentifierFound::Keyword,
10991101
Some(TokenDescription::ReservedKeyword) => ExpectedIdentifierFound::ReservedKeyword,
11001102
Some(TokenDescription::DocComment) => ExpectedIdentifierFound::DocComment,
1103+
Some(TokenDescription::MetaVar(_)) => ExpectedIdentifierFound::MetaVar,
11011104
None => ExpectedIdentifierFound::Other,
11021105
})(span)
11031106
}
@@ -1116,6 +1119,7 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for ExpectedIdentifier {
11161119
fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> {
11171120
let token_descr = TokenDescription::from_token(&self.token);
11181121

1122+
let mut add_token = true;
11191123
let mut diag = Diag::new(dcx, level, match token_descr {
11201124
Some(TokenDescription::ReservedIdentifier) => {
11211125
fluent::parse_expected_identifier_found_reserved_identifier_str
@@ -1127,10 +1131,16 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for ExpectedIdentifier {
11271131
Some(TokenDescription::DocComment) => {
11281132
fluent::parse_expected_identifier_found_doc_comment_str
11291133
}
1134+
Some(TokenDescription::MetaVar(_)) => {
1135+
add_token = false;
1136+
fluent::parse_expected_identifier_found_metavar_str
1137+
}
11301138
None => fluent::parse_expected_identifier_found_str,
11311139
});
11321140
diag.span(self.span);
1133-
diag.arg("token", self.token);
1141+
if add_token {
1142+
diag.arg("token", self.token);
1143+
}
11341144

11351145
if let Some(sugg) = self.suggest_raw {
11361146
sugg.add_to_diag(&mut diag);
@@ -1170,6 +1180,7 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for ExpectedSemi {
11701180
fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> {
11711181
let token_descr = TokenDescription::from_token(&self.token);
11721182

1183+
let mut add_token = true;
11731184
let mut diag = Diag::new(dcx, level, match token_descr {
11741185
Some(TokenDescription::ReservedIdentifier) => {
11751186
fluent::parse_expected_semi_found_reserved_identifier_str
@@ -1179,10 +1190,16 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for ExpectedSemi {
11791190
fluent::parse_expected_semi_found_reserved_keyword_str
11801191
}
11811192
Some(TokenDescription::DocComment) => fluent::parse_expected_semi_found_doc_comment_str,
1193+
Some(TokenDescription::MetaVar(_)) => {
1194+
add_token = false;
1195+
fluent::parse_expected_semi_found_metavar_str
1196+
}
11821197
None => fluent::parse_expected_semi_found_str,
11831198
});
11841199
diag.span(self.span);
1185-
diag.arg("token", self.token);
1200+
if add_token {
1201+
diag.arg("token", self.token);
1202+
}
11861203

11871204
if let Some(unexpected_token_label) = self.unexpected_token_label {
11881205
diag.span_label(unexpected_token_label, fluent::parse_label_unexpected_token);
@@ -1916,6 +1933,12 @@ pub(crate) enum UnexpectedTokenAfterStructName {
19161933
span: Span,
19171934
token: Token,
19181935
},
1936+
#[diag(parse_unexpected_token_after_struct_name_found_metavar)]
1937+
MetaVar {
1938+
#[primary_span]
1939+
#[label(parse_unexpected_token_after_struct_name)]
1940+
span: Span,
1941+
},
19191942
#[diag(parse_unexpected_token_after_struct_name_found_other)]
19201943
Other {
19211944
#[primary_span]
@@ -1932,6 +1955,7 @@ impl UnexpectedTokenAfterStructName {
19321955
Some(TokenDescription::Keyword) => Self::Keyword { span, token },
19331956
Some(TokenDescription::ReservedKeyword) => Self::ReservedKeyword { span, token },
19341957
Some(TokenDescription::DocComment) => Self::DocComment { span, token },
1958+
Some(TokenDescription::MetaVar(_)) => Self::MetaVar { span },
19351959
None => Self::Other { span, token },
19361960
}
19371961
}

compiler/rustc_parse/src/parser/mod.rs

Lines changed: 28 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@ pub(crate) use item::FnParseMode;
2121
pub use pat::{CommaRecoveryMode, RecoverColon, RecoverComma};
2222
use path::PathStyle;
2323
use rustc_ast::ptr::P;
24-
use rustc_ast::token::{self, Delimiter, IdentIsRaw, Nonterminal, Token, TokenKind};
24+
use rustc_ast::token::{
25+
self, Delimiter, IdentIsRaw, InvisibleOrigin, MetaVarKind, Nonterminal, Token, TokenKind,
26+
};
2527
use rustc_ast::tokenstream::{
2628
AttrsTarget, DelimSpacing, DelimSpan, Spacing, TokenStream, TokenTree, TokenTreeCursor,
2729
};
@@ -410,6 +412,12 @@ pub(super) enum TokenDescription {
410412
Keyword,
411413
ReservedKeyword,
412414
DocComment,
415+
416+
// Expanded metavariables are wrapped in invisible delimiters which aren't
417+
// pretty-printed. In error messages we must handle these specially
418+
// otherwise we get confusing things in messages like "expected `(`, found
419+
// ``". It's better to say e.g. "expected `(`, found type metavariable".
420+
MetaVar(MetaVarKind),
413421
}
414422

415423
impl TokenDescription {
@@ -419,26 +427,31 @@ impl TokenDescription {
419427
_ if token.is_used_keyword() => Some(TokenDescription::Keyword),
420428
_ if token.is_unused_keyword() => Some(TokenDescription::ReservedKeyword),
421429
token::DocComment(..) => Some(TokenDescription::DocComment),
430+
token::OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(kind))) => {
431+
Some(TokenDescription::MetaVar(kind))
432+
}
422433
_ => None,
423434
}
424435
}
425436
}
426437

427438
pub fn token_descr(token: &Token) -> String {
428-
let name = pprust::token_to_string(token).to_string();
429-
430-
let kind = match (TokenDescription::from_token(token), &token.kind) {
431-
(Some(TokenDescription::ReservedIdentifier), _) => Some("reserved identifier"),
432-
(Some(TokenDescription::Keyword), _) => Some("keyword"),
433-
(Some(TokenDescription::ReservedKeyword), _) => Some("reserved keyword"),
434-
(Some(TokenDescription::DocComment), _) => Some("doc comment"),
435-
(None, TokenKind::NtIdent(..)) => Some("identifier"),
436-
(None, TokenKind::NtLifetime(..)) => Some("lifetime"),
437-
(None, TokenKind::Interpolated(node)) => Some(node.descr()),
438-
(None, _) => None,
439-
};
440-
441-
if let Some(kind) = kind { format!("{kind} `{name}`") } else { format!("`{name}`") }
439+
use TokenDescription::*;
440+
441+
let s = pprust::token_to_string(token).to_string();
442+
443+
match (TokenDescription::from_token(token), &token.kind) {
444+
(Some(ReservedIdentifier), _) => format!("reserved identifier `{s}`"),
445+
(Some(Keyword), _) => format!("keyword `{s}`"),
446+
(Some(ReservedKeyword), _) => format!("reserved keyword `{s}`"),
447+
(Some(DocComment), _) => format!("doc comment `{s}`"),
448+
// Deliberately doesn't print `s`, which is empty.
449+
(Some(MetaVar(kind)), _) => format!("`{kind}` metavariable"),
450+
(None, TokenKind::NtIdent(..)) => format!("identifier `{s}`"),
451+
(None, TokenKind::NtLifetime(..)) => format!("lifetime `{s}`"),
452+
(None, TokenKind::Interpolated(node)) => format!("{} `{s}`", node.descr()),
453+
(None, _) => format!("`{s}`"),
454+
}
442455
}
443456

444457
impl<'a> Parser<'a> {

0 commit comments

Comments
 (0)