diff --git a/src/librustc_parse/parser/stmt.rs b/src/librustc_parse/parser/stmt.rs index bec810fde081d..53f32b7c800bd 100644 --- a/src/librustc_parse/parser/stmt.rs +++ b/src/librustc_parse/parser/stmt.rs @@ -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::{struct_span_err, Applicability, PResult}; +use rustc_errors::{Applicability, PResult}; use rustc_span::source_map::{BytePos, Span}; use rustc_span::symbol::{kw, sym}; @@ -145,12 +145,12 @@ impl<'a> Parser<'a> { } fn parse_local_mk(&mut self, lo: Span, attrs: AttrVec) -> PResult<'a, Stmt> { - let local = self.parse_local(lo, attrs)?; + let local = self.parse_local(attrs)?; Ok(self.mk_stmt(lo.to(self.prev_token.span), StmtKind::Local(local))) } /// Parses a local variable declaration. - fn parse_local(&mut self, let_span: Span, attrs: AttrVec) -> PResult<'a, P> { + fn parse_local(&mut self, attrs: AttrVec) -> PResult<'a, P> { let lo = self.prev_token.span; let pat = self.parse_top_pat(GateOr::Yes)?; @@ -174,10 +174,7 @@ impl<'a> Parser<'a> { } else { (None, None) }; - let init = match ( - self.parse_initializer(let_span.until(pat.span), ty.is_some(), err.is_some()), - err, - ) { + let init = match (self.parse_initializer(err.is_some()), err) { (Ok(init), None) => { // init parsed, ty parsed init @@ -219,46 +216,28 @@ impl<'a> Parser<'a> { } /// Parses the RHS of a local variable declaration (e.g., '= 14;'). - fn parse_initializer( - &mut self, - let_span: Span, - has_ty: bool, - skip_eq: bool, - ) -> PResult<'a, Option>> { - // In case of code like `let x: i8 += 1`, `i8` is interpreted as a trait consuming the `+` - // from `+=`. - let ate_plus = self.prev_token.is_like_plus() && has_ty; - let parse = if !skip_eq && (ate_plus || matches!(self.token.kind, TokenKind::BinOpEq(_))) { - // Error recovery for `let x += 1` - let mut err = struct_span_err!( - self.sess.span_diagnostic, - self.token.span, - E0067, - "can't reassign to an uninitialized variable" - ); - err.span_suggestion_short( - self.token.span, - "initialize the variable", - "=".to_string(), - Applicability::MaybeIncorrect, - ); - // In case of code like `let x += 1` it's possible the user may have meant to write `x += 1` - if !has_ty { - err.span_suggestion_short( - let_span, - "otherwise, reassign to a previously initialized variable", - "".to_string(), + fn parse_initializer(&mut self, eq_optional: bool) -> PResult<'a, Option>> { + let eq_consumed = match self.token.kind { + token::BinOpEq(..) => { + // Recover `let x = 1` as `let x = 1` + self.struct_span_err( + self.token.span, + "can't reassign to an uninitialized variable", + ) + .span_suggestion_short( + self.token.span, + "initialize the variable", + "=".to_string(), Applicability::MaybeIncorrect, - ); + ) + .emit(); + self.bump(); + true } - err.emit(); - self.bump(); - true - } else { - self.eat(&token::Eq) || skip_eq + _ => self.eat(&token::Eq), }; - if parse { Ok(Some(self.parse_expr()?)) } else { Ok(None) } + Ok(if eq_consumed || eq_optional { Some(self.parse_expr()?) } else { None }) } /// Parses a block. No inner attributes are allowed. diff --git a/src/test/ui/parser/let-binop-plus.rs b/src/test/ui/parser/let-binop-plus.rs deleted file mode 100644 index 4d6d9b5c8d37f..0000000000000 --- a/src/test/ui/parser/let-binop-plus.rs +++ /dev/null @@ -1,8 +0,0 @@ -#![allow(bare_trait_objects)] - -fn main() { - let a: i8 += 1; - //~^ ERROR expected trait, found builtin type `i8` - //~| ERROR can't reassign to an uninitialized variable - let _ = a; -} diff --git a/src/test/ui/parser/let-binop-plus.stderr b/src/test/ui/parser/let-binop-plus.stderr deleted file mode 100644 index 91a59fe24fedc..0000000000000 --- a/src/test/ui/parser/let-binop-plus.stderr +++ /dev/null @@ -1,16 +0,0 @@ -error[E0067]: can't reassign to an uninitialized variable - --> $DIR/let-binop-plus.rs:4:16 - | -LL | let a: i8 += 1; - | ^ help: initialize the variable - -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 2 previous errors - -Some errors have detailed explanations: E0067, E0404. -For more information about an error, try `rustc --explain E0067`. diff --git a/src/test/ui/parser/let-binop.stderr b/src/test/ui/parser/let-binop.stderr index 8a90b7cf74a4a..71431499ac70b 100644 --- a/src/test/ui/parser/let-binop.stderr +++ b/src/test/ui/parser/let-binop.stderr @@ -1,39 +1,20 @@ -error[E0067]: can't reassign to an uninitialized variable +error: can't reassign to an uninitialized variable --> $DIR/let-binop.rs:2:15 | LL | let a: i8 *= 1; | ^^ help: initialize the variable -error[E0067]: can't reassign to an uninitialized variable +error: can't reassign to an uninitialized variable --> $DIR/let-binop.rs:4:11 | LL | let b += 1; - | ^^ - | -help: initialize the variable - | -LL | let b = 1; - | ^ -help: otherwise, reassign to a previously initialized variable - | -LL | b += 1; - | -- + | ^^ help: initialize the variable -error[E0067]: can't reassign to an uninitialized variable +error: can't reassign to an uninitialized variable --> $DIR/let-binop.rs:6:11 | LL | let c *= 1; - | ^^ - | -help: initialize the variable - | -LL | let c = 1; - | ^ -help: otherwise, reassign to a previously initialized variable - | -LL | c *= 1; - | -- + | ^^ help: initialize the variable error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0067`.