Skip to content

Commit d4fe955

Browse files
committed
Implement partial error recovery for let with BinOpEq
When parsing `let x: i8 += 1` the compiler interprets `i8` as a trait which makes it more complicated to do error recovery. More advanced error recovery is not implemented in this commit.
1 parent f182c4a commit d4fe955

File tree

5 files changed

+72
-2
lines changed

5 files changed

+72
-2
lines changed

src/librustc_parse/parser/stmt.rs

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use rustc_ast::ast::{Block, BlockCheckMode, Expr, ExprKind, Local, Stmt, StmtKin
1212
use rustc_ast::ptr::P;
1313
use rustc_ast::token::{self, TokenKind};
1414
use rustc_ast::util::classify;
15-
use rustc_errors::{Applicability, PResult};
15+
use rustc_errors::{struct_span_err, Applicability, PResult};
1616
use rustc_span::source_map::{BytePos, Span};
1717
use rustc_span::symbol::{kw, sym};
1818

@@ -217,7 +217,32 @@ impl<'a> Parser<'a> {
217217

218218
/// Parses the RHS of a local variable declaration (e.g., '= 14;').
219219
fn parse_initializer(&mut self, skip_eq: bool) -> PResult<'a, Option<P<Expr>>> {
220-
if self.eat(&token::Eq) || skip_eq { Ok(Some(self.parse_expr()?)) } else { Ok(None) }
220+
let parse = if !self.eat(&token::Eq) && !skip_eq {
221+
// Error recovery for `let x += 1`
222+
if matches!(self.token.kind, TokenKind::BinOpEq(_)) {
223+
struct_span_err!(
224+
self.sess.span_diagnostic,
225+
self.token.span,
226+
E0067,
227+
"can't reassign to a uninitialized variable"
228+
)
229+
.span_suggestion_short(
230+
self.token.span,
231+
"replace with `=` to initialize the variable",
232+
"=".to_string(),
233+
Applicability::MaybeIncorrect,
234+
)
235+
.emit();
236+
self.bump();
237+
true
238+
} else {
239+
false
240+
}
241+
} else {
242+
true
243+
};
244+
245+
if parse { Ok(Some(self.parse_expr()?)) } else { Ok(None) }
221246
}
222247

223248
/// Parses a block. No inner attributes are allowed.

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#![allow(bare_trait_objects)]
2+
3+
fn main() {
4+
let a: i8 += 1;
5+
//~^ ERROR expected trait, found builtin type `i8`
6+
let _ = a;
7+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
error[E0404]: expected trait, found builtin type `i8`
2+
--> $DIR/let-binop-plus.rs:4:12
3+
|
4+
LL | let a: i8 += 1;
5+
| ^^ not a trait
6+
7+
error: aborting due to previous error
8+
9+
For more information about this error, try `rustc --explain E0404`.

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
fn main() {
2+
let a: i8 *= 1; //~ ERROR can't reassign to a uninitialized variable
3+
let _ = a;
4+
let b += 1; //~ ERROR can't reassign to a uninitialized variable
5+
let _ = b;
6+
let c *= 1; //~ ERROR can't reassign to a uninitialized variable
7+
let _ = c;
8+
}

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

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
error[E0067]: can't reassign to a uninitialized variable
2+
--> $DIR/let-binop.rs:2:15
3+
|
4+
LL | let a: i8 *= 1;
5+
| ^^ help: replace with `=` to initialize the variable
6+
7+
error[E0067]: can't reassign to a uninitialized variable
8+
--> $DIR/let-binop.rs:4:11
9+
|
10+
LL | let b += 1;
11+
| ^^ help: replace with `=` to initialize the variable
12+
13+
error[E0067]: can't reassign to a uninitialized variable
14+
--> $DIR/let-binop.rs:6:11
15+
|
16+
LL | let c *= 1;
17+
| ^^ help: replace with `=` to initialize the variable
18+
19+
error: aborting due to 3 previous errors
20+
21+
For more information about this error, try `rustc --explain E0067`.

0 commit comments

Comments
 (0)