diff options
Diffstat (limited to 'compiler/rustc_parse/src')
| -rw-r--r-- | compiler/rustc_parse/src/errors.rs | 12 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/diagnostics.rs | 31 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/stmt.rs | 17 |
3 files changed, 47 insertions, 13 deletions
diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 0810f0efef9..b6aeaf3d59f 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -907,6 +907,18 @@ pub(crate) struct SuggRemoveComma { } #[derive(Subdiagnostic)] +#[suggestion( + parse_sugg_add_let_for_stmt, + style = "verbose", + applicability = "maybe-incorrect", + code = "let " +)] +pub(crate) struct SuggAddMissingLetStmt { + #[primary_span] + pub span: Span, +} + +#[derive(Subdiagnostic)] pub(crate) enum ExpectedIdentifierFound { #[label(parse_expected_identifier_found_reserved_identifier)] ReservedIdentifier(#[primary_span] Span), diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 36883bd2172..3002f23da75 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -13,7 +13,7 @@ use crate::errors::{ IncorrectUseOfAwait, ParenthesesInForHead, ParenthesesInForHeadSugg, PatternMethodParamWithoutBody, QuestionMarkInType, QuestionMarkInTypeSugg, SelfParamNotFirst, StructLiteralBodyWithoutPath, StructLiteralBodyWithoutPathSugg, StructLiteralNeedingParens, - StructLiteralNeedingParensSugg, SuggEscapeIdentifier, SuggRemoveComma, + StructLiteralNeedingParensSugg, SuggAddMissingLetStmt, SuggEscapeIdentifier, SuggRemoveComma, UnexpectedConstInGenericParam, UnexpectedConstParamDeclaration, UnexpectedConstParamDeclarationSugg, UnmatchedAngleBrackets, UseEqInstead, }; @@ -32,8 +32,8 @@ use rustc_ast::{ use rustc_ast_pretty::pprust; use rustc_data_structures::fx::FxHashSet; use rustc_errors::{ - pluralize, Applicability, Diagnostic, DiagnosticBuilder, DiagnosticMessage, ErrorGuaranteed, - FatalError, Handler, IntoDiagnostic, MultiSpan, PResult, + pluralize, AddToDiagnostic, Applicability, Diagnostic, DiagnosticBuilder, DiagnosticMessage, + ErrorGuaranteed, FatalError, Handler, IntoDiagnostic, MultiSpan, PResult, }; use rustc_session::errors::ExprParenthesesNeeded; use rustc_span::source_map::Spanned; @@ -1006,6 +1006,31 @@ impl<'a> Parser<'a> { Err(e) } + /// Suggest add the missing `let` before the identifier in stmt + /// `a: Ty = 1` -> `let a: Ty = 1` + pub(super) fn suggest_add_missing_let_for_stmt( + &mut self, + err: &mut DiagnosticBuilder<'a, ErrorGuaranteed>, + ) { + if self.token == token::Colon { + let prev_span = self.prev_token.span.shrink_to_lo(); + let snapshot = self.create_snapshot_for_diagnostic(); + self.bump(); + match self.parse_ty() { + Ok(_) => { + if self.token == token::Eq { + let sugg = SuggAddMissingLetStmt { span: prev_span }; + sugg.add_to_diagnostic(err); + } + } + Err(e) => { + e.cancel(); + } + } + self.restore_snapshot(snapshot); + } + } + /// Check to see if a pair of chained operators looks like an attempt at chained comparison, /// e.g. `1 < x <= 3`. If so, suggest either splitting the comparison into two, or /// parenthesising the leftmost comparison. diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index a0bd086053e..03279124177 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -103,7 +103,13 @@ impl<'a> Parser<'a> { ForceCollect::Yes => { self.collect_tokens_no_attrs(|this| this.parse_stmt_path_start(lo, attrs))? } - ForceCollect::No => self.parse_stmt_path_start(lo, attrs)?, + ForceCollect::No => match self.parse_stmt_path_start(lo, attrs) { + Ok(stmt) => stmt, + Err(mut err) => { + self.suggest_add_missing_let_for_stmt(&mut err); + return Err(err); + } + }, } } else if let Some(item) = self.parse_item_common( attrs.clone(), @@ -559,7 +565,6 @@ impl<'a> Parser<'a> { if self.token == token::Colon { // if next token is following a colon, it's likely a path // and we can suggest a path separator - let ident_span = self.prev_token.span; self.bump(); if self.token.span.lo() == self.prev_token.span.hi() { err.span_suggestion_verbose( @@ -569,14 +574,6 @@ impl<'a> Parser<'a> { Applicability::MaybeIncorrect, ); } - if self.look_ahead(1, |token| token == &token::Eq) { - err.span_suggestion_verbose( - ident_span.shrink_to_lo(), - "you might have meant to introduce a new binding", - "let ", - Applicability::MaybeIncorrect, - ); - } if self.sess.unstable_features.is_nightly_build() { // FIXME(Nilstrieb): Remove this again after a few months. err.note("type ascription syntax has been removed, see issue #101728 <https://github.com/rust-lang/rust/issues/101728>"); |
