From 992b914b6bf41aae4212ea4e8ee09f8b16a31f28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96mer=20Sinan=20A=C4=9Facan?= Date: Sat, 27 Feb 2021 13:37:50 +0300 Subject: [PATCH] Recover from X when parsing const expr This adds recovery when in array type syntax user writes [X; Y] instead of [X; Y::] 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;`). We now also do it when parsing the length field in array type syntax. --- compiler/rustc_parse/src/parser/ty.rs | 12 +++++-- .../{issue-82566.rs => issue-82566-1.rs} | 0 ...ssue-82566.stderr => issue-82566-1.stderr} | 6 ++-- src/test/ui/suggestions/issue-82566-2.rs | 31 ++++++++++++++++ src/test/ui/suggestions/issue-82566-2.stderr | 35 +++++++++++++++++++ 5 files changed, 79 insertions(+), 5 deletions(-) rename src/test/ui/suggestions/{issue-82566.rs => issue-82566-1.rs} (100%) rename src/test/ui/suggestions/{issue-82566.stderr => issue-82566-1.stderr} (89%) create mode 100644 src/test/ui/suggestions/issue-82566-2.rs create mode 100644 src/test/ui/suggestions/issue-82566-2.stderr diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index 9553f5d09e83b..8f03bfd4c3ab7 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.rs b/src/test/ui/suggestions/issue-82566-1.rs similarity index 100% rename from src/test/ui/suggestions/issue-82566.rs rename to src/test/ui/suggestions/issue-82566-1.rs diff --git a/src/test/ui/suggestions/issue-82566.stderr b/src/test/ui/suggestions/issue-82566-1.stderr similarity index 89% rename from src/test/ui/suggestions/issue-82566.stderr rename to src/test/ui/suggestions/issue-82566-1.stderr index e13c097e4cc9d..5a9099a894c8f 100644 --- a/src/test/ui/suggestions/issue-82566.stderr +++ b/src/test/ui/suggestions/issue-82566-1.stderr @@ -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 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 0000000000000..80c8034bd0adf --- /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 0000000000000..ea391ee078c81 --- /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 +