Skip to content

Commit 906e535

Browse files
authored
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](#82566 (comment)). - Second commit fixes #82566 --- r? ````@estebank````
2 parents 5e68c60 + 992b914 commit 906e535

File tree

7 files changed

+134
-4
lines changed

7 files changed

+134
-4
lines changed

compiler/rustc_parse/src/parser/diagnostics.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -662,7 +662,7 @@ impl<'a> Parser<'a> {
662662
let x = self.parse_seq_to_before_end(
663663
&token::Gt,
664664
SeqSep::trailing_allowed(token::Comma),
665-
|p| p.parse_ty(),
665+
|p| p.parse_generic_arg(),
666666
);
667667
match x {
668668
Ok((_, _, false)) => {

compiler/rustc_parse/src/parser/path.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -545,7 +545,7 @@ impl<'a> Parser<'a> {
545545

546546
/// Parse a generic argument in a path segment.
547547
/// This does not include constraints, e.g., `Item = u8`, which is handled in `parse_angle_arg`.
548-
fn parse_generic_arg(&mut self) -> PResult<'a, Option<GenericArg>> {
548+
pub(super) fn parse_generic_arg(&mut self) -> PResult<'a, Option<GenericArg>> {
549549
let start = self.token.span;
550550
let arg = if self.check_lifetime() && self.look_ahead(1, |t| !t.is_like_plus()) {
551551
// Parse lifetime argument.

compiler/rustc_parse/src/parser/ty.rs

+10-2
Original file line numberDiff line numberDiff line change
@@ -360,12 +360,20 @@ impl<'a> Parser<'a> {
360360
}
361361
Err(err) => return Err(err),
362362
};
363+
363364
let ty = if self.eat(&token::Semi) {
364-
TyKind::Array(elt_ty, self.parse_anon_const_expr()?)
365+
let mut length = self.parse_anon_const_expr()?;
366+
if let Err(e) = self.expect(&token::CloseDelim(token::Bracket)) {
367+
// Try to recover from `X<Y, ...>` when `X::<Y, ...>` works
368+
self.check_mistyped_turbofish_with_multiple_type_params(e, &mut length.value)?;
369+
self.expect(&token::CloseDelim(token::Bracket))?;
370+
}
371+
TyKind::Array(elt_ty, length)
365372
} else {
373+
self.expect(&token::CloseDelim(token::Bracket))?;
366374
TyKind::Slice(elt_ty)
367375
};
368-
self.expect(&token::CloseDelim(token::Bracket))?;
376+
369377
Ok(ty)
370378
}
371379

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
struct T1<const X1: usize>;
2+
struct T2<const X1: usize, const X2: usize>;
3+
struct T3<const X1: usize, const X2: usize, const X3: usize>;
4+
5+
impl T1<1> {
6+
const C: () = ();
7+
}
8+
9+
impl T2<1, 2> {
10+
const C: () = ();
11+
}
12+
13+
impl T3<1, 2, 3> {
14+
const C: () = ();
15+
}
16+
17+
fn main() {
18+
T1<1>::C; //~ ERROR: comparison operators cannot be chained
19+
T2<1, 2>::C; //~ ERROR: expected one of `.`, `;`, `?`, `}`, or an operator, found `,`
20+
T3<1, 2, 3>::C; //~ ERROR: expected one of `.`, `;`, `?`, `}`, or an operator, found `,`
21+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
error: comparison operators cannot be chained
2+
--> $DIR/issue-82566-1.rs:18:7
3+
|
4+
LL | T1<1>::C;
5+
| ^ ^
6+
|
7+
help: use `::<...>` instead of `<...>` to specify type or const arguments
8+
|
9+
LL | T1::<1>::C;
10+
| ^^
11+
12+
error: expected one of `.`, `;`, `?`, `}`, or an operator, found `,`
13+
--> $DIR/issue-82566-1.rs:19:9
14+
|
15+
LL | T2<1, 2>::C;
16+
| ^ expected one of `.`, `;`, `?`, `}`, or an operator
17+
|
18+
help: use `::<...>` instead of `<...>` to specify type or const arguments
19+
|
20+
LL | T2::<1, 2>::C;
21+
| ^^
22+
23+
error: expected one of `.`, `;`, `?`, `}`, or an operator, found `,`
24+
--> $DIR/issue-82566-1.rs:20:9
25+
|
26+
LL | T3<1, 2, 3>::C;
27+
| ^ expected one of `.`, `;`, `?`, `}`, or an operator
28+
|
29+
help: use `::<...>` instead of `<...>` to specify type or const arguments
30+
|
31+
LL | T3::<1, 2, 3>::C;
32+
| ^^
33+
34+
error: aborting due to 3 previous errors
35+
+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
struct Foo1<const N1: usize>;
2+
struct Foo2<const N1: usize, const N2: usize>;
3+
struct Foo3<const N1: usize, const N2: usize, const N3: usize>;
4+
5+
impl<const N1: usize> Foo1<N1> {
6+
const SUM: usize = N1;
7+
}
8+
9+
impl<const N1: usize, const N2: usize> Foo2<N1, N2> {
10+
const SUM: usize = N1 + N2;
11+
}
12+
13+
impl<const N1: usize, const N2: usize, const N3: usize> Foo3<N1, N2, N3> {
14+
const SUM: usize = N1 + N2 + N3;
15+
}
16+
17+
fn foo1() -> [(); Foo1<10>::SUM] { //~ ERROR: comparison operators cannot be chained
18+
todo!()
19+
}
20+
21+
fn foo2() -> [(); Foo2<10, 20>::SUM] {
22+
//~^ ERROR: expected one of `.`, `?`, `]`, or an operator, found `,`
23+
todo!()
24+
}
25+
26+
fn foo3() -> [(); Foo3<10, 20, 30>::SUM] {
27+
//~^ ERROR: expected one of `.`, `?`, `]`, or an operator, found `,`
28+
todo!()
29+
}
30+
31+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
error: comparison operators cannot be chained
2+
--> $DIR/issue-82566-2.rs:17:23
3+
|
4+
LL | fn foo1() -> [(); Foo1<10>::SUM] {
5+
| ^ ^
6+
|
7+
help: use `::<...>` instead of `<...>` to specify type or const arguments
8+
|
9+
LL | fn foo1() -> [(); Foo1::<10>::SUM] {
10+
| ^^
11+
12+
error: expected one of `.`, `?`, `]`, or an operator, found `,`
13+
--> $DIR/issue-82566-2.rs:21:26
14+
|
15+
LL | fn foo2() -> [(); Foo2<10, 20>::SUM] {
16+
| ^ expected one of `.`, `?`, `]`, or an operator
17+
|
18+
help: use `::<...>` instead of `<...>` to specify type or const arguments
19+
|
20+
LL | fn foo2() -> [(); Foo2::<10, 20>::SUM] {
21+
| ^^
22+
23+
error: expected one of `.`, `?`, `]`, or an operator, found `,`
24+
--> $DIR/issue-82566-2.rs:26:26
25+
|
26+
LL | fn foo3() -> [(); Foo3<10, 20, 30>::SUM] {
27+
| ^ expected one of `.`, `?`, `]`, or an operator
28+
|
29+
help: use `::<...>` instead of `<...>` to specify type or const arguments
30+
|
31+
LL | fn foo3() -> [(); Foo3::<10, 20, 30>::SUM] {
32+
| ^^
33+
34+
error: aborting due to 3 previous errors
35+

0 commit comments

Comments
 (0)