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.
This commit is contained in:
parent
f182c4af8a
commit
d4fe9553f6
5 changed files with 72 additions and 2 deletions
|
@ -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};
|
||||
|
||||
|
@ -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.
|
||||
|
|
7
src/test/ui/parser/let-binop-plus.rs
Normal file
7
src/test/ui/parser/let-binop-plus.rs
Normal file
|
@ -0,0 +1,7 @@
|
|||
#![allow(bare_trait_objects)]
|
||||
|
||||
fn main() {
|
||||
let a: i8 += 1;
|
||||
//~^ ERROR expected trait, found builtin type `i8`
|
||||
let _ = a;
|
||||
}
|
9
src/test/ui/parser/let-binop-plus.stderr
Normal file
9
src/test/ui/parser/let-binop-plus.stderr
Normal file
|
@ -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
src/test/ui/parser/let-binop.rs
Normal file
8
src/test/ui/parser/let-binop.rs
Normal file
|
@ -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
src/test/ui/parser/let-binop.stderr
Normal file
21
src/test/ui/parser/let-binop.stderr
Normal file
|
@ -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`.
|
Loading…
Add table
Add a link
Reference in a new issue