refactor: improve "ident starts with number" error
This commit is contained in:
parent
c9ddb73184
commit
b4e17a5098
@ -986,7 +986,10 @@ impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for ExpectedIdentifier {
|
|||||||
|
|
||||||
#[derive(Subdiagnostic)]
|
#[derive(Subdiagnostic)]
|
||||||
#[help(parse_invalid_identifier_with_leading_number)]
|
#[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(crate) struct ExpectedSemi {
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
|
@ -38,7 +38,7 @@ use rustc_errors::{
|
|||||||
use rustc_session::errors::ExprParenthesesNeeded;
|
use rustc_session::errors::ExprParenthesesNeeded;
|
||||||
use rustc_span::source_map::Spanned;
|
use rustc_span::source_map::Spanned;
|
||||||
use rustc_span::symbol::{kw, sym, Ident};
|
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::mem::take;
|
||||||
use std::ops::{Deref, DerefMut};
|
use std::ops::{Deref, DerefMut};
|
||||||
use thin_vec::{thin_vec, ThinVec};
|
use thin_vec::{thin_vec, ThinVec};
|
||||||
@ -309,8 +309,11 @@ impl<'a> Parser<'a> {
|
|||||||
&& self.look_ahead(1, |t| t.is_ident()))
|
&& self.look_ahead(1, |t| t.is_ident()))
|
||||||
.then_some(SuggRemoveComma { span: self.token.span });
|
.then_some(SuggRemoveComma { span: self.token.span });
|
||||||
|
|
||||||
let help_cannot_start_number =
|
let help_cannot_start_number = self.is_lit_bad_ident().map(|(len, _valid_portion)| {
|
||||||
self.is_lit_bad_ident().then_some(HelpIdentifierStartsWithNumber);
|
let (invalid, _valid) = self.token.span.split_at(len as u32);
|
||||||
|
|
||||||
|
HelpIdentifierStartsWithNumber { num_span: invalid }
|
||||||
|
});
|
||||||
|
|
||||||
let err = ExpectedIdentifier {
|
let err = ExpectedIdentifier {
|
||||||
span: self.token.span,
|
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
|
/// 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.
|
/// 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, .. })
|
/// Returns the number of characters (bytes) composing the invalid portion
|
||||||
// ensure that the integer literal is followed by a *invalid*
|
/// of the identifier and the valid portion of the identifier.
|
||||||
// suffix: this is how we know that it is a identifier with an
|
pub(super) fn is_lit_bad_ident(&mut self) -> Option<(usize, Symbol)> {
|
||||||
// invalid beginning.
|
// ensure that the integer literal is followed by a *invalid*
|
||||||
if rustc_ast::MetaItemLit::from_token(&self.token).is_none()
|
// 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(
|
pub(super) fn expected_one_of_not_found(
|
||||||
|
@ -348,10 +348,6 @@ impl<'a> Parser<'a> {
|
|||||||
lo = self.token.span;
|
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 {
|
let pat = if self.check(&token::BinOp(token::And)) || self.token.kind == token::AndAnd {
|
||||||
self.parse_pat_deref(expected)?
|
self.parse_pat_deref(expected)?
|
||||||
} else if self.check(&token::OpenDelim(Delimiter::Parenthesis)) {
|
} else if self.check(&token::OpenDelim(Delimiter::Parenthesis)) {
|
||||||
@ -395,7 +391,7 @@ impl<'a> Parser<'a> {
|
|||||||
} else {
|
} else {
|
||||||
PatKind::Lit(const_expr)
|
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`
|
// Parse `ident @ pat`
|
||||||
// This can give false positives and parse nullary enums,
|
// This can give false positives and parse nullary enums,
|
||||||
// they are dealt with later in resolve.
|
// they are dealt with later in resolve.
|
||||||
|
@ -795,6 +795,18 @@ impl Span {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Splits a span into two composite spans around a certain position.
|
||||||
|
pub fn split_at(self, pos: u32) -> (Span, Span) {
|
||||||
|
let len = self.hi().0 - self.lo().0;
|
||||||
|
debug_assert!(pos <= len);
|
||||||
|
|
||||||
|
let split_pos = BytePos(self.lo().0 + pos);
|
||||||
|
(
|
||||||
|
Span::new(self.lo(), split_pos, self.ctxt(), self.parent()),
|
||||||
|
Span::new(split_pos, self.hi(), self.ctxt(), self.parent()),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns a `Span` that would enclose both `self` and `end`.
|
/// Returns a `Span` that would enclose both `self` and `end`.
|
||||||
///
|
///
|
||||||
/// Note that this can also be used to extend the span "backwards":
|
/// Note that this can also be used to extend the span "backwards":
|
||||||
|
@ -4,7 +4,11 @@ error: expected identifier, found `1main`
|
|||||||
LL | fn 1main() {}
|
LL | fn 1main() {}
|
||||||
| ^^^^^ expected identifier
|
| ^^^^^ expected identifier
|
||||||
|
|
|
|
||||||
= help: identifiers cannot start with a number
|
help: identifiers cannot start with a number
|
||||||
|
--> $DIR/integer-literal-start-ident.rs:1:4
|
||||||
|
|
|
||||||
|
LL | fn 1main() {}
|
||||||
|
| ^
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
@ -4,7 +4,11 @@ error: expected identifier, found `1x`
|
|||||||
LL | let 1x = 123;
|
LL | let 1x = 123;
|
||||||
| ^^ expected identifier
|
| ^^ expected identifier
|
||||||
|
|
|
|
||||||
= help: identifiers cannot start with a number
|
help: identifiers cannot start with a number
|
||||||
|
--> $DIR/issue-104088.rs:6:9
|
||||||
|
|
|
||||||
|
LL | let 1x = 123;
|
||||||
|
| ^
|
||||||
|
|
||||||
error: expected identifier, found `2x`
|
error: expected identifier, found `2x`
|
||||||
--> $DIR/issue-104088.rs:11:9
|
--> $DIR/issue-104088.rs:11:9
|
||||||
@ -12,7 +16,11 @@ error: expected identifier, found `2x`
|
|||||||
LL | let 2x: i32 = 123;
|
LL | let 2x: i32 = 123;
|
||||||
| ^^ expected identifier
|
| ^^ expected identifier
|
||||||
|
|
|
|
||||||
= help: identifiers cannot start with a number
|
help: identifiers cannot start with a number
|
||||||
|
--> $DIR/issue-104088.rs:11:9
|
||||||
|
|
|
||||||
|
LL | let 2x: i32 = 123;
|
||||||
|
| ^
|
||||||
|
|
||||||
error: expected identifier, found `23name`
|
error: expected identifier, found `23name`
|
||||||
--> $DIR/issue-104088.rs:22:9
|
--> $DIR/issue-104088.rs:22:9
|
||||||
@ -20,7 +28,11 @@ error: expected identifier, found `23name`
|
|||||||
LL | let 23name = 123;
|
LL | let 23name = 123;
|
||||||
| ^^^^^^ expected identifier
|
| ^^^^^^ expected identifier
|
||||||
|
|
|
|
||||||
= help: identifiers cannot start with a number
|
help: identifiers cannot start with a number
|
||||||
|
--> $DIR/issue-104088.rs:22:9
|
||||||
|
|
|
||||||
|
LL | let 23name = 123;
|
||||||
|
| ^^
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/issue-104088.rs:16:12
|
--> $DIR/issue-104088.rs:16:12
|
||||||
|
Loading…
x
Reference in New Issue
Block a user