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

Commit 4ce6956

Browse files
nnethercotecompiler-errors
authored andcommitted
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 ace58ea commit 4ce6956

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}`
@@ -845,6 +850,8 @@ parse_unexpected_token_after_not_logical = use `!` to perform logical negation
845850
parse_unexpected_token_after_struct_name = expected `where`, `{"{"}`, `(`, or `;` after struct name
846851
parse_unexpected_token_after_struct_name_found_doc_comment = expected `where`, `{"{"}`, `(`, or `;` after struct name, found doc comment `{$token}`
847852
parse_unexpected_token_after_struct_name_found_keyword = expected `where`, `{"{"}`, `(`, or `;` after struct name, found keyword `{$token}`
853+
# This one deliberately doesn't print a token.
854+
parse_unexpected_token_after_struct_name_found_metavar = expected `where`, `{"{"}`, `(`, or `;` after struct name, found metavar
848855
parse_unexpected_token_after_struct_name_found_other = expected `where`, `{"{"}`, `(`, or `;` after struct name, found `{$token}`
849856
850857
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
@@ -1083,6 +1083,8 @@ pub(crate) enum ExpectedIdentifierFound {
10831083
ReservedKeyword(#[primary_span] Span),
10841084
#[label(parse_expected_identifier_found_doc_comment)]
10851085
DocComment(#[primary_span] Span),
1086+
#[label(parse_expected_identifier_found_metavar)]
1087+
MetaVar(#[primary_span] Span),
10861088
#[label(parse_expected_identifier)]
10871089
Other(#[primary_span] Span),
10881090
}
@@ -1096,6 +1098,7 @@ impl ExpectedIdentifierFound {
10961098
Some(TokenDescription::Keyword) => ExpectedIdentifierFound::Keyword,
10971099
Some(TokenDescription::ReservedKeyword) => ExpectedIdentifierFound::ReservedKeyword,
10981100
Some(TokenDescription::DocComment) => ExpectedIdentifierFound::DocComment,
1101+
Some(TokenDescription::MetaVar(_)) => ExpectedIdentifierFound::MetaVar,
10991102
None => ExpectedIdentifierFound::Other,
11001103
})(span)
11011104
}
@@ -1114,6 +1117,7 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for ExpectedIdentifier {
11141117
fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> {
11151118
let token_descr = TokenDescription::from_token(&self.token);
11161119

1120+
let mut add_token = true;
11171121
let mut diag = Diag::new(
11181122
dcx,
11191123
level,
@@ -1130,11 +1134,17 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for ExpectedIdentifier {
11301134
Some(TokenDescription::DocComment) => {
11311135
fluent::parse_expected_identifier_found_doc_comment_str
11321136
}
1137+
Some(TokenDescription::MetaVar(_)) => {
1138+
add_token = false;
1139+
fluent::parse_expected_identifier_found_metavar_str
1140+
}
11331141
None => fluent::parse_expected_identifier_found_str,
11341142
},
11351143
);
11361144
diag.span(self.span);
1137-
diag.arg("token", self.token);
1145+
if add_token {
1146+
diag.arg("token", self.token);
1147+
}
11381148

11391149
if let Some(sugg) = self.suggest_raw {
11401150
sugg.add_to_diag(&mut diag);
@@ -1174,6 +1184,7 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for ExpectedSemi {
11741184
fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> {
11751185
let token_descr = TokenDescription::from_token(&self.token);
11761186

1187+
let mut add_token = true;
11771188
let mut diag = Diag::new(
11781189
dcx,
11791190
level,
@@ -1188,11 +1199,17 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for ExpectedSemi {
11881199
Some(TokenDescription::DocComment) => {
11891200
fluent::parse_expected_semi_found_doc_comment_str
11901201
}
1202+
Some(TokenDescription::MetaVar(_)) => {
1203+
add_token = false;
1204+
fluent::parse_expected_semi_found_metavar_str
1205+
}
11911206
None => fluent::parse_expected_semi_found_str,
11921207
},
11931208
);
11941209
diag.span(self.span);
1195-
diag.arg("token", self.token);
1210+
if add_token {
1211+
diag.arg("token", self.token);
1212+
}
11961213

11971214
if let Some(unexpected_token_label) = self.unexpected_token_label {
11981215
diag.span_label(unexpected_token_label, fluent::parse_label_unexpected_token);
@@ -1918,6 +1935,12 @@ pub(crate) enum UnexpectedTokenAfterStructName {
19181935
span: Span,
19191936
token: Token,
19201937
},
1938+
#[diag(parse_unexpected_token_after_struct_name_found_metavar)]
1939+
MetaVar {
1940+
#[primary_span]
1941+
#[label(parse_unexpected_token_after_struct_name)]
1942+
span: Span,
1943+
},
19211944
#[diag(parse_unexpected_token_after_struct_name_found_other)]
19221945
Other {
19231946
#[primary_span]
@@ -1934,6 +1957,7 @@ impl UnexpectedTokenAfterStructName {
19341957
Some(TokenDescription::Keyword) => Self::Keyword { span, token },
19351958
Some(TokenDescription::ReservedKeyword) => Self::ReservedKeyword { span, token },
19361959
Some(TokenDescription::DocComment) => Self::DocComment { span, token },
1960+
Some(TokenDescription::MetaVar(_)) => Self::MetaVar { span },
19371961
None => Self::Other { span, token },
19381962
}
19391963
}

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
};
@@ -406,6 +408,12 @@ pub(super) enum TokenDescription {
406408
Keyword,
407409
ReservedKeyword,
408410
DocComment,
411+
412+
// Expanded metavariables are wrapped in invisible delimiters which aren't
413+
// pretty-printed. In error messages we must handle these specially
414+
// otherwise we get confusing things in messages like "expected `(`, found
415+
// ``". It's better to say e.g. "expected `(`, found type metavariable".
416+
MetaVar(MetaVarKind),
409417
}
410418

411419
impl TokenDescription {
@@ -415,26 +423,31 @@ impl TokenDescription {
415423
_ if token.is_used_keyword() => Some(TokenDescription::Keyword),
416424
_ if token.is_unused_keyword() => Some(TokenDescription::ReservedKeyword),
417425
token::DocComment(..) => Some(TokenDescription::DocComment),
426+
token::OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(kind))) => {
427+
Some(TokenDescription::MetaVar(kind))
428+
}
418429
_ => None,
419430
}
420431
}
421432
}
422433

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

440453
impl<'a> Parser<'a> {

0 commit comments

Comments
 (0)