Recover and suggest use ; to construct array type

Signed-off-by: xizheyin <xizheyin@smail.nju.edu.cn>
This commit is contained in:
xizheyin 2025-07-14 04:28:20 +08:00
parent 1cac8cbde9
commit ed88af2163
No known key found for this signature in database
GPG key ID: 0A0D90BE99CEDEAD
14 changed files with 183 additions and 87 deletions

View file

@ -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());

View file

@ -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

View file

@ -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

View file

@ -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() {}

View file

@ -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() {}

View file

@ -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`.

View file

@ -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`
}

View file

@ -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

View file

@ -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() {}

View file

@ -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`.

View file

@ -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`
}

View file

@ -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 `]`
|
= 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[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 b: [i32, 5];
| ^^^ not a value
error[E0423]: expected value, found builtin type `i32`
--> $DIR/array-type-no-semi.rs:10:13
--> $DIR/array-type-no-semi.rs:9: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 6 previous errors
error: aborting due to 7 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`.

View file

@ -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() {}

View file

@ -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];
|
error: aborting due to 1 previous error
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; 1 warning emitted