summary refs log tree commit diff
path: root/src/libsyntax/parse
diff options
context:
space:
mode:
authorEsteban Küber <esteban@kuber.com.ar>2018-02-18 14:36:35 -0800
committerEsteban Küber <esteban@kuber.com.ar>2018-02-27 10:45:18 -0800
commit0c9afa87ba8145d09a2c4af7b15a9a23ad470fc8 (patch)
tree134b21037ed63090afb8e55129abccb254abc284 /src/libsyntax/parse
parent29f5c699b11a6a148f097f82eaa05202f8799bbc (diff)
downloadrust-0c9afa87ba8145d09a2c4af7b15a9a23ad470fc8.tar.gz
rust-0c9afa87ba8145d09a2c4af7b15a9a23ad470fc8.zip
Provide missing comma in match arm suggestion
When finding:

```rust
match &Some(3) {
    &None => 1
    &Some(2) => { 3 }
    _ => 2
}
```

provide the following diagnostic:

```
error: expected one of `,`, `.`, `?`, `}`, or an operator, found `=>`
 --> $DIR/missing-comma-in-match.rs:15:18
  |
X |         &None => 1
  |               --  - help: missing comma
  |               |
  |               while parsing the match arm starting here
X |         &Some(2) => { 3 }
  |                  ^^ expected one of `,`, `.`, `?`, `}`, or an operator here
```
Diffstat (limited to 'src/libsyntax/parse')
-rw-r--r--src/libsyntax/parse/parser.rs38
1 files changed, 36 insertions, 2 deletions
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 09dd00fa5fa..2046bbfa713 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -3404,14 +3404,48 @@ impl<'a> Parser<'a> {
         } else {
             None
         };
+        let arrow_span = self.span;
         self.expect(&token::FatArrow)?;
-        let expr = self.parse_expr_res(Restrictions::STMT_EXPR, None)?;
+        let arm_start_span = self.span;
+
+        let expr = self.parse_expr_res(Restrictions::STMT_EXPR, None)
+            .map_err(|mut err| {
+                err.span_label(arrow_span, "while parsing the match arm starting here");
+                err
+            })?;
 
         let require_comma = classify::expr_requires_semi_to_be_stmt(&expr)
             && self.token != token::CloseDelim(token::Brace);
 
         if require_comma {
-            self.expect_one_of(&[token::Comma], &[token::CloseDelim(token::Brace)])?;
+            let cm = self.sess.codemap();
+            self.expect_one_of(&[token::Comma], &[token::CloseDelim(token::Brace)])
+                .map_err(|mut err| {
+                    err.span_label(arrow_span, "while parsing the match arm starting here");
+                    match (cm.span_to_lines(expr.span), cm.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
+                            && self.token == token::FatArrow => {
+                            // We check wether there's any trailing code in the parse span, if there
+                            // isn't, we very likely have the following:
+                            //
+                            // X |     &Y => "y"
+                            //   |        --    - missing comma
+                            //   |        |
+                            //   |        arrow_span
+                            // X |     &X => "x"
+                            //   |      - ^^ self.span
+                            //   |      |
+                            //   |      parsed until here as `"y" & X`
+                            err.span_suggestion_short(cm.next_point(arm_start_span),
+                                                      "missing a comma here to end this match arm",
+                                                      ",".to_owned());
+                        }
+                        _ => {}
+                    }
+                    err
+                })?;
         } else {
             self.eat(&token::Comma);
         }