Skip to content

Commit 50d454d

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 4c79efb commit 50d454d

File tree

3 files changed

+47
-12
lines changed

3 files changed

+47
-12
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+
# Deliberately doesn't print `$token`, which is empty.
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
@@ -217,7 +220,9 @@ parse_expected_mut_or_const_in_raw_pointer_type = expected `mut` or `const` keyw
217220
.suggestion = add `mut` or `const` here
218221
219222
parse_expected_semi_found_doc_comment_str = expected `;`, found doc comment `{$token}`
223+
# Deliberately doesn't print `$token`, which is empty.
220224
parse_expected_semi_found_keyword_str = expected `;`, found keyword `{$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}`
@@ -811,7 +816,9 @@ parse_unexpected_token_after_not_default = use `!` to perform logical negation o
811816
parse_unexpected_token_after_not_logical = use `!` to perform logical negation
812817
parse_unexpected_token_after_struct_name = expected `where`, `{"{"}`, `(`, or `;` after struct name
813818
parse_unexpected_token_after_struct_name_found_doc_comment = expected `where`, `{"{"}`, `(`, or `;` after struct name, found doc comment `{$token}`
819+
# Deliberately doesn't print `$token`, which is empty.
814820
parse_unexpected_token_after_struct_name_found_keyword = expected `where`, `{"{"}`, `(`, or `;` after struct name, found keyword `{$token}`
821+
parse_unexpected_token_after_struct_name_found_metavar = expected `where`, `{"{"}`, `(`, or `;` after struct name, found metavar
815822
parse_unexpected_token_after_struct_name_found_other = expected `where`, `{"{"}`, `(`, or `;` after struct name, found `{$token}`
816823
817824
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: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1032,6 +1032,8 @@ pub(crate) enum ExpectedIdentifierFound {
10321032
ReservedKeyword(#[primary_span] Span),
10331033
#[label(parse_expected_identifier_found_doc_comment)]
10341034
DocComment(#[primary_span] Span),
1035+
#[label(parse_expected_identifier_found_metavar)]
1036+
MetaVar(#[primary_span] Span),
10351037
#[label(parse_expected_identifier)]
10361038
Other(#[primary_span] Span),
10371039
}
@@ -1045,6 +1047,7 @@ impl ExpectedIdentifierFound {
10451047
Some(TokenDescription::Keyword) => ExpectedIdentifierFound::Keyword,
10461048
Some(TokenDescription::ReservedKeyword) => ExpectedIdentifierFound::ReservedKeyword,
10471049
Some(TokenDescription::DocComment) => ExpectedIdentifierFound::DocComment,
1050+
Some(TokenDescription::MetaVar(_)) => ExpectedIdentifierFound::MetaVar,
10481051
None => ExpectedIdentifierFound::Other,
10491052
})(span)
10501053
}
@@ -1079,6 +1082,9 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for ExpectedIdentifier {
10791082
Some(TokenDescription::DocComment) => {
10801083
fluent::parse_expected_identifier_found_doc_comment_str
10811084
}
1085+
Some(TokenDescription::MetaVar(_)) => {
1086+
fluent::parse_expected_identifier_found_metavar_str
1087+
}
10821088
None => fluent::parse_expected_identifier_found_str,
10831089
},
10841090
);
@@ -1137,6 +1143,9 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for ExpectedSemi {
11371143
Some(TokenDescription::DocComment) => {
11381144
fluent::parse_expected_semi_found_doc_comment_str
11391145
}
1146+
Some(TokenDescription::MetaVar(_)) => {
1147+
fluent::parse_expected_semi_found_metavar_str
1148+
}
11401149
None => fluent::parse_expected_semi_found_str,
11411150
},
11421151
);
@@ -1821,6 +1830,13 @@ pub(crate) enum UnexpectedTokenAfterStructName {
18211830
span: Span,
18221831
token: Token,
18231832
},
1833+
#[diag(parse_unexpected_token_after_struct_name_found_metavar)]
1834+
MetaVar {
1835+
#[primary_span]
1836+
#[label(parse_unexpected_token_after_struct_name)]
1837+
span: Span,
1838+
token: Token, // unused
1839+
},
18241840
#[diag(parse_unexpected_token_after_struct_name_found_other)]
18251841
Other {
18261842
#[primary_span]
@@ -1837,6 +1853,7 @@ impl UnexpectedTokenAfterStructName {
18371853
Some(TokenDescription::Keyword) => Self::Keyword { span, token },
18381854
Some(TokenDescription::ReservedKeyword) => Self::ReservedKeyword { span, token },
18391855
Some(TokenDescription::DocComment) => Self::DocComment { span, token },
1856+
Some(TokenDescription::MetaVar(_)) => Self::MetaVar { span, token },
18401857
None => Self::Other { span, token },
18411858
}
18421859
}

compiler/rustc_parse/src/parser/mod.rs

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ pub use pat::{CommaRecoveryMode, RecoverColon, RecoverComma};
2020
pub use path::PathStyle;
2121

2222
use rustc_ast::ptr::P;
23-
use rustc_ast::token::{self, Delimiter, Token, TokenKind};
23+
use rustc_ast::token::{self, Delimiter, InvisibleOrigin, NonterminalKind, Token, TokenKind};
2424
use rustc_ast::tokenstream::{AttributesData, DelimSpacing, DelimSpan, Spacing};
2525
use rustc_ast::tokenstream::{TokenStream, TokenTree, TokenTreeCursor};
2626
use rustc_ast::util::case::Case;
@@ -383,6 +383,12 @@ pub enum TokenDescription {
383383
Keyword,
384384
ReservedKeyword,
385385
DocComment,
386+
387+
// Expanded metavariables are wrapped in invisible delimiters which aren't
388+
// pretty-printed. In error messages we must handle these specially
389+
// otherwise we get confusing things in messages like "expected `(`, found
390+
// ``". It's better to say "expected `(`, found type metavariable".
391+
MetaVar(NonterminalKind),
386392
}
387393

388394
impl TokenDescription {
@@ -392,24 +398,29 @@ impl TokenDescription {
392398
_ if token.is_used_keyword() => Some(TokenDescription::Keyword),
393399
_ if token.is_unused_keyword() => Some(TokenDescription::ReservedKeyword),
394400
token::DocComment(..) => Some(TokenDescription::DocComment),
401+
token::OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(kind))) => {
402+
Some(TokenDescription::MetaVar(kind))
403+
}
395404
_ => None,
396405
}
397406
}
398407
}
399408

400409
pub fn token_descr(token: &Token) -> String {
401-
let name = pprust::token_to_string(token).to_string();
402-
403-
let kind = match (TokenDescription::from_token(token), &token.kind) {
404-
(Some(TokenDescription::ReservedIdentifier), _) => Some("reserved identifier"),
405-
(Some(TokenDescription::Keyword), _) => Some("keyword"),
406-
(Some(TokenDescription::ReservedKeyword), _) => Some("reserved keyword"),
407-
(Some(TokenDescription::DocComment), _) => Some("doc comment"),
408-
(None, TokenKind::Interpolated(node)) => Some(node.0.descr()),
409-
(None, _) => None,
410-
};
410+
use TokenDescription::*;
411411

412-
if let Some(kind) = kind { format!("{kind} `{name}`") } else { format!("`{name}`") }
412+
let s = pprust::token_to_string(token).to_string();
413+
414+
match (TokenDescription::from_token(token), &token.kind) {
415+
(Some(ReservedIdentifier), _) => format!("reserved identifier `{s}`"),
416+
(Some(Keyword), _) => format!("keyword `{s}`"),
417+
(Some(ReservedKeyword), _) => format!("reserved keyword `{s}`"),
418+
(Some(DocComment), _) => format!("doc comment `{s}`"),
419+
// Deliberately doesn't print `s`, which is empty.
420+
(Some(MetaVar(kind)), _) => format!("`{kind}` metavariable"),
421+
(None, TokenKind::Interpolated(node)) => format!("{} `{s}`", node.0.descr()),
422+
(None, _) => format!("`{s}`"),
423+
}
413424
}
414425

415426
impl<'a> Parser<'a> {

0 commit comments

Comments
 (0)