diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 5b4939b7407..f4ab3260d1a 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -662,7 +662,7 @@ impl<'a> Parser<'a> { let x = self.parse_seq_to_before_end( &token::Gt, SeqSep::trailing_allowed(token::Comma), - |p| p.parse_ty(), + |p| p.parse_generic_arg(), ); match x { Ok((_, _, false)) => { diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs index 6b7059eecf4..9cc600d9ede 100644 --- a/compiler/rustc_parse/src/parser/path.rs +++ b/compiler/rustc_parse/src/parser/path.rs @@ -545,7 +545,7 @@ impl<'a> Parser<'a> { /// Parse a generic argument in a path segment. /// 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> { + pub(super) fn parse_generic_arg(&mut self) -> PResult<'a, Option> { let start = self.token.span; let arg = if self.check_lifetime() && self.look_ahead(1, |t| !t.is_like_plus()) { // Parse lifetime argument. 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` when `X::` 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-1.rs b/src/test/ui/suggestions/issue-82566-1.rs new file mode 100644 index 00000000000..95c31fbaa28 --- /dev/null +++ b/src/test/ui/suggestions/issue-82566-1.rs @@ -0,0 +1,21 @@ +struct T1; +struct T2; +struct T3; + +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 `,` +} diff --git a/src/test/ui/suggestions/issue-82566-1.stderr b/src/test/ui/suggestions/issue-82566-1.stderr new file mode 100644 index 00000000000..5a9099a894c --- /dev/null +++ b/src/test/ui/suggestions/issue-82566-1.stderr @@ -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 + 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; +struct Foo2; +struct Foo3; + +impl Foo1 { + const SUM: usize = N1; +} + +impl Foo2 { + const SUM: usize = N1 + N2; +} + +impl Foo3 { + 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 +