about summary refs log tree commit diff
path: root/src/librustc_parse
diff options
context:
space:
mode:
authormibac138 <5672750+mibac138@users.noreply.github.com>2020-05-07 05:00:59 +0200
committermibac138 <5672750+mibac138@users.noreply.github.com>2020-05-20 20:42:11 +0200
commit05d653199871955eba90abdd3b176603f030ab60 (patch)
treebd052f7d528467baac2355d19fa8601400c955f9 /src/librustc_parse
parent48ff12acb184672393692e087927a66ff7907d71 (diff)
Error recovery for `let` with `+=`
Diffstat (limited to 'src/librustc_parse')
-rw-r--r--src/librustc_parse/parser/stmt.rs65
1 files changed, 32 insertions, 33 deletions
diff --git a/src/librustc_parse/parser/stmt.rs b/src/librustc_parse/parser/stmt.rs
index aceee814328..224f4ebf538 100644
--- a/src/librustc_parse/parser/stmt.rs
+++ b/src/librustc_parse/parser/stmt.rs
@@ -222,44 +222,43 @@ impl<'a> Parser<'a> {
         has_ty: bool,
         skip_eq: bool,
     ) -> PResult<'a, Option<P<Expr>>> {
-        let parse = if !self.eat(&token::Eq) && !skip_eq {
+        // 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`
-            if matches!(self.token.kind, TokenKind::BinOpEq(_)) {
-                let mut err = struct_span_err!(
-                    self.sess.span_diagnostic,
-                    self.token.span,
-                    E0067,
-                    "can't reassign to a uninitialized variable"
-                );
+            let mut err = struct_span_err!(
+                self.sess.span_diagnostic,
+                self.token.span,
+                E0067,
+                "can't reassign to a uninitialized variable"
+            );
+            err.span_suggestion_short(
+                self.token.span,
+                "replace with `=` to initialize the variable",
+                "=".to_string(),
+                if has_ty {
+                    // for `let x: i8 += 1` it's highly likely that the `+` is a typo
+                    Applicability::MachineApplicable
+                } else {
+                    // for `let x += 1` it's a bit less likely that the `+` is a typo
+                    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(
-                    self.token.span,
-                    "replace with `=` to initialize the variable",
-                    "=".to_string(),
-                    if has_ty {
-                        // for `let x: i8 += 1` it's highly likely that the `+` is a typo
-                        Applicability::MachineApplicable
-                    } else {
-                        // for `let x += 1` it's a bit less likely that the `+` is a typo
-                        Applicability::MaybeIncorrect
-                    },
+                    let_span,
+                    "remove to reassign to a previously initialized 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,
-                        "remove to reassign to a previously initialized variable",
-                        "".to_string(),
-                        Applicability::MaybeIncorrect,
-                    );
-                }
-                err.emit();
-                self.bump();
-                true
-            } else {
-                false
             }
-        } else {
+            err.emit();
+            self.bump();
             true
+        } else {
+            self.eat(&token::Eq) || skip_eq
         };
 
         if parse { Ok(Some(self.parse_expr()?)) } else { Ok(None) }