about summary refs log tree commit diff
diff options
context:
space:
mode:
authorxizheyin <xizheyin@smail.nju.edu.cn>2025-07-14 04:28:20 +0800
committerxizheyin <xizheyin@smail.nju.edu.cn>2025-07-15 12:00:46 +0800
commited88af21637ff3677100fd26f8db354cd6134ad4 (patch)
treed03f55a747f4481c6674f693f42131663bfee0ce
parent1cac8cbde98e7b15ad24fc96af4864cdd67b9c30 (diff)
downloadrust-ed88af21637ff3677100fd26f8db354cd6134ad4.tar.gz
rust-ed88af21637ff3677100fd26f8db354cd6134ad4.zip
Recover and suggest use `;` to construct array type
Signed-off-by: xizheyin <xizheyin@smail.nju.edu.cn>
-rw-r--r--compiler/rustc_parse/src/parser/ty.rs59
-rw-r--r--src/tools/tidy/src/issues.txt1
-rw-r--r--src/tools/tidy/src/ui_tests.rs2
-rw-r--r--tests/ui/issues/issue-50571.fixed10
-rw-r--r--tests/ui/issues/issue-50571.rs10
-rw-r--r--tests/ui/issues/issue-50571.stderr15
-rw-r--r--tests/ui/parser/better-expected.rs2
-rw-r--r--tests/ui/parser/better-expected.stderr12
-rw-r--r--tests/ui/parser/issues/error-pattern-issue-50571.rs11
-rw-r--r--tests/ui/parser/issues/error-pattern-issue-50571.stderr28
-rw-r--r--tests/ui/parser/recover/array-type-no-semi.rs11
-rw-r--r--tests/ui/parser/recover/array-type-no-semi.stderr79
-rw-r--r--tests/ui/parser/removed-syntax/removed-syntax-fixed-vec.rs7
-rw-r--r--tests/ui/parser/removed-syntax/removed-syntax-fixed-vec.stderr21
14 files changed, 182 insertions, 86 deletions
diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs
index a997be3405d..740dd10ea8b 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<Ty>) -> 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 cac4dba2b49..8b57db23d01 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 53226fcb80e..74f8104c7e9 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 6d73f17cca4..00000000000
--- 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 dd840ffe4d1..00000000000
--- 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 9b00fe0f5db..00000000000
--- 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 16b61caa4df..91128c39691 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 f4ec933be16..4646ce7eff0 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 00000000000..0c2ce6052cb
--- /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 00000000000..47457cff461
--- /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 ae5efbaf36c..2cc5d979604 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 84b7282b4fe..82330465144 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 560efecb91c..fb9a1c643fc 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 5bc9c2ccf00..8d7938a1a46 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