Skip to content

Commit

Permalink
Implement partial error recovery for let with BinOpEq
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
mibac138 committed May 20, 2020
1 parent f182c4a commit d4fe955
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 2 deletions.
29 changes: 27 additions & 2 deletions src/librustc_parse/parser/stmt.rs
Expand Up @@ -12,7 +12,7 @@ use rustc_ast::ast::{Block, BlockCheckMode, Expr, ExprKind, Local, Stmt, StmtKin
use rustc_ast::ptr::P;
use rustc_ast::token::{self, TokenKind};
use rustc_ast::util::classify;
use rustc_errors::{Applicability, PResult};
use rustc_errors::{struct_span_err, Applicability, PResult};
use rustc_span::source_map::{BytePos, Span};
use rustc_span::symbol::{kw, sym};

Expand Down Expand Up @@ -217,7 +217,32 @@ impl<'a> Parser<'a> {

/// Parses the RHS of a local variable declaration (e.g., '= 14;').
fn parse_initializer(&mut self, skip_eq: bool) -> PResult<'a, Option<P<Expr>>> {
if self.eat(&token::Eq) || skip_eq { Ok(Some(self.parse_expr()?)) } else { Ok(None) }
let parse = if !self.eat(&token::Eq) && !skip_eq {
// Error recovery for `let x += 1`
if matches!(self.token.kind, TokenKind::BinOpEq(_)) {
struct_span_err!(
self.sess.span_diagnostic,
self.token.span,
E0067,
"can't reassign to a uninitialized variable"
)
.span_suggestion_short(
self.token.span,
"replace with `=` to initialize the variable",
"=".to_string(),
Applicability::MaybeIncorrect,
)
.emit();
self.bump();
true
} else {
false
}
} else {
true
};

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

/// Parses a block. No inner attributes are allowed.
Expand Down
7 changes: 7 additions & 0 deletions src/test/ui/parser/let-binop-plus.rs
@@ -0,0 +1,7 @@
#![allow(bare_trait_objects)]

fn main() {
let a: i8 += 1;
//~^ ERROR expected trait, found builtin type `i8`
let _ = a;
}
9 changes: 9 additions & 0 deletions src/test/ui/parser/let-binop-plus.stderr
@@ -0,0 +1,9 @@
error[E0404]: expected trait, found builtin type `i8`
--> $DIR/let-binop-plus.rs:4:12
|
LL | let a: i8 += 1;
| ^^ not a trait

error: aborting due to previous error

For more information about this error, try `rustc --explain E0404`.
8 changes: 8 additions & 0 deletions src/test/ui/parser/let-binop.rs
@@ -0,0 +1,8 @@
fn main() {
let a: i8 *= 1; //~ ERROR can't reassign to a uninitialized variable
let _ = a;
let b += 1; //~ ERROR can't reassign to a uninitialized variable
let _ = b;
let c *= 1; //~ ERROR can't reassign to a uninitialized variable
let _ = c;
}
21 changes: 21 additions & 0 deletions src/test/ui/parser/let-binop.stderr
@@ -0,0 +1,21 @@
error[E0067]: can't reassign to a uninitialized variable
--> $DIR/let-binop.rs:2:15
|
LL | let a: i8 *= 1;
| ^^ help: replace with `=` to initialize the variable

error[E0067]: can't reassign to a uninitialized variable
--> $DIR/let-binop.rs:4:11
|
LL | let b += 1;
| ^^ help: replace with `=` to initialize the variable

error[E0067]: can't reassign to a uninitialized variable
--> $DIR/let-binop.rs:6:11
|
LL | let c *= 1;
| ^^ help: replace with `=` to initialize the variable

error: aborting due to 3 previous errors

For more information about this error, try `rustc --explain E0067`.

0 comments on commit d4fe955

Please sign in to comment.