Skip to content

Commit 8c51701

Browse files
authored
Rollup merge of #111120 - chenyukang:yukang-suggest-let, r=Nilstrieb
Suggest let for possible binding with ty Origin from #109128 (comment) r? `@Nilstrieb`
2 parents dbd090c + 4d219d0 commit 8c51701

15 files changed

+122
-16
lines changed

compiler/rustc_macros/src/diagnostics/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ pub fn lint_diagnostic_derive(s: Structure<'_>) -> TokenStream {
140140
/// ```fluent
141141
/// parser_expected_identifier = expected identifier
142142
///
143-
/// parser_expected_identifier-found = expected identifier, found {$found}
143+
/// parser_expected_identifier_found = expected identifier, found {$found}
144144
///
145145
/// parser_raw_identifier = escape `{$ident}` to use it as an identifier
146146
/// ```

compiler/rustc_parse/messages.ftl

+1
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,7 @@ parse_expected_identifier = expected identifier
343343
parse_sugg_escape_identifier = escape `{$ident_name}` to use it as an identifier
344344
345345
parse_sugg_remove_comma = remove this comma
346+
parse_sugg_add_let_for_stmt = you might have meant to introduce a new binding
346347
347348
parse_expected_semi_found_reserved_identifier_str = expected `;`, found reserved identifier `{$token}`
348349
parse_expected_semi_found_keyword_str = expected `;`, found keyword `{$token}`

compiler/rustc_parse/src/errors.rs

+12
Original file line numberDiff line numberDiff line change
@@ -906,6 +906,18 @@ pub(crate) struct SuggRemoveComma {
906906
pub span: Span,
907907
}
908908

909+
#[derive(Subdiagnostic)]
910+
#[suggestion(
911+
parse_sugg_add_let_for_stmt,
912+
style = "verbose",
913+
applicability = "maybe-incorrect",
914+
code = "let "
915+
)]
916+
pub(crate) struct SuggAddMissingLetStmt {
917+
#[primary_span]
918+
pub span: Span,
919+
}
920+
909921
#[derive(Subdiagnostic)]
910922
pub(crate) enum ExpectedIdentifierFound {
911923
#[label(parse_expected_identifier_found_reserved_identifier)]

compiler/rustc_parse/src/parser/diagnostics.rs

+28-3
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use crate::errors::{
1313
IncorrectUseOfAwait, ParenthesesInForHead, ParenthesesInForHeadSugg,
1414
PatternMethodParamWithoutBody, QuestionMarkInType, QuestionMarkInTypeSugg, SelfParamNotFirst,
1515
StructLiteralBodyWithoutPath, StructLiteralBodyWithoutPathSugg, StructLiteralNeedingParens,
16-
StructLiteralNeedingParensSugg, SuggEscapeIdentifier, SuggRemoveComma,
16+
StructLiteralNeedingParensSugg, SuggAddMissingLetStmt, SuggEscapeIdentifier, SuggRemoveComma,
1717
UnexpectedConstInGenericParam, UnexpectedConstParamDeclaration,
1818
UnexpectedConstParamDeclarationSugg, UnmatchedAngleBrackets, UseEqInstead,
1919
};
@@ -32,8 +32,8 @@ use rustc_ast::{
3232
use rustc_ast_pretty::pprust;
3333
use rustc_data_structures::fx::FxHashSet;
3434
use rustc_errors::{
35-
pluralize, Applicability, Diagnostic, DiagnosticBuilder, DiagnosticMessage, ErrorGuaranteed,
36-
FatalError, Handler, IntoDiagnostic, MultiSpan, PResult,
35+
pluralize, AddToDiagnostic, Applicability, Diagnostic, DiagnosticBuilder, DiagnosticMessage,
36+
ErrorGuaranteed, FatalError, Handler, IntoDiagnostic, MultiSpan, PResult,
3737
};
3838
use rustc_session::errors::ExprParenthesesNeeded;
3939
use rustc_span::source_map::Spanned;
@@ -1006,6 +1006,31 @@ impl<'a> Parser<'a> {
10061006
Err(e)
10071007
}
10081008

1009+
/// Suggest add the missing `let` before the identifier in stmt
1010+
/// `a: Ty = 1` -> `let a: Ty = 1`
1011+
pub(super) fn suggest_add_missing_let_for_stmt(
1012+
&mut self,
1013+
err: &mut DiagnosticBuilder<'a, ErrorGuaranteed>,
1014+
) {
1015+
if self.token == token::Colon {
1016+
let prev_span = self.prev_token.span.shrink_to_lo();
1017+
let snapshot = self.create_snapshot_for_diagnostic();
1018+
self.bump();
1019+
match self.parse_ty() {
1020+
Ok(_) => {
1021+
if self.token == token::Eq {
1022+
let sugg = SuggAddMissingLetStmt { span: prev_span };
1023+
sugg.add_to_diagnostic(err);
1024+
}
1025+
}
1026+
Err(e) => {
1027+
e.cancel();
1028+
}
1029+
}
1030+
self.restore_snapshot(snapshot);
1031+
}
1032+
}
1033+
10091034
/// Check to see if a pair of chained operators looks like an attempt at chained comparison,
10101035
/// e.g. `1 < x <= 3`. If so, suggest either splitting the comparison into two, or
10111036
/// parenthesising the leftmost comparison.

compiler/rustc_parse/src/parser/stmt.rs

+7-10
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,13 @@ impl<'a> Parser<'a> {
103103
ForceCollect::Yes => {
104104
self.collect_tokens_no_attrs(|this| this.parse_stmt_path_start(lo, attrs))?
105105
}
106-
ForceCollect::No => self.parse_stmt_path_start(lo, attrs)?,
106+
ForceCollect::No => match self.parse_stmt_path_start(lo, attrs) {
107+
Ok(stmt) => stmt,
108+
Err(mut err) => {
109+
self.suggest_add_missing_let_for_stmt(&mut err);
110+
return Err(err);
111+
}
112+
},
107113
}
108114
} else if let Some(item) = self.parse_item_common(
109115
attrs.clone(),
@@ -559,7 +565,6 @@ impl<'a> Parser<'a> {
559565
if self.token == token::Colon {
560566
// if next token is following a colon, it's likely a path
561567
// and we can suggest a path separator
562-
let ident_span = self.prev_token.span;
563568
self.bump();
564569
if self.token.span.lo() == self.prev_token.span.hi() {
565570
err.span_suggestion_verbose(
@@ -569,14 +574,6 @@ impl<'a> Parser<'a> {
569574
Applicability::MaybeIncorrect,
570575
);
571576
}
572-
if self.look_ahead(1, |token| token == &token::Eq) {
573-
err.span_suggestion_verbose(
574-
ident_span.shrink_to_lo(),
575-
"you might have meant to introduce a new binding",
576-
"let ",
577-
Applicability::MaybeIncorrect,
578-
);
579-
}
580577
if self.sess.unstable_features.is_nightly_build() {
581578
// FIXME(Nilstrieb): Remove this again after a few months.
582579
err.note("type ascription syntax has been removed, see issue #101728 <https://github.com/rust-lang/rust/issues/101728>");
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// run-rustfix
2+
3+
fn fun(x: i32) -> i32 { x }
4+
5+
fn main() {
6+
let _closure_annotated = |value: i32| -> i32 {
7+
let temp: i32 = fun(5i32);
8+
//~^ ERROR expected identifier, found `:`
9+
temp + value + 1
10+
};
11+
}

tests/ui/suggestions/type-ascription-instead-of-let.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1+
// run-rustfix
2+
13
fn fun(x: i32) -> i32 { x }
24

35
fn main() {
4-
let closure_annotated = |value: i32| -> i32 {
6+
let _closure_annotated = |value: i32| -> i32 {
57
temp: i32 = fun(5i32);
68
//~^ ERROR expected identifier, found `:`
79
temp + value + 1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
11
error: expected identifier, found `:`
2-
--> $DIR/type-ascription-instead-of-let.rs:5:13
2+
--> $DIR/type-ascription-instead-of-let.rs:7:13
33
|
44
LL | temp: i32 = fun(5i32);
55
| ^ expected identifier
6+
|
7+
help: you might have meant to introduce a new binding
8+
|
9+
LL | let temp: i32 = fun(5i32);
10+
| +++
611

712
error: aborting due to previous error
813

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// run-rustfix
2+
3+
fn main() {
4+
let _v: Vec<i32> = vec![1, 2, 3]; //~ ERROR expected identifier, found `:`
5+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// run-rustfix
2+
3+
fn main() {
4+
_v: Vec<i32> = vec![1, 2, 3]; //~ ERROR expected identifier, found `:`
5+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
error: expected identifier, found `:`
2+
--> $DIR/missing-let-in-binding-2.rs:4:7
3+
|
4+
LL | _v: Vec<i32> = vec![1, 2, 3];
5+
| ^ expected identifier
6+
|
7+
help: you might have meant to introduce a new binding
8+
|
9+
LL | let _v: Vec<i32> = vec![1, 2, 3];
10+
| +++
11+
12+
error: aborting due to previous error
13+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
struct A {
2+
: :u8, //~ ERROR expected identifier, found `:`
3+
}
4+
5+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
error: expected identifier, found `:`
2+
--> $DIR/missing-let-in-binding-3.rs:2:5
3+
|
4+
LL | struct A {
5+
| - while parsing this struct
6+
LL | : :u8,
7+
| ^ expected identifier
8+
9+
error: aborting due to previous error
10+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
struct A {
2+
: u8 =, //~ ERROR expected identifier, found `:`
3+
}
4+
5+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
error: expected identifier, found `:`
2+
--> $DIR/missing-let-in-binding-4.rs:2:5
3+
|
4+
LL | struct A {
5+
| - while parsing this struct
6+
LL | : u8 =,
7+
| ^ expected identifier
8+
9+
error: aborting due to previous error
10+

0 commit comments

Comments
 (0)