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.
This commit is contained in:
Ömer Sinan Ağacan 2021-02-27 13:37:50 +03:00
parent fb631a55c2
commit 992b914b6b
5 changed files with 79 additions and 5 deletions

View file

@ -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)
}

View file

@ -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

View file

@ -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() {}

View file

@ -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