Skip to content

Commit ee08666

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 74d42f4 commit ee08666

File tree

3 files changed

+50
-15
lines changed

3 files changed

+50
-15
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}`
@@ -815,7 +820,9 @@ parse_unexpected_token_after_not_default = use `!` to perform logical negation o
815820
parse_unexpected_token_after_not_logical = use `!` to perform logical negation
816821
parse_unexpected_token_after_struct_name = expected `where`, `{"{"}`, `(`, or `;` after struct name
817822
parse_unexpected_token_after_struct_name_found_doc_comment = expected `where`, `{"{"}`, `(`, or `;` after struct name, found doc comment `{$token}`
823+
# Deliberately doesn't print `$token`, which is empty.
818824
parse_unexpected_token_after_struct_name_found_keyword = expected `where`, `{"{"}`, `(`, or `;` after struct name, found keyword `{$token}`
825+
parse_unexpected_token_after_struct_name_found_metavar = expected `where`, `{"{"}`, `(`, or `;` after struct name, found metavar
819826
parse_unexpected_token_after_struct_name_found_other = expected `where`, `{"{"}`, `(`, or `;` after struct name, found `{$token}`
820827
821828
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: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1033,6 +1033,8 @@ pub(crate) enum ExpectedIdentifierFound {
10331033
ReservedKeyword(#[primary_span] Span),
10341034
#[label(parse_expected_identifier_found_doc_comment)]
10351035
DocComment(#[primary_span] Span),
1036+
#[label(parse_expected_identifier_found_metavar)]
1037+
MetaVar(#[primary_span] Span),
10361038
#[label(parse_expected_identifier)]
10371039
Other(#[primary_span] Span),
10381040
}
@@ -1046,6 +1048,7 @@ impl ExpectedIdentifierFound {
10461048
Some(TokenDescription::Keyword) => ExpectedIdentifierFound::Keyword,
10471049
Some(TokenDescription::ReservedKeyword) => ExpectedIdentifierFound::ReservedKeyword,
10481050
Some(TokenDescription::DocComment) => ExpectedIdentifierFound::DocComment,
1051+
Some(TokenDescription::MetaVar(_)) => ExpectedIdentifierFound::MetaVar,
10491052
None => ExpectedIdentifierFound::Other,
10501053
})(span)
10511054
}
@@ -1080,6 +1083,9 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for ExpectedIdentifier {
10801083
Some(TokenDescription::DocComment) => {
10811084
fluent::parse_expected_identifier_found_doc_comment_str
10821085
}
1086+
Some(TokenDescription::MetaVar(_)) => {
1087+
fluent::parse_expected_identifier_found_metavar_str
1088+
}
10831089
None => fluent::parse_expected_identifier_found_str,
10841090
},
10851091
);
@@ -1138,6 +1144,7 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for ExpectedSemi {
11381144
Some(TokenDescription::DocComment) => {
11391145
fluent::parse_expected_semi_found_doc_comment_str
11401146
}
1147+
Some(TokenDescription::MetaVar(_)) => fluent::parse_expected_semi_found_metavar_str,
11411148
None => fluent::parse_expected_semi_found_str,
11421149
},
11431150
);
@@ -1822,6 +1829,13 @@ pub(crate) enum UnexpectedTokenAfterStructName {
18221829
span: Span,
18231830
token: Token,
18241831
},
1832+
#[diag(parse_unexpected_token_after_struct_name_found_metavar)]
1833+
MetaVar {
1834+
#[primary_span]
1835+
#[label(parse_unexpected_token_after_struct_name)]
1836+
span: Span,
1837+
token: Token, // unused
1838+
},
18251839
#[diag(parse_unexpected_token_after_struct_name_found_other)]
18261840
Other {
18271841
#[primary_span]
@@ -1838,6 +1852,7 @@ impl UnexpectedTokenAfterStructName {
18381852
Some(TokenDescription::Keyword) => Self::Keyword { span, token },
18391853
Some(TokenDescription::ReservedKeyword) => Self::ReservedKeyword { span, token },
18401854
Some(TokenDescription::DocComment) => Self::DocComment { span, token },
1855+
Some(TokenDescription::MetaVar(_)) => Self::MetaVar { span, token },
18411856
None => Self::Other { span, token },
18421857
}
18431858
}

compiler/rustc_parse/src/parser/mod.rs

Lines changed: 28 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@ pub use path::PathStyle;
2020

2121
use core::fmt;
2222
use rustc_ast::ptr::P;
23-
use rustc_ast::token::{self, Delimiter, IdentIsRaw, Nonterminal, Token, TokenKind};
23+
use rustc_ast::token::{
24+
self, Delimiter, IdentIsRaw, InvisibleOrigin, Nonterminal, NonterminalKind, Token, TokenKind,
25+
};
2426
use rustc_ast::tokenstream::{AttributesData, DelimSpacing, DelimSpan, Spacing};
2527
use rustc_ast::tokenstream::{TokenStream, TokenTree, TokenTreeCursor};
2628
use rustc_ast::util::case::Case;
@@ -385,6 +387,12 @@ pub enum TokenDescription {
385387
Keyword,
386388
ReservedKeyword,
387389
DocComment,
390+
391+
// Expanded metavariables are wrapped in invisible delimiters which aren't
392+
// pretty-printed. In error messages we must handle these specially
393+
// otherwise we get confusing things in messages like "expected `(`, found
394+
// ``". It's better to say "expected `(`, found type metavariable".
395+
MetaVar(NonterminalKind),
388396
}
389397

390398
impl TokenDescription {
@@ -394,26 +402,31 @@ impl TokenDescription {
394402
_ if token.is_used_keyword() => Some(TokenDescription::Keyword),
395403
_ if token.is_unused_keyword() => Some(TokenDescription::ReservedKeyword),
396404
token::DocComment(..) => Some(TokenDescription::DocComment),
405+
token::OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(kind))) => {
406+
Some(TokenDescription::MetaVar(kind))
407+
}
397408
_ => None,
398409
}
399410
}
400411
}
401412

402413
pub fn token_descr(token: &Token) -> String {
403-
let name = pprust::token_to_string(token).to_string();
404-
405-
let kind = match (TokenDescription::from_token(token), &token.kind) {
406-
(Some(TokenDescription::ReservedIdentifier), _) => Some("reserved identifier"),
407-
(Some(TokenDescription::Keyword), _) => Some("keyword"),
408-
(Some(TokenDescription::ReservedKeyword), _) => Some("reserved keyword"),
409-
(Some(TokenDescription::DocComment), _) => Some("doc comment"),
410-
(None, TokenKind::NtIdent(..)) => Some("identifier"),
411-
(None, TokenKind::NtLifetime(..)) => Some("lifetime"),
412-
(None, TokenKind::Interpolated(node)) => Some(node.descr()),
413-
(None, _) => None,
414-
};
415-
416-
if let Some(kind) = kind { format!("{kind} `{name}`") } else { format!("`{name}`") }
414+
use TokenDescription::*;
415+
416+
let s = pprust::token_to_string(token).to_string();
417+
418+
match (TokenDescription::from_token(token), &token.kind) {
419+
(Some(ReservedIdentifier), _) => format!("reserved identifier `{s}`"),
420+
(Some(Keyword), _) => format!("keyword `{s}`"),
421+
(Some(ReservedKeyword), _) => format!("reserved keyword `{s}`"),
422+
(Some(DocComment), _) => format!("doc comment `{s}`"),
423+
// Deliberately doesn't print `s`, which is empty.
424+
(Some(MetaVar(kind)), _) => format!("`{kind}` metavariable"),
425+
(None, TokenKind::NtIdent(..)) => format!("identifier `{s}`"),
426+
(None, TokenKind::NtLifetime(..)) => format!("lifetime `{s}`"),
427+
(None, TokenKind::Interpolated(node)) => format!("{} `{s}`", node.descr()),
428+
(None, _) => format!("`{s}`"),
429+
}
417430
}
418431

419432
impl<'a> Parser<'a> {

0 commit comments

Comments
 (0)