Skip to content

Commit 7507ee2

Browse files
committed
Migrate "expected identifier" diagnostics to diagnostic structs
1 parent 21b5194 commit 7507ee2

File tree

4 files changed

+170
-43
lines changed

4 files changed

+170
-43
lines changed

compiler/rustc_error_messages/locales/en-US/parser.ftl

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,3 +290,19 @@ parser_inner_doc_comment_not_permitted = expected outer doc comment
290290
.suggestion = you might have meant to write a regular comment
291291
.label_does_not_annotate_this = the inner doc comment doesn't annotate this {$item}
292292
.sugg_change_inner_to_outer = to annotate the {$item}, change the doc comment from inner to outer style
293+
294+
parser_expected_identifier_found_reserved_identifier_str = expected identifier, found reserved identifier `{$token_str}`
295+
parser_expected_identifier_found_keyword_str = expected identifier, found keyword `{$token_str}`
296+
parser_expected_identifier_found_reserved_keyword_str = expected identifier, found reserved keyword `{$token_str}`
297+
parser_expected_identifier_found_doc_comment_str = expected identifier, found doc comment `{$token_str}`
298+
parser_expected_identifier_found_str = expected identifier, found `{$token_str}`
299+
300+
parser_expected_identifier_found_reserved_identifier = expected identifier, found reserved identifier
301+
parser_expected_identifier_found_keyword = expected identifier, found keyword
302+
parser_expected_identifier_found_reserved_keyword = expected identifier, found reserved keyword
303+
parser_expected_identifier_found_doc_comment = expected identifier, found doc comment
304+
parser_expected_identifier = expected identifier
305+
306+
parser_sugg_escape_to_use_as_identifier = escape `{$ident_name}` to use it as an identifier
307+
308+
parser_sugg_remove_comma = remove this comma

compiler/rustc_parse/src/errors.rs

Lines changed: 94 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1-
use rustc_errors::Applicability;
1+
use rustc_errors::{fluent, AddToDiagnostic, Applicability, EmissionGuarantee, IntoDiagnostic};
22
use rustc_macros::{Diagnostic, Subdiagnostic};
33
use rustc_session::errors::ExprParenthesesNeeded;
44
use rustc_span::symbol::Ident;
55
use rustc_span::{Span, Symbol};
66

7+
use crate::parser::{TokenDescription, TokenDescriptionKind};
8+
79
#[derive(Diagnostic)]
810
#[diag(parser::maybe_report_ambiguous_plus)]
911
pub(crate) struct AmbiguousPlus {
@@ -870,3 +872,94 @@ pub(crate) struct InvalidMetaItem {
870872
pub span: Span,
871873
pub token: String,
872874
}
875+
876+
#[derive(Subdiagnostic)]
877+
#[suggestion_verbose(
878+
parser::sugg_escape_to_use_as_identifier,
879+
applicability = "maybe-incorrect",
880+
code = "r#"
881+
)]
882+
pub(crate) struct SuggEscapeToUseAsIdentifier {
883+
#[primary_span]
884+
pub span: Span,
885+
pub ident_name: String,
886+
}
887+
888+
#[derive(Subdiagnostic)]
889+
#[suggestion(parser::sugg_remove_comma, applicability = "machine-applicable", code = "")]
890+
pub(crate) struct SuggRemoveComma {
891+
#[primary_span]
892+
pub span: Span,
893+
}
894+
895+
#[derive(Subdiagnostic)]
896+
pub(crate) enum ExpectedIdentifierFound {
897+
#[label(parser::expected_identifier_found_reserved_identifier)]
898+
ReservedIdentifier(#[primary_span] Span),
899+
#[label(parser::expected_identifier_found_keyword)]
900+
Keyword(#[primary_span] Span),
901+
#[label(parser::expected_identifier_found_reserved_keyword)]
902+
ReservedKeyword(#[primary_span] Span),
903+
#[label(parser::expected_identifier_found_doc_comment)]
904+
DocComment(#[primary_span] Span),
905+
#[label(parser::expected_identifier)]
906+
Other(#[primary_span] Span),
907+
}
908+
909+
impl ExpectedIdentifierFound {
910+
pub fn new(token_descr_kind: Option<TokenDescriptionKind>, span: Span) -> Self {
911+
(match token_descr_kind {
912+
Some(TokenDescriptionKind::ReservedIdentifier) => {
913+
ExpectedIdentifierFound::ReservedIdentifier
914+
}
915+
Some(TokenDescriptionKind::Keyword) => ExpectedIdentifierFound::Keyword,
916+
Some(TokenDescriptionKind::ReservedKeyword) => ExpectedIdentifierFound::ReservedKeyword,
917+
Some(TokenDescriptionKind::DocComment) => ExpectedIdentifierFound::DocComment,
918+
None => ExpectedIdentifierFound::Other,
919+
})(span)
920+
}
921+
}
922+
923+
pub(crate) struct ExpectedIdentifier {
924+
pub span: Span,
925+
pub token_descr: TokenDescription,
926+
pub suggest_raw: Option<SuggEscapeToUseAsIdentifier>,
927+
pub suggest_remove_comma: Option<SuggRemoveComma>,
928+
}
929+
930+
impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for ExpectedIdentifier {
931+
fn into_diagnostic(
932+
self,
933+
handler: &'a rustc_errors::Handler,
934+
) -> rustc_errors::DiagnosticBuilder<'a, G> {
935+
let mut diag = handler.struct_diagnostic(match self.token_descr.kind {
936+
Some(TokenDescriptionKind::ReservedIdentifier) => {
937+
fluent::parser::expected_identifier_found_reserved_identifier_str
938+
}
939+
Some(TokenDescriptionKind::Keyword) => {
940+
fluent::parser::expected_identifier_found_keyword_str
941+
}
942+
Some(TokenDescriptionKind::ReservedKeyword) => {
943+
fluent::parser::expected_identifier_found_reserved_keyword_str
944+
}
945+
Some(TokenDescriptionKind::DocComment) => {
946+
fluent::parser::expected_identifier_found_doc_comment_str
947+
}
948+
None => fluent::parser::expected_identifier_found_str,
949+
});
950+
diag.set_span(self.span);
951+
diag.set_arg("token_str", self.token_descr.name);
952+
953+
if let Some(sugg) = self.suggest_raw {
954+
sugg.add_to_diagnostic(&mut diag);
955+
}
956+
957+
ExpectedIdentifierFound::new(self.token_descr.kind, self.span).add_to_diagnostic(&mut diag);
958+
959+
if let Some(sugg) = self.suggest_remove_comma {
960+
sugg.add_to_diagnostic(&mut diag);
961+
}
962+
963+
diag
964+
}
965+
}

compiler/rustc_parse/src/parser/diagnostics.rs

Lines changed: 25 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@ use super::{
44
TokenExpectType, TokenType,
55
};
66
use crate::errors::{
7-
AmbiguousPlus, BadQPathStage2, BadTypePlus, BadTypePlusSub, InInTypo, IncorrectAwait,
8-
IncorrectSemicolon, IncorrectUseOfAwait, UseEqInstead,
7+
AmbiguousPlus, BadQPathStage2, BadTypePlus, BadTypePlusSub, ExpectedIdentifier, InInTypo,
8+
IncorrectAwait, IncorrectSemicolon, IncorrectUseOfAwait, SuggEscapeToUseAsIdentifier,
9+
SuggRemoveComma, UseEqInstead,
910
};
1011

1112
use crate::lexer::UnmatchedBrace;
@@ -23,7 +24,7 @@ use rustc_data_structures::fx::FxHashSet;
2324
use rustc_errors::{
2425
fluent, Applicability, DiagnosticBuilder, DiagnosticMessage, Handler, MultiSpan, PResult,
2526
};
26-
use rustc_errors::{pluralize, struct_span_err, Diagnostic, ErrorGuaranteed};
27+
use rustc_errors::{pluralize, struct_span_err, Diagnostic, ErrorGuaranteed, IntoDiagnostic};
2728
use rustc_span::source_map::Spanned;
2829
use rustc_span::symbol::{kw, sym, Ident};
2930
use rustc_span::{Span, SpanSnippetError, DUMMY_SP};
@@ -285,10 +286,6 @@ impl<'a> Parser<'a> {
285286
}
286287

287288
pub(super) fn expected_ident_found(&self) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
288-
let mut err = self.struct_span_err(
289-
self.token.span,
290-
&format!("expected identifier, found {}", super::token_descr(&self.token)),
291-
);
292289
let valid_follow = &[
293290
TokenKind::Eq,
294291
TokenKind::Colon,
@@ -300,34 +297,33 @@ impl<'a> Parser<'a> {
300297
TokenKind::CloseDelim(Delimiter::Brace),
301298
TokenKind::CloseDelim(Delimiter::Parenthesis),
302299
];
303-
match self.token.ident() {
300+
let suggest_raw = match self.token.ident() {
304301
Some((ident, false))
305302
if ident.is_raw_guess()
306303
&& self.look_ahead(1, |t| valid_follow.contains(&t.kind)) =>
307304
{
308-
err.span_suggestion_verbose(
309-
ident.span.shrink_to_lo(),
310-
&format!("escape `{}` to use it as an identifier", ident.name),
311-
"r#",
312-
Applicability::MaybeIncorrect,
313-
);
305+
Some(SuggEscapeToUseAsIdentifier {
306+
span: ident.span.shrink_to_lo(),
307+
ident_name: ident.name.to_string(),
308+
})
314309
}
315-
_ => {}
316-
}
317-
if let Some(token_descr) = super::token_descr_opt(&self.token) {
318-
err.span_label(self.token.span, format!("expected identifier, found {}", token_descr));
319-
} else {
320-
err.span_label(self.token.span, "expected identifier");
310+
_ => None,
311+
};
312+
313+
let suggest_remove_comma =
321314
if self.token == token::Comma && self.look_ahead(1, |t| t.is_ident()) {
322-
err.span_suggestion(
323-
self.token.span,
324-
"remove this comma",
325-
"",
326-
Applicability::MachineApplicable,
327-
);
328-
}
329-
}
330-
err
315+
Some(SuggRemoveComma { span: self.token.span })
316+
} else {
317+
None
318+
};
319+
320+
let err = ExpectedIdentifier {
321+
span: self.token.span,
322+
token_descr: super::token_descr_struct(&self.token),
323+
suggest_raw,
324+
suggest_remove_comma,
325+
};
326+
err.into_diagnostic(&self.sess.span_diagnostic)
331327
}
332328

333329
pub(super) fn expected_one_of_not_found(

compiler/rustc_parse/src/parser/mod.rs

Lines changed: 35 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -410,22 +410,44 @@ pub enum FollowedByType {
410410
No,
411411
}
412412

413-
fn token_descr_opt(token: &Token) -> Option<&'static str> {
414-
Some(match token.kind {
415-
_ if token.is_special_ident() => "reserved identifier",
416-
_ if token.is_used_keyword() => "keyword",
417-
_ if token.is_unused_keyword() => "reserved keyword",
418-
token::DocComment(..) => "doc comment",
419-
_ => return None,
420-
})
413+
#[derive(Clone, Copy, PartialEq, Eq)]
414+
pub enum TokenDescriptionKind {
415+
ReservedIdentifier,
416+
Keyword,
417+
ReservedKeyword,
418+
DocComment,
419+
}
420+
421+
#[derive(Clone, PartialEq, Eq)]
422+
pub struct TokenDescription {
423+
pub kind: Option<TokenDescriptionKind>,
424+
pub name: String,
425+
}
426+
427+
pub(super) fn token_descr_struct(token: &Token) -> TokenDescription {
428+
let kind = match token.kind {
429+
_ if token.is_special_ident() => Some(TokenDescriptionKind::ReservedIdentifier),
430+
_ if token.is_used_keyword() => Some(TokenDescriptionKind::Keyword),
431+
_ if token.is_unused_keyword() => Some(TokenDescriptionKind::ReservedKeyword),
432+
token::DocComment(..) => Some(TokenDescriptionKind::DocComment),
433+
_ => None,
434+
};
435+
let name = pprust::token_to_string(token).to_string();
436+
437+
TokenDescription { kind, name }
421438
}
422439

423440
pub(super) fn token_descr(token: &Token) -> String {
424-
let token_str = pprust::token_to_string(token);
425-
match token_descr_opt(token) {
426-
Some(prefix) => format!("{} `{}`", prefix, token_str),
427-
_ => format!("`{}`", token_str),
428-
}
441+
let TokenDescription { kind, name } = token_descr_struct(token);
442+
443+
let kind = kind.map(|kind| match kind {
444+
TokenDescriptionKind::ReservedIdentifier => "reserved identifier",
445+
TokenDescriptionKind::Keyword => "keyword",
446+
TokenDescriptionKind::ReservedKeyword => "reserved keyword",
447+
TokenDescriptionKind::DocComment => "doc comment",
448+
});
449+
450+
if let Some(kind) = kind { format!("{} `{}`", kind, name) } else { format!("`{}`", name) }
429451
}
430452

431453
impl<'a> Parser<'a> {

0 commit comments

Comments
 (0)