@@ -12,7 +12,7 @@ use rustc_ast::ast::{Block, BlockCheckMode, Expr, ExprKind, Local, Stmt, StmtKin
1212use rustc_ast:: ptr:: P ;
1313use rustc_ast:: token:: { self , TokenKind } ;
1414use rustc_ast:: util:: classify;
15- use rustc_errors:: { struct_span_err , Applicability , PResult } ;
15+ use rustc_errors:: { Applicability , PResult } ;
1616use rustc_span:: source_map:: { BytePos , Span } ;
1717use rustc_span:: symbol:: { kw, sym} ;
1818
@@ -145,12 +145,12 @@ impl<'a> Parser<'a> {
145145 }
146146
147147 fn parse_local_mk ( & mut self , lo : Span , attrs : AttrVec ) -> PResult < ' a , Stmt > {
148- let local = self . parse_local ( lo , attrs) ?;
148+ let local = self . parse_local ( attrs) ?;
149149 Ok ( self . mk_stmt ( lo. to ( self . prev_token . span ) , StmtKind :: Local ( local) ) )
150150 }
151151
152152 /// Parses a local variable declaration.
153- fn parse_local ( & mut self , let_span : Span , attrs : AttrVec ) -> PResult < ' a , P < Local > > {
153+ fn parse_local ( & mut self , attrs : AttrVec ) -> PResult < ' a , P < Local > > {
154154 let lo = self . prev_token . span ;
155155 let pat = self . parse_top_pat ( GateOr :: Yes ) ?;
156156
@@ -174,10 +174,7 @@ impl<'a> Parser<'a> {
174174 } else {
175175 ( None , None )
176176 } ;
177- let init = match (
178- self . parse_initializer ( let_span. until ( pat. span ) , ty. is_some ( ) , err. is_some ( ) ) ,
179- err,
180- ) {
177+ let init = match ( self . parse_initializer ( err. is_some ( ) ) , err) {
181178 ( Ok ( init) , None ) => {
182179 // init parsed, ty parsed
183180 init
@@ -219,46 +216,28 @@ impl<'a> Parser<'a> {
219216 }
220217
221218 /// Parses the RHS of a local variable declaration (e.g., '= 14;').
222- fn parse_initializer (
223- & mut self ,
224- let_span : Span ,
225- has_ty : bool ,
226- skip_eq : bool ,
227- ) -> PResult < ' a , Option < P < Expr > > > {
228- // In case of code like `let x: i8 += 1`, `i8` is interpreted as a trait consuming the `+`
229- // from `+=`.
230- let ate_plus = self . prev_token . is_like_plus ( ) && has_ty;
231- let parse = if !skip_eq && ( ate_plus || matches ! ( self . token. kind, TokenKind :: BinOpEq ( _) ) ) {
232- // Error recovery for `let x += 1`
233- let mut err = struct_span_err ! (
234- self . sess. span_diagnostic,
235- self . token. span,
236- E0067 ,
237- "can't reassign to an uninitialized variable"
238- ) ;
239- err. span_suggestion_short (
240- self . token . span ,
241- "initialize the variable" ,
242- "=" . to_string ( ) ,
243- Applicability :: MaybeIncorrect ,
244- ) ;
245- // In case of code like `let x += 1` it's possible the user may have meant to write `x += 1`
246- if !has_ty {
247- err. span_suggestion_short (
248- let_span,
249- "otherwise, reassign to a previously initialized variable" ,
250- "" . to_string ( ) ,
219+ fn parse_initializer ( & mut self , eq_optional : bool ) -> PResult < ' a , Option < P < Expr > > > {
220+ let eq_consumed = match self . token . kind {
221+ token:: BinOpEq ( ..) => {
222+ // Recover `let x <op>= 1` as `let x = 1`
223+ self . struct_span_err (
224+ self . token . span ,
225+ "can't reassign to an uninitialized variable" ,
226+ )
227+ . span_suggestion_short (
228+ self . token . span ,
229+ "initialize the variable" ,
230+ "=" . to_string ( ) ,
251231 Applicability :: MaybeIncorrect ,
252- ) ;
232+ )
233+ . emit ( ) ;
234+ self . bump ( ) ;
235+ true
253236 }
254- err. emit ( ) ;
255- self . bump ( ) ;
256- true
257- } else {
258- self . eat ( & token:: Eq ) || skip_eq
237+ _ => self . eat ( & token:: Eq ) ,
259238 } ;
260239
261- if parse { Ok ( Some ( self . parse_expr ( ) ?) ) } else { Ok ( None ) }
240+ Ok ( if eq_consumed || eq_optional { Some ( self . parse_expr ( ) ?) } else { None } )
262241 }
263242
264243 /// Parses a block. No inner attributes are allowed.
0 commit comments