Skip to content

Commit fb631a5

Browse files
committed
Fix turbofish recovery with multiple generic args
check_mistyped_turbofish_with_multiple_type_params was previously expecting type arguments between angle brackets, which is not right, as we can also see const expressions. We now use generic argument parser instead of type parser. Test with one, two, and three generic arguments added to check consistentcy between 1. check_no_chained_comparison: Called after parsing a nested binop application like `x < A > ...` where angle brackets are interpreted as binary operators and `A` is an expression. 2. check_mistyped_turbofish_with_multiple_type_params: called by `parse_full_stmt` when we expect to see a semicolon after parsing an expression but don't see it. (In `T2<1, 2>::C;`, the expression is `T2 < 1`)
1 parent 3da2dd3 commit fb631a5

File tree

4 files changed

+58
-2
lines changed

4 files changed

+58
-2
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.
+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+
}
+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
error: comparison operators cannot be chained
2+
--> $DIR/issue-82566.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.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.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+

0 commit comments

Comments
 (0)