Rollup merge of #82579 - osa1:issue82566, r=estebank
Fix turbofish recovery with multiple generic args This consists of two commits, each can be individually reviewed. - First commit fixes the issue in [this comment](https://github.com/rust-lang/rust/issues/82566#issuecomment-786924466). - Second commit fixes #82566 --- r? ````@estebank````
This commit is contained in:
commit
906e535205
7 changed files with 134 additions and 4 deletions
|
@ -662,7 +662,7 @@ impl<'a> Parser<'a> {
|
||||||
let x = self.parse_seq_to_before_end(
|
let x = self.parse_seq_to_before_end(
|
||||||
&token::Gt,
|
&token::Gt,
|
||||||
SeqSep::trailing_allowed(token::Comma),
|
SeqSep::trailing_allowed(token::Comma),
|
||||||
|p| p.parse_ty(),
|
|p| p.parse_generic_arg(),
|
||||||
);
|
);
|
||||||
match x {
|
match x {
|
||||||
Ok((_, _, false)) => {
|
Ok((_, _, false)) => {
|
||||||
|
|
|
@ -545,7 +545,7 @@ impl<'a> Parser<'a> {
|
||||||
|
|
||||||
/// Parse a generic argument in a path segment.
|
/// Parse a generic argument in a path segment.
|
||||||
/// This does not include constraints, e.g., `Item = u8`, which is handled in `parse_angle_arg`.
|
/// This does not include constraints, e.g., `Item = u8`, which is handled in `parse_angle_arg`.
|
||||||
fn parse_generic_arg(&mut self) -> PResult<'a, Option<GenericArg>> {
|
pub(super) fn parse_generic_arg(&mut self) -> PResult<'a, Option<GenericArg>> {
|
||||||
let start = self.token.span;
|
let start = self.token.span;
|
||||||
let arg = if self.check_lifetime() && self.look_ahead(1, |t| !t.is_like_plus()) {
|
let arg = if self.check_lifetime() && self.look_ahead(1, |t| !t.is_like_plus()) {
|
||||||
// Parse lifetime argument.
|
// Parse lifetime argument.
|
||||||
|
|
|
@ -360,12 +360,20 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
Err(err) => return Err(err),
|
Err(err) => return Err(err),
|
||||||
};
|
};
|
||||||
|
|
||||||
let ty = if self.eat(&token::Semi) {
|
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 {
|
} else {
|
||||||
|
self.expect(&token::CloseDelim(token::Bracket))?;
|
||||||
TyKind::Slice(elt_ty)
|
TyKind::Slice(elt_ty)
|
||||||
};
|
};
|
||||||
self.expect(&token::CloseDelim(token::Bracket))?;
|
|
||||||
Ok(ty)
|
Ok(ty)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
21
src/test/ui/suggestions/issue-82566-1.rs
Normal file
21
src/test/ui/suggestions/issue-82566-1.rs
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
struct T1<const X1: usize>;
|
||||||
|
struct T2<const X1: usize, const X2: usize>;
|
||||||
|
struct T3<const X1: usize, const X2: usize, const X3: usize>;
|
||||||
|
|
||||||
|
impl T1<1> {
|
||||||
|
const C: () = ();
|
||||||
|
}
|
||||||
|
|
||||||
|
impl T2<1, 2> {
|
||||||
|
const C: () = ();
|
||||||
|
}
|
||||||
|
|
||||||
|
impl T3<1, 2, 3> {
|
||||||
|
const C: () = ();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
T1<1>::C; //~ ERROR: comparison operators cannot be chained
|
||||||
|
T2<1, 2>::C; //~ ERROR: expected one of `.`, `;`, `?`, `}`, or an operator, found `,`
|
||||||
|
T3<1, 2, 3>::C; //~ ERROR: expected one of `.`, `;`, `?`, `}`, or an operator, found `,`
|
||||||
|
}
|
35
src/test/ui/suggestions/issue-82566-1.stderr
Normal file
35
src/test/ui/suggestions/issue-82566-1.stderr
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
error: comparison operators cannot be chained
|
||||||
|
--> $DIR/issue-82566-1.rs:18:7
|
||||||
|
|
|
||||||
|
LL | T1<1>::C;
|
||||||
|
| ^ ^
|
||||||
|
|
|
||||||
|
help: use `::<...>` instead of `<...>` to specify type or const arguments
|
||||||
|
|
|
||||||
|
LL | T1::<1>::C;
|
||||||
|
| ^^
|
||||||
|
|
||||||
|
error: expected one of `.`, `;`, `?`, `}`, or an operator, found `,`
|
||||||
|
--> $DIR/issue-82566-1.rs:19:9
|
||||||
|
|
|
||||||
|
LL | T2<1, 2>::C;
|
||||||
|
| ^ expected one of `.`, `;`, `?`, `}`, or an operator
|
||||||
|
|
|
||||||
|
help: use `::<...>` instead of `<...>` to specify type or const arguments
|
||||||
|
|
|
||||||
|
LL | T2::<1, 2>::C;
|
||||||
|
| ^^
|
||||||
|
|
||||||
|
error: expected one of `.`, `;`, `?`, `}`, or an operator, found `,`
|
||||||
|
--> $DIR/issue-82566-1.rs:20:9
|
||||||
|
|
|
||||||
|
LL | T3<1, 2, 3>::C;
|
||||||
|
| ^ expected one of `.`, `;`, `?`, `}`, or an operator
|
||||||
|
|
|
||||||
|
help: use `::<...>` instead of `<...>` to specify type or const arguments
|
||||||
|
|
|
||||||
|
LL | T3::<1, 2, 3>::C;
|
||||||
|
| ^^
|
||||||
|
|
||||||
|
error: aborting due to 3 previous errors
|
||||||
|
|
31
src/test/ui/suggestions/issue-82566-2.rs
Normal file
31
src/test/ui/suggestions/issue-82566-2.rs
Normal 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() {}
|
35
src/test/ui/suggestions/issue-82566-2.stderr
Normal file
35
src/test/ui/suggestions/issue-82566-2.stderr
Normal 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
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue