about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorYuki Okushi <huyuumi.dev@gmail.com>2020-05-29 15:07:04 +0900
committerGitHub <noreply@github.com>2020-05-29 15:07:04 +0900
commitd19b51e441833630a53a8966e3bc0ed1c94420f7 (patch)
tree9e240486f738382b1e1c4492c8e3c2a963b58473 /src
parent6786c7d190a0792cd392fc2d8dde7c7de1e9f9b3 (diff)
parent593d1eed8216c4ab33500b323fbd1b3de4ecb34d (diff)
downloadrust-d19b51e441833630a53a8966e3bc0ed1c94420f7.tar.gz
rust-d19b51e441833630a53a8966e3bc0ed1c94420f7.zip
Rollup merge of #72534 - chrissimpkins:fix-72373, r=estebank
Improve missing `@` in slice binding pattern diagnostics

Closes https://github.com/rust-lang/rust/issues/72373

Includes a new suggestion with `Applicability::MaybeIncorrect` confidence level.

Before:

```
 --> src/main.rs:5:19
  |
5 |         [h, ref ts..] => foo(c, n - h) + foo(ts, n),
  |                   -^
  |                   |
  |                   expected one of `,`, `@`, `]`, or `|`
  |                   help: missing `,`

error[E0308]: mismatched types
 --> src/main.rs:5:46
  |
5 |         [h, ref ts..] => foo(c, n - h) + foo(ts, n),
  |                                              ^^ expected slice `[u32]`, found `u32`
  |
  = note: expected reference `&[u32]`
             found reference `&u32`

error: aborting due to 2 previous errors
```

After:

```
error: expected one of `,`, `@`, `]`, or `|`, found `..`
 --> src/main.rs:5:20
  |
5 |         [h, ref ts..] => foo(c, n - h) + foo(ts, n),
  |                    ^^ expected one of `,`, `@`, `]`, or `|`
  |
help: if you meant to bind the contents of the rest of the array pattern into `ts`, use `@`
  |
5 |         [h, ref ts @ ..] => foo(c, n - h) + foo(ts, n),
  |                    ^

error: aborting due to previous error
```

r? @estebank
Diffstat (limited to 'src')
-rw-r--r--src/librustc_parse/parser/mod.rs20
-rw-r--r--src/test/ui/issues/issue-72373.rs9
-rw-r--r--src/test/ui/issues/issue-72373.stderr13
3 files changed, 42 insertions, 0 deletions
diff --git a/src/librustc_parse/parser/mod.rs b/src/librustc_parse/parser/mod.rs
index b21524cb9bd..c00b6084829 100644
--- a/src/librustc_parse/parser/mod.rs
+++ b/src/librustc_parse/parser/mod.rs
@@ -672,6 +672,26 @@ impl<'a> Parser<'a> {
                                 }
                             }
 
+                            // If this was a missing `@` in a binding pattern
+                            // bail with a suggestion
+                            // https://github.com/rust-lang/rust/issues/72373
+                            if self.prev_token.is_ident() && &self.token.kind == &token::DotDot {
+                                let msg = format!(
+                                    "if you meant to bind the contents of \
+                                    the rest of the array pattern into `{}`, use `@`",
+                                    pprust::token_to_string(&self.prev_token)
+                                );
+                                expect_err
+                                    .span_suggestion_verbose(
+                                        self.prev_token.span.shrink_to_hi().until(self.token.span),
+                                        &msg,
+                                        " @ ".to_string(),
+                                        Applicability::MaybeIncorrect,
+                                    )
+                                    .emit();
+                                break;
+                            }
+
                             // Attempt to keep parsing if it was an omitted separator.
                             match f(self) {
                                 Ok(t) => {
diff --git a/src/test/ui/issues/issue-72373.rs b/src/test/ui/issues/issue-72373.rs
new file mode 100644
index 00000000000..4da6061c27f
--- /dev/null
+++ b/src/test/ui/issues/issue-72373.rs
@@ -0,0 +1,9 @@
+fn foo(c: &[u32], n: u32) -> u32 {
+    match *c {
+        [h, ..] if h > n => 0,
+        [h, ..] if h == n => 1,
+        [h, ref ts..] => foo(c, n - h) + foo(ts, n),
+        //~^ ERROR expected one of `,`, `@`, `]`, or `|`, found `..`
+        [] => 0,
+    }
+}
diff --git a/src/test/ui/issues/issue-72373.stderr b/src/test/ui/issues/issue-72373.stderr
new file mode 100644
index 00000000000..dfde8624814
--- /dev/null
+++ b/src/test/ui/issues/issue-72373.stderr
@@ -0,0 +1,13 @@
+error: expected one of `,`, `@`, `]`, or `|`, found `..`
+  --> $DIR/issue-72373.rs:5:19
+   |
+LL |         [h, ref ts..] => foo(c, n - h) + foo(ts, n),
+   |                   ^^ expected one of `,`, `@`, `]`, or `|`
+   |
+help: if you meant to bind the contents of the rest of the array pattern into `ts`, use `@`
+   |
+LL |         [h, ref ts @ ..] => foo(c, n - h) + foo(ts, n),
+   |                    ^
+
+error: aborting due to previous error
+