about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2022-06-07 02:19:18 -0700
committerMichael Goulet <michael@errs.io>2022-06-07 02:19:51 -0700
commitb13eb61a2cdfac1e094c2a4d608086f40cea5e01 (patch)
tree1d1e3b23c02f50b1b2b13e39a605517365e79be2
parent9f7e997c8bc3cacd2ab4eb75e63cb5fa9279c7b0 (diff)
downloadrust-b13eb61a2cdfac1e094c2a4d608086f40cea5e01.tar.gz
rust-b13eb61a2cdfac1e094c2a4d608086f40cea5e01.zip
Recover missing comma after match arm
-rw-r--r--compiler/rustc_parse/src/parser/expr.rs51
-rw-r--r--src/test/ui/parser/match-arm-without-braces.rs6
-rw-r--r--src/test/ui/parser/match-arm-without-braces.stderr10
3 files changed, 44 insertions, 23 deletions
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index b786c52e688..324e04b1981 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -2718,13 +2718,12 @@ impl<'a> Parser<'a> {
                     ));
                 }
                 this.expect_one_of(&[token::Comma], &[token::CloseDelim(Delimiter::Brace)])
-                    .map_err(|mut err| {
-                        match (sm.span_to_lines(expr.span), sm.span_to_lines(arm_start_span)) {
-                            (Ok(ref expr_lines), Ok(ref arm_start_lines))
-                                if arm_start_lines.lines[0].end_col
-                                    == expr_lines.lines[0].end_col
-                                    && expr_lines.lines.len() == 2
-                                    && this.token == token::FatArrow =>
+                    .or_else(|mut err| {
+                        if this.token == token::FatArrow {
+                            if let Ok(expr_lines) = sm.span_to_lines(expr.span)
+                            && let Ok(arm_start_lines) = sm.span_to_lines(arm_start_span)
+                            && arm_start_lines.lines[0].end_col == expr_lines.lines[0].end_col
+                            && expr_lines.lines.len() == 2
                             {
                                 // We check whether there's any trailing code in the parse span,
                                 // if there isn't, we very likely have the following:
@@ -2743,15 +2742,41 @@ impl<'a> Parser<'a> {
                                     ",".to_owned(),
                                     Applicability::MachineApplicable,
                                 );
+                                return Err(err);
                             }
-                            _ => {
-                                err.span_label(
-                                    arrow_span,
-                                    "while parsing the `match` arm starting here",
-                                );
+                        } else {
+                            // FIXME(compiler-errors): We could also recover `; PAT =>` here
+
+                            // Try to parse a following `PAT =>`, if successful
+                            // then we should recover.
+                            let mut snapshot = this.create_snapshot_for_diagnostic();
+                            let pattern_follows = snapshot
+                                .parse_pat_allow_top_alt(
+                                    None,
+                                    RecoverComma::Yes,
+                                    RecoverColon::Yes,
+                                    CommaRecoveryMode::EitherTupleOrPipe,
+                                )
+                                .map_err(|err| err.cancel())
+                                .is_ok();
+                            if pattern_follows && snapshot.check(&TokenKind::FatArrow) {
+                                err.cancel();
+                                this.struct_span_err(
+                                    hi.shrink_to_hi(),
+                                    "expected `,` following `match` arm",
+                                )
+                                .span_suggestion(
+                                    hi.shrink_to_hi(),
+                                    "missing a comma here to end this `match` arm",
+                                    ",".to_owned(),
+                                    Applicability::MachineApplicable,
+                                )
+                                .emit();
+                                return Ok(true);
                             }
                         }
-                        err
+                        err.span_label(arrow_span, "while parsing the `match` arm starting here");
+                        Err(err)
                     })?;
             } else {
                 this.eat(&token::Comma);
diff --git a/src/test/ui/parser/match-arm-without-braces.rs b/src/test/ui/parser/match-arm-without-braces.rs
index 55a88742769..bba38fd0fa4 100644
--- a/src/test/ui/parser/match-arm-without-braces.rs
+++ b/src/test/ui/parser/match-arm-without-braces.rs
@@ -45,9 +45,9 @@ fn main() {
           15;
     }
     match S::get(16) {
-        Some(Val::Foo) => 17
-        _ => 18, //~ ERROR expected one of
-    }
+        Some(Val::Foo) => 17 //~ ERROR expected `,` following `match` arm
+        _ => 18,
+    };
     match S::get(19) {
         Some(Val::Foo) =>
           20; //~ ERROR `match` arm body without braces
diff --git a/src/test/ui/parser/match-arm-without-braces.stderr b/src/test/ui/parser/match-arm-without-braces.stderr
index 4831d79ef2b..37d55aa53f8 100644
--- a/src/test/ui/parser/match-arm-without-braces.stderr
+++ b/src/test/ui/parser/match-arm-without-braces.stderr
@@ -52,15 +52,11 @@ LL ~           { 14;
 LL ~           15; }
    |
 
-error: expected one of `,`, `.`, `?`, `}`, or an operator, found reserved identifier `_`
-  --> $DIR/match-arm-without-braces.rs:49:9
+error: expected `,` following `match` arm
+  --> $DIR/match-arm-without-braces.rs:48:29
    |
 LL |         Some(Val::Foo) => 17
-   |                        --   - expected one of `,`, `.`, `?`, `}`, or an operator
-   |                        |
-   |                        while parsing the `match` arm starting here
-LL |         _ => 18,
-   |         ^ unexpected token
+   |                             ^ help: missing a comma here to end this `match` arm: `,`
 
 error: `match` arm body without braces
   --> $DIR/match-arm-without-braces.rs:53:11