Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Suggest let for possible binding with ty #111120

Merged
merged 5 commits into from
May 9, 2023
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion compiler/rustc_macros/src/diagnostics/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ pub fn lint_diagnostic_derive(s: Structure<'_>) -> TokenStream {
/// ```fluent
/// parser_expected_identifier = expected identifier
///
/// parser_expected_identifier-found = expected identifier, found {$found}
/// parser_expected_identifier_found = expected identifier, found {$found}
///
/// parser_raw_identifier = escape `{$ident}` to use it as an identifier
/// ```
Expand Down
29 changes: 29 additions & 0 deletions compiler/rustc_parse/src/parser/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1006,6 +1006,35 @@ 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 {
err.span_suggestion_verbose(
prev_span,
"you might have meant to introduce a new binding",
chenyukang marked this conversation as resolved.
Show resolved Hide resolved
"let ".to_string(),
Applicability::MaybeIncorrect,
);
}
}
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.
Expand Down
17 changes: 7 additions & 10 deletions compiler/rustc_parse/src/parser/stmt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,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(),
Expand Down Expand Up @@ -555,7 +561,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(
Expand All @@ -565,14 +570,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>");
Expand Down
11 changes: 11 additions & 0 deletions tests/ui/suggestions/type-ascription-instead-of-let.fixed
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// run-rustfix

fn fun(x: i32) -> i32 { x }

fn main() {
let _closure_annotated = |value: i32| -> i32 {
let temp: i32 = fun(5i32);
//~^ ERROR expected identifier, found `:`
temp + value + 1
};
}
4 changes: 3 additions & 1 deletion tests/ui/suggestions/type-ascription-instead-of-let.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
// run-rustfix

fn fun(x: i32) -> i32 { x }

fn main() {
let closure_annotated = |value: i32| -> i32 {
let _closure_annotated = |value: i32| -> i32 {
temp: i32 = fun(5i32);
//~^ ERROR expected identifier, found `:`
temp + value + 1
Expand Down
7 changes: 6 additions & 1 deletion tests/ui/suggestions/type-ascription-instead-of-let.stderr
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
error: expected identifier, found `:`
--> $DIR/type-ascription-instead-of-let.rs:5:13
--> $DIR/type-ascription-instead-of-let.rs:7:13
|
LL | temp: i32 = fun(5i32);
| ^ expected identifier
|
help: you might have meant to introduce a new binding
|
LL | let temp: i32 = fun(5i32);
| +++

error: aborting due to previous error

5 changes: 5 additions & 0 deletions tests/ui/type/missing-let-in-binding-2.fixed
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// run-rustfix

fn main() {
let _v: Vec<i32> = vec![1, 2, 3]; //~ ERROR expected identifier, found `:`
}
5 changes: 5 additions & 0 deletions tests/ui/type/missing-let-in-binding-2.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// run-rustfix

fn main() {
_v: Vec<i32> = vec![1, 2, 3]; //~ ERROR expected identifier, found `:`
}
13 changes: 13 additions & 0 deletions tests/ui/type/missing-let-in-binding-2.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
error: expected identifier, found `:`
--> $DIR/missing-let-in-binding-2.rs:4:7
|
LL | _v: Vec<i32> = vec![1, 2, 3];
| ^ expected identifier
|
help: you might have meant to introduce a new binding
|
LL | let _v: Vec<i32> = vec![1, 2, 3];
| +++

error: aborting due to previous error

5 changes: 5 additions & 0 deletions tests/ui/type/missing-let-in-binding-3.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
struct A {
: :u8, //~ ERROR expected identifier, found `:`
}

fn main() {}
10 changes: 10 additions & 0 deletions tests/ui/type/missing-let-in-binding-3.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
error: expected identifier, found `:`
--> $DIR/missing-let-in-binding-3.rs:2:5
|
LL | struct A {
| - while parsing this struct
LL | : :u8,
| ^ expected identifier

error: aborting due to previous error

5 changes: 5 additions & 0 deletions tests/ui/type/missing-let-in-binding-4.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
struct A {
: u8 =, //~ ERROR expected identifier, found `:`
}

fn main() {}
10 changes: 10 additions & 0 deletions tests/ui/type/missing-let-in-binding-4.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
error: expected identifier, found `:`
--> $DIR/missing-let-in-binding-4.rs:2:5
|
LL | struct A {
| - while parsing this struct
LL | : u8 =,
| ^ expected identifier

error: aborting due to previous error