about summary refs log tree commit diff
path: root/src
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
parent48ff12acb184672393692e087927a66ff7907d71 (diff)
Error recovery for `let` with `+=`
Diffstat (limited to 'src')
-rw-r--r--src/librustc_parse/parser/stmt.rs65
-rw-r--r--src/test/ui/parser/let-binop-plus.rs1
-rw-r--r--src/test/ui/parser/let-binop-plus.stderr11
3 files changed, 42 insertions, 35 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) }
diff --git a/src/test/ui/parser/let-binop-plus.rs b/src/test/ui/parser/let-binop-plus.rs
index 8d883d6e248..98473e9f096 100644
--- a/src/test/ui/parser/let-binop-plus.rs
+++ b/src/test/ui/parser/let-binop-plus.rs
@@ -3,5 +3,6 @@
 fn main() {
     let a: i8 += 1;
     //~^ ERROR expected trait, found builtin type `i8`
+    //~| ERROR can't reassign to a uninitialized variable
     let _ = a;
 }
diff --git a/src/test/ui/parser/let-binop-plus.stderr b/src/test/ui/parser/let-binop-plus.stderr
index baa935aff71..d7d84ff16a0 100644
--- a/src/test/ui/parser/let-binop-plus.stderr
+++ b/src/test/ui/parser/let-binop-plus.stderr
@@ -1,9 +1,16 @@
+error[E0067]: can't reassign to a uninitialized variable
+  --> $DIR/let-binop-plus.rs:4:16
+   |
+LL |     let a: i8 += 1;
+   |                ^ help: replace with `=` to 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 previous error
+error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0404`.
+Some errors have detailed explanations: E0067, E0404.
+For more information about an error, try `rustc --explain E0067`.