about summary refs log tree commit diff
diff options
context:
space:
mode:
authorÖmer Sinan Ağacan <omeragacan@gmail.com>2021-02-27 13:37:50 +0300
committerÖmer Sinan Ağacan <omeragacan@gmail.com>2021-02-27 14:06:57 +0300
commit992b914b6bf41aae4212ea4e8ee09f8b16a31f28 (patch)
tree354a37698a7a8d61a905b083e5b5e133af586c5a
parentfb631a55c2acfae37e55e4c338dd3cc03da0fa7f (diff)
downloadrust-992b914b6bf41aae4212ea4e8ee09f8b16a31f28.tar.gz
rust-992b914b6bf41aae4212ea4e8ee09f8b16a31f28.zip
Recover from X<Y,Z> when parsing const expr
This adds recovery when in array type syntax user writes

    [X; Y<Z, ...>]

instead of

    [X; Y::<Z, ...>]

Fixes #82566

Note that whenever we parse an expression and know that the next token
cannot be `,`, we should be calling
check_mistyped_turbofish_with_multiple_type_params for this recovery.
Previously we only did this for statement parsing (e.g. `let x = f<a,
b>;`). We now also do it when parsing the length field in array type
syntax.
-rw-r--r--compiler/rustc_parse/src/parser/ty.rs12
-rw-r--r--src/test/ui/suggestions/issue-82566-1.rs (renamed from src/test/ui/suggestions/issue-82566.rs)0
-rw-r--r--src/test/ui/suggestions/issue-82566-1.stderr (renamed from src/test/ui/suggestions/issue-82566.stderr)6
-rw-r--r--src/test/ui/suggestions/issue-82566-2.rs31
-rw-r--r--src/test/ui/suggestions/issue-82566-2.stderr35
5 files changed, 79 insertions, 5 deletions
diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs
index 9553f5d09e8..8f03bfd4c3a 100644
--- a/compiler/rustc_parse/src/parser/ty.rs
+++ b/compiler/rustc_parse/src/parser/ty.rs
@@ -360,12 +360,20 @@ impl<'a> Parser<'a> {
             }
             Err(err) => return Err(err),
         };
+
         let ty = if self.eat(&token::Semi) {
-            TyKind::Array(elt_ty, self.parse_anon_const_expr()?)
+            let mut length = self.parse_anon_const_expr()?;
+            if let Err(e) = self.expect(&token::CloseDelim(token::Bracket)) {
+                // Try to recover from `X<Y, ...>` when `X::<Y, ...>` works
+                self.check_mistyped_turbofish_with_multiple_type_params(e, &mut length.value)?;
+                self.expect(&token::CloseDelim(token::Bracket))?;
+            }
+            TyKind::Array(elt_ty, length)
         } else {
+            self.expect(&token::CloseDelim(token::Bracket))?;
             TyKind::Slice(elt_ty)
         };
-        self.expect(&token::CloseDelim(token::Bracket))?;
+
         Ok(ty)
     }
 
diff --git a/src/test/ui/suggestions/issue-82566.rs b/src/test/ui/suggestions/issue-82566-1.rs
index 95c31fbaa28..95c31fbaa28 100644
--- a/src/test/ui/suggestions/issue-82566.rs
+++ b/src/test/ui/suggestions/issue-82566-1.rs
diff --git a/src/test/ui/suggestions/issue-82566.stderr b/src/test/ui/suggestions/issue-82566-1.stderr
index e13c097e4cc..5a9099a894c 100644
--- a/src/test/ui/suggestions/issue-82566.stderr
+++ b/src/test/ui/suggestions/issue-82566-1.stderr
@@ -1,5 +1,5 @@
 error: comparison operators cannot be chained
-  --> $DIR/issue-82566.rs:18:7
+  --> $DIR/issue-82566-1.rs:18:7
    |
 LL |     T1<1>::C;
    |       ^ ^
@@ -10,7 +10,7 @@ LL |     T1::<1>::C;
    |       ^^
 
 error: expected one of `.`, `;`, `?`, `}`, or an operator, found `,`
-  --> $DIR/issue-82566.rs:19:9
+  --> $DIR/issue-82566-1.rs:19:9
    |
 LL |     T2<1, 2>::C;
    |         ^ expected one of `.`, `;`, `?`, `}`, or an operator
@@ -21,7 +21,7 @@ LL |     T2::<1, 2>::C;
    |       ^^
 
 error: expected one of `.`, `;`, `?`, `}`, or an operator, found `,`
-  --> $DIR/issue-82566.rs:20:9
+  --> $DIR/issue-82566-1.rs:20:9
    |
 LL |     T3<1, 2, 3>::C;
    |         ^ expected one of `.`, `;`, `?`, `}`, or an operator
diff --git a/src/test/ui/suggestions/issue-82566-2.rs b/src/test/ui/suggestions/issue-82566-2.rs
new file mode 100644
index 00000000000..80c8034bd0a
--- /dev/null
+++ b/src/test/ui/suggestions/issue-82566-2.rs
@@ -0,0 +1,31 @@
+struct Foo1<const N1: usize>;
+struct Foo2<const N1: usize, const N2: usize>;
+struct Foo3<const N1: usize, const N2: usize, const N3: usize>;
+
+impl<const N1: usize> Foo1<N1> {
+    const SUM: usize = N1;
+}
+
+impl<const N1: usize, const N2: usize> Foo2<N1, N2> {
+    const SUM: usize = N1 + N2;
+}
+
+impl<const N1: usize, const N2: usize, const N3: usize> Foo3<N1, N2, N3> {
+    const SUM: usize = N1 + N2 + N3;
+}
+
+fn foo1() -> [(); Foo1<10>::SUM] { //~ ERROR: comparison operators cannot be chained
+    todo!()
+}
+
+fn foo2() -> [(); Foo2<10, 20>::SUM] {
+    //~^ ERROR: expected one of `.`, `?`, `]`, or an operator, found `,`
+    todo!()
+}
+
+fn foo3() -> [(); Foo3<10, 20, 30>::SUM] {
+    //~^ ERROR: expected one of `.`, `?`, `]`, or an operator, found `,`
+    todo!()
+}
+
+fn main() {}
diff --git a/src/test/ui/suggestions/issue-82566-2.stderr b/src/test/ui/suggestions/issue-82566-2.stderr
new file mode 100644
index 00000000000..ea391ee078c
--- /dev/null
+++ b/src/test/ui/suggestions/issue-82566-2.stderr
@@ -0,0 +1,35 @@
+error: comparison operators cannot be chained
+  --> $DIR/issue-82566-2.rs:17:23
+   |
+LL | fn foo1() -> [(); Foo1<10>::SUM] {
+   |                       ^  ^
+   |
+help: use `::<...>` instead of `<...>` to specify type or const arguments
+   |
+LL | fn foo1() -> [(); Foo1::<10>::SUM] {
+   |                       ^^
+
+error: expected one of `.`, `?`, `]`, or an operator, found `,`
+  --> $DIR/issue-82566-2.rs:21:26
+   |
+LL | fn foo2() -> [(); Foo2<10, 20>::SUM] {
+   |                          ^ expected one of `.`, `?`, `]`, or an operator
+   |
+help: use `::<...>` instead of `<...>` to specify type or const arguments
+   |
+LL | fn foo2() -> [(); Foo2::<10, 20>::SUM] {
+   |                       ^^
+
+error: expected one of `.`, `?`, `]`, or an operator, found `,`
+  --> $DIR/issue-82566-2.rs:26:26
+   |
+LL | fn foo3() -> [(); Foo3<10, 20, 30>::SUM] {
+   |                          ^ expected one of `.`, `?`, `]`, or an operator
+   |
+help: use `::<...>` instead of `<...>` to specify type or const arguments
+   |
+LL | fn foo3() -> [(); Foo3::<10, 20, 30>::SUM] {
+   |                       ^^
+
+error: aborting due to 3 previous errors
+