diff options
| author | Ezra Shaw <ezrasure@outlook.com> | 2023-03-17 21:41:26 +1300 |
|---|---|---|
| committer | Ezra Shaw <ezrasure@outlook.com> | 2023-03-19 20:24:06 +1300 |
| commit | b4e17a5098f0413b01c90c8505e0f01e8bea50de (patch) | |
| tree | 48ec7d45ab5f0608ee1ffaadcbf360efceb67ad1 /compiler/rustc_parse/src | |
| parent | c9ddb73184290e0698060a80b0b5727d6ee11098 (diff) | |
| download | rust-b4e17a5098f0413b01c90c8505e0f01e8bea50de.tar.gz rust-b4e17a5098f0413b01c90c8505e0f01e8bea50de.zip | |
refactor: improve "ident starts with number" error
Diffstat (limited to 'compiler/rustc_parse/src')
| -rw-r--r-- | compiler/rustc_parse/src/errors.rs | 5 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/diagnostics.rs | 34 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/pat.rs | 6 |
3 files changed, 29 insertions, 16 deletions
diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 2def5c5b32f..a9d116012ae 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -986,7 +986,10 @@ impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for ExpectedIdentifier { #[derive(Subdiagnostic)] #[help(parse_invalid_identifier_with_leading_number)] -pub(crate) struct HelpIdentifierStartsWithNumber; +pub(crate) struct HelpIdentifierStartsWithNumber { + #[primary_span] + pub num_span: Span, +} pub(crate) struct ExpectedSemi { pub span: Span, diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index a9f24ab44ea..47d11084915 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -38,7 +38,7 @@ use rustc_errors::{ use rustc_session::errors::ExprParenthesesNeeded; use rustc_span::source_map::Spanned; use rustc_span::symbol::{kw, sym, Ident}; -use rustc_span::{Span, SpanSnippetError, DUMMY_SP}; +use rustc_span::{Span, SpanSnippetError, Symbol, DUMMY_SP}; use std::mem::take; use std::ops::{Deref, DerefMut}; use thin_vec::{thin_vec, ThinVec}; @@ -309,8 +309,11 @@ impl<'a> Parser<'a> { && self.look_ahead(1, |t| t.is_ident())) .then_some(SuggRemoveComma { span: self.token.span }); - let help_cannot_start_number = - self.is_lit_bad_ident().then_some(HelpIdentifierStartsWithNumber); + let help_cannot_start_number = self.is_lit_bad_ident().map(|(len, _valid_portion)| { + let (invalid, _valid) = self.token.span.split_at(len as u32); + + HelpIdentifierStartsWithNumber { num_span: invalid } + }); let err = ExpectedIdentifier { span: self.token.span, @@ -378,13 +381,24 @@ impl<'a> Parser<'a> { /// Checks if the current token is a integer or float literal and looks like /// it could be a invalid identifier with digits at the start. - pub(super) fn is_lit_bad_ident(&mut self) -> bool { - matches!(self.token.uninterpolate().kind, token::Literal(Lit { kind: token::LitKind::Integer | token::LitKind::Float, .. }) - // ensure that the integer literal is followed by a *invalid* - // suffix: this is how we know that it is a identifier with an - // invalid beginning. - if rustc_ast::MetaItemLit::from_token(&self.token).is_none() - ) + /// + /// Returns the number of characters (bytes) composing the invalid portion + /// of the identifier and the valid portion of the identifier. + pub(super) fn is_lit_bad_ident(&mut self) -> Option<(usize, Symbol)> { + // ensure that the integer literal is followed by a *invalid* + // suffix: this is how we know that it is a identifier with an + // invalid beginning. + if let token::Literal(Lit { + kind: token::LitKind::Integer | token::LitKind::Float, + symbol, + suffix, + }) = self.token.uninterpolate().kind + && rustc_ast::MetaItemLit::from_token(&self.token).is_none() + { + Some((symbol.as_str().len(), suffix.unwrap())) + } else { + None + } } pub(super) fn expected_one_of_not_found( diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index fc9f1d1330a..d9af2415848 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -348,10 +348,6 @@ impl<'a> Parser<'a> { lo = self.token.span; } - if self.is_lit_bad_ident() { - return Err(self.expected_ident_found()); - } - let pat = if self.check(&token::BinOp(token::And)) || self.token.kind == token::AndAnd { self.parse_pat_deref(expected)? } else if self.check(&token::OpenDelim(Delimiter::Parenthesis)) { @@ -395,7 +391,7 @@ impl<'a> Parser<'a> { } else { PatKind::Lit(const_expr) } - } else if self.can_be_ident_pat() { + } else if self.can_be_ident_pat() || self.is_lit_bad_ident().is_some() { // Parse `ident @ pat` // This can give false positives and parse nullary enums, // they are dealt with later in resolve. |
