diff options
| 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 |
| commit | 992b914b6bf41aae4212ea4e8ee09f8b16a31f28 (patch) | |
| tree | 354a37698a7a8d61a905b083e5b5e133af586c5a | |
| parent | fb631a55c2acfae37e55e4c338dd3cc03da0fa7f (diff) | |
| download | rust-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.rs | 12 | ||||
| -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.rs | 31 | ||||
| -rw-r--r-- | src/test/ui/suggestions/issue-82566-2.stderr | 35 |
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 + |
