From 1cac8cbde98e7b15ad24fc96af4864cdd67b9c30 Mon Sep 17 00:00:00 2001 From: xizheyin Date: Mon, 14 Jul 2025 03:39:24 +0800 Subject: [PATCH 1/2] Add test array-type-no-semi.rs Signed-off-by: xizheyin --- tests/ui/parser/recover/array-type-no-semi.rs | 18 ++++++ .../parser/recover/array-type-no-semi.stderr | 56 +++++++++++++++++++ 2 files changed, 74 insertions(+) create mode 100644 tests/ui/parser/recover/array-type-no-semi.rs create mode 100644 tests/ui/parser/recover/array-type-no-semi.stderr diff --git a/tests/ui/parser/recover/array-type-no-semi.rs b/tests/ui/parser/recover/array-type-no-semi.rs new file mode 100644 index 0000000000000..ae5efbaf36ca2 --- /dev/null +++ b/tests/ui/parser/recover/array-type-no-semi.rs @@ -0,0 +1,18 @@ +// when the next token is not a semicolon, +// we should suggest to use semicolon if recovery is allowed +// See issue #143828 + +fn main() { + let x = 5; + let b: [i32, 5]; + //~^ ERROR expected one of `!`, `(`, `+`, `::`, `;`, `<`, or `]`, found `,` + //~| ERROR expected value, found builtin type `i32` [E0423] + let a: [i32, ]; + //~^ ERROR expected one of `!`, `(`, `+`, `::`, `;`, `<`, or `]`, found `,` + //~| ERROR expected value, found builtin type `i32` [E0423] + let c: [i32, x]; + //~^ ERROR expected one of `!`, `(`, `+`, `::`, `;`, `<`, or `]`, found `,` + //~| ERROR expected value, found builtin type `i32` [E0423] + let e: [i32 5]; + //~^ ERROR expected one of `!`, `(`, `+`, `::`, `;`, `<`, or `]`, found `5` +} diff --git a/tests/ui/parser/recover/array-type-no-semi.stderr b/tests/ui/parser/recover/array-type-no-semi.stderr new file mode 100644 index 0000000000000..84b7282b4fedb --- /dev/null +++ b/tests/ui/parser/recover/array-type-no-semi.stderr @@ -0,0 +1,56 @@ +error: expected one of `!`, `(`, `+`, `::`, `;`, `<`, or `]`, found `,` + --> $DIR/array-type-no-semi.rs:7:16 + | +LL | let b: [i32, 5]; + | - ^ expected one of 7 possible tokens + | | + | while parsing the type for `b` + | help: use `=` if you meant to assign + +error: expected one of `!`, `(`, `+`, `::`, `;`, `<`, or `]`, found `,` + --> $DIR/array-type-no-semi.rs:10:16 + | +LL | let a: [i32, ]; + | - ^ expected one of 7 possible tokens + | | + | while parsing the type for `a` + | help: use `=` if you meant to assign + +error: expected one of `!`, `(`, `+`, `::`, `;`, `<`, or `]`, found `,` + --> $DIR/array-type-no-semi.rs:13:16 + | +LL | let c: [i32, x]; + | - ^ expected one of 7 possible tokens + | | + | while parsing the type for `c` + | help: use `=` if you meant to assign + +error: expected one of `!`, `(`, `+`, `::`, `;`, `<`, or `]`, found `5` + --> $DIR/array-type-no-semi.rs:16:17 + | +LL | let e: [i32 5]; + | - ^ expected one of 7 possible tokens + | | + | while parsing the type for `e` + +error[E0423]: expected value, found builtin type `i32` + --> $DIR/array-type-no-semi.rs:7:13 + | +LL | let b: [i32, 5]; + | ^^^ not a value + +error[E0423]: expected value, found builtin type `i32` + --> $DIR/array-type-no-semi.rs:10:13 + | +LL | let a: [i32, ]; + | ^^^ not a value + +error[E0423]: expected value, found builtin type `i32` + --> $DIR/array-type-no-semi.rs:13:13 + | +LL | let c: [i32, x]; + | ^^^ not a value + +error: aborting due to 7 previous errors + +For more information about this error, try `rustc --explain E0423`. From ed88af21637ff3677100fd26f8db354cd6134ad4 Mon Sep 17 00:00:00 2001 From: xizheyin Date: Mon, 14 Jul 2025 04:28:20 +0800 Subject: [PATCH 2/2] Recover and suggest use `;` to construct array type Signed-off-by: xizheyin --- compiler/rustc_parse/src/parser/ty.rs | 59 +++++++++++++- src/tools/tidy/src/issues.txt | 1 - src/tools/tidy/src/ui_tests.rs | 2 +- tests/ui/issues/issue-50571.fixed | 10 --- tests/ui/issues/issue-50571.rs | 10 --- tests/ui/issues/issue-50571.stderr | 15 ---- tests/ui/parser/better-expected.rs | 2 +- tests/ui/parser/better-expected.stderr | 12 ++- .../issues/error-pattern-issue-50571.rs | 11 +++ .../issues/error-pattern-issue-50571.stderr | 28 +++++++ tests/ui/parser/recover/array-type-no-semi.rs | 11 ++- .../parser/recover/array-type-no-semi.stderr | 79 +++++++++++-------- .../removed-syntax-fixed-vec.rs | 7 +- .../removed-syntax-fixed-vec.stderr | 21 ++++- 14 files changed, 182 insertions(+), 86 deletions(-) delete mode 100644 tests/ui/issues/issue-50571.fixed delete mode 100644 tests/ui/issues/issue-50571.rs delete mode 100644 tests/ui/issues/issue-50571.stderr create mode 100644 tests/ui/parser/issues/error-pattern-issue-50571.rs create mode 100644 tests/ui/parser/issues/error-pattern-issue-50571.stderr diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index a997be3405d69..740dd10ea8ba1 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -575,14 +575,69 @@ impl<'a> Parser<'a> { self.expect(exp!(CloseBracket))?; } TyKind::Array(elt_ty, length) - } else { - self.expect(exp!(CloseBracket))?; + } else if self.eat(exp!(CloseBracket)) { TyKind::Slice(elt_ty) + } else { + self.maybe_recover_array_ty_without_semi(elt_ty)? }; Ok(ty) } + /// Recover from malformed array type syntax. + /// + /// This method attempts to recover from cases like: + /// - `[u8, 5]` → suggests using `;`, return a Array type + /// - `[u8 5]` → suggests using `;`, return a Array type + /// Consider to add more cases in the future. + fn maybe_recover_array_ty_without_semi(&mut self, elt_ty: P) -> PResult<'a, TyKind> { + let span = self.token.span; + let token_descr = super::token_descr(&self.token); + let mut err = + self.dcx().struct_span_err(span, format!("expected `;` or `]`, found {}", token_descr)); + err.span_label(span, "expected `;` or `]`"); + err.note("you might have meant to write a slice or array type"); + + // If we cannot recover, return the error immediately. + if !self.may_recover() { + return Err(err); + } + + let snapshot = self.create_snapshot_for_diagnostic(); + + let suggestion_span = if self.eat(exp!(Comma)) || self.eat(exp!(Star)) { + // Consume common erroneous separators. + self.prev_token.span + } else { + self.token.span.shrink_to_lo() + }; + + // we first try to parse pattern like `[u8 5]` + let length = match self.parse_expr_anon_const() { + Ok(length) => length, + Err(e) => { + e.cancel(); + self.restore_snapshot(snapshot); + return Err(err); + } + }; + + if let Err(e) = self.expect(exp!(CloseBracket)) { + e.cancel(); + self.restore_snapshot(snapshot); + return Err(err); + } + + err.span_suggestion_verbose( + suggestion_span, + "you might have meant to use `;` as the separator", + ";", + Applicability::MaybeIncorrect, + ); + err.emit(); + Ok(TyKind::Array(elt_ty, length)) + } + fn parse_borrowed_pointee(&mut self) -> PResult<'a, TyKind> { let and_span = self.prev_token.span; let mut opt_lifetime = self.check_lifetime().then(|| self.expect_lifetime()); diff --git a/src/tools/tidy/src/issues.txt b/src/tools/tidy/src/issues.txt index cac4dba2b49d7..8b57db23d01c1 100644 --- a/src/tools/tidy/src/issues.txt +++ b/src/tools/tidy/src/issues.txt @@ -2338,7 +2338,6 @@ ui/issues/issue-50415.rs ui/issues/issue-50442.rs ui/issues/issue-50471.rs ui/issues/issue-50518.rs -ui/issues/issue-50571.rs ui/issues/issue-50581.rs ui/issues/issue-50582.rs ui/issues/issue-50585.rs diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs index 53226fcb80e6a..74f8104c7e980 100644 --- a/src/tools/tidy/src/ui_tests.rs +++ b/src/tools/tidy/src/ui_tests.rs @@ -17,7 +17,7 @@ use ignore::Walk; const ENTRY_LIMIT: u32 = 901; // FIXME: The following limits should be reduced eventually. -const ISSUES_ENTRY_LIMIT: u32 = 1619; +const ISSUES_ENTRY_LIMIT: u32 = 1616; const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[ "rs", // test source files diff --git a/tests/ui/issues/issue-50571.fixed b/tests/ui/issues/issue-50571.fixed deleted file mode 100644 index 6d73f17cca4ca..0000000000000 --- a/tests/ui/issues/issue-50571.fixed +++ /dev/null @@ -1,10 +0,0 @@ -//@ edition: 2015 -//@ run-rustfix - -#![allow(dead_code)] -trait Foo { - fn foo(_: [i32; 2]) {} - //~^ ERROR: patterns aren't allowed in methods without bodies -} - -fn main() {} diff --git a/tests/ui/issues/issue-50571.rs b/tests/ui/issues/issue-50571.rs deleted file mode 100644 index dd840ffe4d170..0000000000000 --- a/tests/ui/issues/issue-50571.rs +++ /dev/null @@ -1,10 +0,0 @@ -//@ edition: 2015 -//@ run-rustfix - -#![allow(dead_code)] -trait Foo { - fn foo([a, b]: [i32; 2]) {} - //~^ ERROR: patterns aren't allowed in methods without bodies -} - -fn main() {} diff --git a/tests/ui/issues/issue-50571.stderr b/tests/ui/issues/issue-50571.stderr deleted file mode 100644 index 9b00fe0f5db64..0000000000000 --- a/tests/ui/issues/issue-50571.stderr +++ /dev/null @@ -1,15 +0,0 @@ -error[E0642]: patterns aren't allowed in methods without bodies - --> $DIR/issue-50571.rs:6:12 - | -LL | fn foo([a, b]: [i32; 2]) {} - | ^^^^^^ - | -help: give this argument a name or use an underscore to ignore it - | -LL - fn foo([a, b]: [i32; 2]) {} -LL + fn foo(_: [i32; 2]) {} - | - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0642`. diff --git a/tests/ui/parser/better-expected.rs b/tests/ui/parser/better-expected.rs index 16b61caa4dffc..91128c39691d3 100644 --- a/tests/ui/parser/better-expected.rs +++ b/tests/ui/parser/better-expected.rs @@ -1,3 +1,3 @@ fn main() { - let x: [isize 3]; //~ ERROR expected one of `!`, `(`, `+`, `::`, `;`, `<`, or `]`, found `3` + let x: [isize 3]; //~ ERROR expected `;` or `]`, found `3` } diff --git a/tests/ui/parser/better-expected.stderr b/tests/ui/parser/better-expected.stderr index f4ec933be1643..4646ce7eff0e0 100644 --- a/tests/ui/parser/better-expected.stderr +++ b/tests/ui/parser/better-expected.stderr @@ -1,10 +1,14 @@ -error: expected one of `!`, `(`, `+`, `::`, `;`, `<`, or `]`, found `3` +error: expected `;` or `]`, found `3` --> $DIR/better-expected.rs:2:19 | LL | let x: [isize 3]; - | - ^ expected one of 7 possible tokens - | | - | while parsing the type for `x` + | ^ expected `;` or `]` + | + = note: you might have meant to write a slice or array type +help: you might have meant to use `;` as the separator + | +LL | let x: [isize ;3]; + | + error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/error-pattern-issue-50571.rs b/tests/ui/parser/issues/error-pattern-issue-50571.rs new file mode 100644 index 0000000000000..0c2ce6052cb80 --- /dev/null +++ b/tests/ui/parser/issues/error-pattern-issue-50571.rs @@ -0,0 +1,11 @@ +// There is a regression introduced for issue #143828 +//@ edition: 2015 + +#![allow(dead_code)] +trait Foo { + fn foo([a, b]: [i32; 2]) {} + //~^ ERROR: expected `;` or `]`, found `,` + //~| ERROR: patterns aren't allowed in methods without bodies +} + +fn main() {} diff --git a/tests/ui/parser/issues/error-pattern-issue-50571.stderr b/tests/ui/parser/issues/error-pattern-issue-50571.stderr new file mode 100644 index 0000000000000..47457cff461ce --- /dev/null +++ b/tests/ui/parser/issues/error-pattern-issue-50571.stderr @@ -0,0 +1,28 @@ +error: expected `;` or `]`, found `,` + --> $DIR/error-pattern-issue-50571.rs:6:14 + | +LL | fn foo([a, b]: [i32; 2]) {} + | ^ expected `;` or `]` + | + = note: you might have meant to write a slice or array type +help: you might have meant to use `;` as the separator + | +LL - fn foo([a, b]: [i32; 2]) {} +LL + fn foo([a; b]: [i32; 2]) {} + | + +error[E0642]: patterns aren't allowed in methods without bodies + --> $DIR/error-pattern-issue-50571.rs:6:12 + | +LL | fn foo([a, b]: [i32; 2]) {} + | ^^^^^^ + | +help: give this argument a name or use an underscore to ignore it + | +LL - fn foo([a, b]: [i32; 2]) {} +LL + fn foo(_: [i32; 2]) {} + | + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0642`. diff --git a/tests/ui/parser/recover/array-type-no-semi.rs b/tests/ui/parser/recover/array-type-no-semi.rs index ae5efbaf36ca2..2cc5d979604c7 100644 --- a/tests/ui/parser/recover/array-type-no-semi.rs +++ b/tests/ui/parser/recover/array-type-no-semi.rs @@ -5,14 +5,13 @@ fn main() { let x = 5; let b: [i32, 5]; - //~^ ERROR expected one of `!`, `(`, `+`, `::`, `;`, `<`, or `]`, found `,` - //~| ERROR expected value, found builtin type `i32` [E0423] + //~^ ERROR expected `;` or `]`, found `,` let a: [i32, ]; - //~^ ERROR expected one of `!`, `(`, `+`, `::`, `;`, `<`, or `]`, found `,` + //~^ ERROR expected `;` or `]`, found `,` //~| ERROR expected value, found builtin type `i32` [E0423] let c: [i32, x]; - //~^ ERROR expected one of `!`, `(`, `+`, `::`, `;`, `<`, or `]`, found `,` - //~| ERROR expected value, found builtin type `i32` [E0423] + //~^ ERROR expected `;` or `]`, found `,` + //~| ERROR attempt to use a non-constant value in a constant [E0435] let e: [i32 5]; - //~^ ERROR expected one of `!`, `(`, `+`, `::`, `;`, `<`, or `]`, found `5` + //~^ ERROR expected `;` or `]`, found `5` } diff --git a/tests/ui/parser/recover/array-type-no-semi.stderr b/tests/ui/parser/recover/array-type-no-semi.stderr index 84b7282b4fedb..82330465144c8 100644 --- a/tests/ui/parser/recover/array-type-no-semi.stderr +++ b/tests/ui/parser/recover/array-type-no-semi.stderr @@ -1,56 +1,71 @@ -error: expected one of `!`, `(`, `+`, `::`, `;`, `<`, or `]`, found `,` +error: expected `;` or `]`, found `,` --> $DIR/array-type-no-semi.rs:7:16 | LL | let b: [i32, 5]; - | - ^ expected one of 7 possible tokens - | | - | while parsing the type for `b` - | help: use `=` if you meant to assign + | ^ expected `;` or `]` + | + = note: you might have meant to write a slice or array type +help: you might have meant to use `;` as the separator + | +LL - let b: [i32, 5]; +LL + let b: [i32; 5]; + | -error: expected one of `!`, `(`, `+`, `::`, `;`, `<`, or `]`, found `,` - --> $DIR/array-type-no-semi.rs:10:16 +error: expected `;` or `]`, found `,` + --> $DIR/array-type-no-semi.rs:9:16 | LL | let a: [i32, ]; - | - ^ expected one of 7 possible tokens + | - ^ expected `;` or `]` | | | while parsing the type for `a` | help: use `=` if you meant to assign + | + = note: you might have meant to write a slice or array type -error: expected one of `!`, `(`, `+`, `::`, `;`, `<`, or `]`, found `,` - --> $DIR/array-type-no-semi.rs:13:16 +error: expected `;` or `]`, found `,` + --> $DIR/array-type-no-semi.rs:12:16 | LL | let c: [i32, x]; - | - ^ expected one of 7 possible tokens - | | - | while parsing the type for `c` - | help: use `=` if you meant to assign + | ^ expected `;` or `]` + | + = note: you might have meant to write a slice or array type +help: you might have meant to use `;` as the separator + | +LL - let c: [i32, x]; +LL + let c: [i32; x]; + | -error: expected one of `!`, `(`, `+`, `::`, `;`, `<`, or `]`, found `5` - --> $DIR/array-type-no-semi.rs:16:17 +error: expected `;` or `]`, found `5` + --> $DIR/array-type-no-semi.rs:15:17 | LL | let e: [i32 5]; - | - ^ expected one of 7 possible tokens - | | - | while parsing the type for `e` - -error[E0423]: expected value, found builtin type `i32` - --> $DIR/array-type-no-semi.rs:7:13 + | ^ expected `;` or `]` | -LL | let b: [i32, 5]; - | ^^^ not a value + = note: you might have meant to write a slice or array type +help: you might have meant to use `;` as the separator + | +LL | let e: [i32 ;5]; + | + -error[E0423]: expected value, found builtin type `i32` - --> $DIR/array-type-no-semi.rs:10:13 +error[E0435]: attempt to use a non-constant value in a constant + --> $DIR/array-type-no-semi.rs:12:18 + | +LL | let c: [i32, x]; + | ^ non-constant value + | +help: consider using `const` instead of `let` + | +LL - let x = 5; +LL + const x: /* Type */ = 5; | -LL | let a: [i32, ]; - | ^^^ not a value error[E0423]: expected value, found builtin type `i32` - --> $DIR/array-type-no-semi.rs:13:13 + --> $DIR/array-type-no-semi.rs:9:13 | -LL | let c: [i32, x]; +LL | let a: [i32, ]; | ^^^ not a value -error: aborting due to 7 previous errors +error: aborting due to 6 previous errors -For more information about this error, try `rustc --explain E0423`. +Some errors have detailed explanations: E0423, E0435. +For more information about an error, try `rustc --explain E0423`. diff --git a/tests/ui/parser/removed-syntax/removed-syntax-fixed-vec.rs b/tests/ui/parser/removed-syntax/removed-syntax-fixed-vec.rs index 560efecb91cfc..fb9a1c643fccc 100644 --- a/tests/ui/parser/removed-syntax/removed-syntax-fixed-vec.rs +++ b/tests/ui/parser/removed-syntax/removed-syntax-fixed-vec.rs @@ -1 +1,6 @@ -type v = [isize * 3]; //~ ERROR expected one of `!`, `(`, `+`, `::`, `;`, `<`, or `]`, found `*` +type v = [isize * 3]; +//~^ ERROR expected `;` or `]`, found `*` +//~| WARN type `v` should have an upper camel case name [non_camel_case_types] + + +fn main() {} diff --git a/tests/ui/parser/removed-syntax/removed-syntax-fixed-vec.stderr b/tests/ui/parser/removed-syntax/removed-syntax-fixed-vec.stderr index 5bc9c2ccf00ad..8d7938a1a4699 100644 --- a/tests/ui/parser/removed-syntax/removed-syntax-fixed-vec.stderr +++ b/tests/ui/parser/removed-syntax/removed-syntax-fixed-vec.stderr @@ -1,8 +1,23 @@ -error: expected one of `!`, `(`, `+`, `::`, `;`, `<`, or `]`, found `*` +error: expected `;` or `]`, found `*` --> $DIR/removed-syntax-fixed-vec.rs:1:17 | LL | type v = [isize * 3]; - | ^ expected one of 7 possible tokens + | ^ expected `;` or `]` + | + = note: you might have meant to write a slice or array type +help: you might have meant to use `;` as the separator + | +LL - type v = [isize * 3]; +LL + type v = [isize ; 3]; + | + +warning: type `v` should have an upper camel case name + --> $DIR/removed-syntax-fixed-vec.rs:1:6 + | +LL | type v = [isize * 3]; + | ^ help: convert the identifier to upper camel case (notice the capitalization): `V` + | + = note: `#[warn(non_camel_case_types)]` on by default -error: aborting due to 1 previous error +error: aborting due to 1 previous error; 1 warning emitted