Skip to content

Commit 48ff12a

Browse files
committed
Expand partial error recovery for let with BinOpEq
1 parent d4fe955 commit 48ff12a

File tree

2 files changed

+50
-12
lines changed

2 files changed

+50
-12
lines changed

src/librustc_parse/parser/stmt.rs

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -145,12 +145,12 @@ impl<'a> Parser<'a> {
145145
}
146146

147147
fn parse_local_mk(&mut self, lo: Span, attrs: AttrVec) -> PResult<'a, Stmt> {
148-
let local = self.parse_local(attrs)?;
148+
let local = self.parse_local(lo, attrs)?;
149149
Ok(self.mk_stmt(lo.to(self.prev_token.span), StmtKind::Local(local)))
150150
}
151151

152152
/// Parses a local variable declaration.
153-
fn parse_local(&mut self, attrs: AttrVec) -> PResult<'a, P<Local>> {
153+
fn parse_local(&mut self, let_span: Span, attrs: AttrVec) -> PResult<'a, P<Local>> {
154154
let lo = self.prev_token.span;
155155
let pat = self.parse_top_pat(GateOr::Yes)?;
156156

@@ -174,7 +174,7 @@ impl<'a> Parser<'a> {
174174
} else {
175175
(None, None)
176176
};
177-
let init = match (self.parse_initializer(err.is_some()), err) {
177+
let init = match (self.parse_initializer(let_span, ty.is_some(), err.is_some()), err) {
178178
(Ok(init), None) => {
179179
// init parsed, ty parsed
180180
init
@@ -216,23 +216,43 @@ impl<'a> Parser<'a> {
216216
}
217217

218218
/// Parses the RHS of a local variable declaration (e.g., '= 14;').
219-
fn parse_initializer(&mut self, skip_eq: bool) -> PResult<'a, Option<P<Expr>>> {
219+
fn parse_initializer(
220+
&mut self,
221+
let_span: Span,
222+
has_ty: bool,
223+
skip_eq: bool,
224+
) -> PResult<'a, Option<P<Expr>>> {
220225
let parse = if !self.eat(&token::Eq) && !skip_eq {
221226
// Error recovery for `let x += 1`
222227
if matches!(self.token.kind, TokenKind::BinOpEq(_)) {
223-
struct_span_err!(
228+
let mut err = struct_span_err!(
224229
self.sess.span_diagnostic,
225230
self.token.span,
226231
E0067,
227232
"can't reassign to a uninitialized variable"
228-
)
229-
.span_suggestion_short(
233+
);
234+
err.span_suggestion_short(
230235
self.token.span,
231236
"replace with `=` to initialize the variable",
232237
"=".to_string(),
233-
Applicability::MaybeIncorrect,
234-
)
235-
.emit();
238+
if has_ty {
239+
// for `let x: i8 += 1` it's highly likely that the `+` is a typo
240+
Applicability::MachineApplicable
241+
} else {
242+
// for `let x += 1` it's a bit less likely that the `+` is a typo
243+
Applicability::MaybeIncorrect
244+
},
245+
);
246+
// In case of code like `let x += 1` it's possible the user may have meant to write `x += 1`
247+
if !has_ty {
248+
err.span_suggestion_short(
249+
let_span,
250+
"remove to reassign to a previously initialized variable",
251+
"".to_string(),
252+
Applicability::MaybeIncorrect,
253+
);
254+
}
255+
err.emit();
236256
self.bump();
237257
true
238258
} else {

src/test/ui/parser/let-binop.stderr

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,31 @@ error[E0067]: can't reassign to a uninitialized variable
88
--> $DIR/let-binop.rs:4:11
99
|
1010
LL | let b += 1;
11-
| ^^ help: replace with `=` to initialize the variable
11+
| ^^
12+
|
13+
help: replace with `=` to initialize the variable
14+
|
15+
LL | let b = 1;
16+
| ^
17+
help: remove to reassign to a previously initialized variable
18+
|
19+
LL | b += 1;
20+
| --
1221

1322
error[E0067]: can't reassign to a uninitialized variable
1423
--> $DIR/let-binop.rs:6:11
1524
|
1625
LL | let c *= 1;
17-
| ^^ help: replace with `=` to initialize the variable
26+
| ^^
27+
|
28+
help: replace with `=` to initialize the variable
29+
|
30+
LL | let c = 1;
31+
| ^
32+
help: remove to reassign to a previously initialized variable
33+
|
34+
LL | c *= 1;
35+
| --
1836

1937
error: aborting due to 3 previous errors
2038

0 commit comments

Comments
 (0)