Skip to content

Commit 05d6531

Browse files
committed
Error recovery for let with +=
1 parent 48ff12a commit 05d6531

File tree

3 files changed

+42
-35
lines changed

3 files changed

+42
-35
lines changed

src/librustc_parse/parser/stmt.rs

+32-33
Original file line numberDiff line numberDiff line change
@@ -222,44 +222,43 @@ impl<'a> Parser<'a> {
222222
has_ty: bool,
223223
skip_eq: bool,
224224
) -> PResult<'a, Option<P<Expr>>> {
225-
let parse = if !self.eat(&token::Eq) && !skip_eq {
225+
// In case of code like `let x: i8 += 1`, `i8` is interpreted as a trait consuming the `+`
226+
// from `+=`.
227+
let ate_plus = self.prev_token.is_like_plus() && has_ty;
228+
let parse = if !skip_eq && (ate_plus || matches!(self.token.kind, TokenKind::BinOpEq(_))) {
226229
// Error recovery for `let x += 1`
227-
if matches!(self.token.kind, TokenKind::BinOpEq(_)) {
228-
let mut err = struct_span_err!(
229-
self.sess.span_diagnostic,
230-
self.token.span,
231-
E0067,
232-
"can't reassign to a uninitialized variable"
233-
);
230+
let mut err = struct_span_err!(
231+
self.sess.span_diagnostic,
232+
self.token.span,
233+
E0067,
234+
"can't reassign to a uninitialized variable"
235+
);
236+
err.span_suggestion_short(
237+
self.token.span,
238+
"replace with `=` to initialize the variable",
239+
"=".to_string(),
240+
if has_ty {
241+
// for `let x: i8 += 1` it's highly likely that the `+` is a typo
242+
Applicability::MachineApplicable
243+
} else {
244+
// for `let x += 1` it's a bit less likely that the `+` is a typo
245+
Applicability::MaybeIncorrect
246+
},
247+
);
248+
// In case of code like `let x += 1` it's possible the user may have meant to write `x += 1`
249+
if !has_ty {
234250
err.span_suggestion_short(
235-
self.token.span,
236-
"replace with `=` to initialize the variable",
237-
"=".to_string(),
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-
},
251+
let_span,
252+
"remove to reassign to a previously initialized variable",
253+
"".to_string(),
254+
Applicability::MaybeIncorrect,
245255
);
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();
256-
self.bump();
257-
true
258-
} else {
259-
false
260256
}
261-
} else {
257+
err.emit();
258+
self.bump();
262259
true
260+
} else {
261+
self.eat(&token::Eq) || skip_eq
263262
};
264263

265264
if parse { Ok(Some(self.parse_expr()?)) } else { Ok(None) }

src/test/ui/parser/let-binop-plus.rs

+1
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,6 @@
33
fn main() {
44
let a: i8 += 1;
55
//~^ ERROR expected trait, found builtin type `i8`
6+
//~| ERROR can't reassign to a uninitialized variable
67
let _ = a;
78
}
+9-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,16 @@
1+
error[E0067]: can't reassign to a uninitialized variable
2+
--> $DIR/let-binop-plus.rs:4:16
3+
|
4+
LL | let a: i8 += 1;
5+
| ^ help: replace with `=` to initialize the variable
6+
17
error[E0404]: expected trait, found builtin type `i8`
28
--> $DIR/let-binop-plus.rs:4:12
39
|
410
LL | let a: i8 += 1;
511
| ^^ not a trait
612

7-
error: aborting due to previous error
13+
error: aborting due to 2 previous errors
814

9-
For more information about this error, try `rustc --explain E0404`.
15+
Some errors have detailed explanations: E0067, E0404.
16+
For more information about an error, try `rustc --explain E0067`.

0 commit comments

Comments
 (0)