Skip to content

Commit 6f5e8c2

Browse files
authored
Rollup merge of #102286 - compiler-errors:recover-semi-in-block-item, r=davidtwco
Recover some items that expect braces and don't take semicolons Fixes #102262
2 parents e9bec2f + 4d0d688 commit 6f5e8c2

File tree

7 files changed

+78
-11
lines changed

7 files changed

+78
-11
lines changed

compiler/rustc_error_messages/locales/en-US/parser.ftl

+3
Original file line numberDiff line numberDiff line change
@@ -158,3 +158,6 @@ parser_remove_let = expected pattern, found `let`
158158
159159
parser_use_eq_instead = unexpected `==`
160160
.suggestion = try using `=` instead
161+
162+
parser_use_empty_block_not_semi = expected { "`{}`" }, found `;`
163+
.suggestion = try using { "`{}`" } instead

compiler/rustc_parse/src/parser/diagnostics.rs

+8
Original file line numberDiff line numberDiff line change
@@ -745,6 +745,14 @@ pub(crate) struct UseEqInstead {
745745
pub span: Span,
746746
}
747747

748+
#[derive(Diagnostic)]
749+
#[diag(parser::use_empty_block_not_semi)]
750+
pub(crate) struct UseEmptyBlockNotSemi {
751+
#[primary_span]
752+
#[suggestion_hidden(applicability = "machine-applicable", code = "{{}}")]
753+
pub span: Span,
754+
}
755+
748756
// SnapshotParser is used to create a snapshot of the parser
749757
// without causing duplicate errors being emitted when the `Parser`
750758
// is dropped.

compiler/rustc_parse/src/parser/item.rs

+22-7
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use super::diagnostics::{dummy_arg, ConsumeClosingDelim, Error};
1+
use super::diagnostics::{dummy_arg, ConsumeClosingDelim, Error, UseEmptyBlockNotSemi};
22
use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign};
33
use super::{AttrWrapper, FollowedByType, ForceCollect, Parser, PathStyle, TrailingToken};
44

@@ -664,6 +664,14 @@ impl<'a> Parser<'a> {
664664
mut parse_item: impl FnMut(&mut Parser<'a>) -> PResult<'a, Option<Option<T>>>,
665665
) -> PResult<'a, Vec<T>> {
666666
let open_brace_span = self.token.span;
667+
668+
// Recover `impl Ty;` instead of `impl Ty {}`
669+
if self.token == TokenKind::Semi {
670+
self.sess.emit_err(UseEmptyBlockNotSemi { span: self.token.span });
671+
self.bump();
672+
return Ok(vec![]);
673+
}
674+
667675
self.expect(&token::OpenDelim(Delimiter::Brace))?;
668676
attrs.extend(self.parse_inner_attributes()?);
669677

@@ -1305,12 +1313,19 @@ impl<'a> Parser<'a> {
13051313
let mut generics = self.parse_generics()?;
13061314
generics.where_clause = self.parse_where_clause()?;
13071315

1308-
let (variants, _) = self
1309-
.parse_delim_comma_seq(Delimiter::Brace, |p| p.parse_enum_variant())
1310-
.map_err(|e| {
1311-
self.recover_stmt();
1312-
e
1313-
})?;
1316+
// Possibly recover `enum Foo;` instead of `enum Foo {}`
1317+
let (variants, _) = if self.token == TokenKind::Semi {
1318+
self.sess.emit_err(UseEmptyBlockNotSemi { span: self.token.span });
1319+
self.bump();
1320+
(vec![], false)
1321+
} else {
1322+
self.parse_delim_comma_seq(Delimiter::Brace, |p| p.parse_enum_variant()).map_err(
1323+
|e| {
1324+
self.recover_stmt();
1325+
e
1326+
},
1327+
)?
1328+
};
13141329

13151330
let enum_definition = EnumDef { variants: variants.into_iter().flatten().collect() };
13161331
Ok((id, ItemKind::Enum(enum_definition, generics)))
+4-1
Original file line numberDiff line numberDiff line change
@@ -1 +1,4 @@
1-
impl Foo; //~ ERROR expected one of `!`, `(`, `+`, `::`, `<`, `for`, `where`, or `{`, found `;`
1+
struct Foo;
2+
impl Foo; //~ ERROR expected `{}`, found `;`
3+
4+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1-
error: expected one of `!`, `(`, `+`, `::`, `<`, `for`, `where`, or `{`, found `;`
2-
--> $DIR/empty-impl-semicolon.rs:1:9
1+
error: expected `{}`, found `;`
2+
--> $DIR/empty-impl-semicolon.rs:2:9
33
|
44
LL | impl Foo;
5-
| ^ expected one of 8 possible tokens
5+
| ^
6+
|
7+
= help: try using `{}` instead
68

79
error: aborting due to previous error
810

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
trait Trait;
2+
//~^ ERROR expected `{}`, found `;`
3+
4+
impl Trait for ();
5+
//~^ ERROR expected `{}`, found `;`
6+
7+
enum Enum;
8+
//~^ ERROR expected `{}`, found `;`
9+
10+
fn main() {}
+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
error: expected `{}`, found `;`
2+
--> $DIR/item-needs-block.rs:1:12
3+
|
4+
LL | trait Trait;
5+
| ^
6+
|
7+
= help: try using `{}` instead
8+
9+
error: expected `{}`, found `;`
10+
--> $DIR/item-needs-block.rs:4:18
11+
|
12+
LL | impl Trait for ();
13+
| ^
14+
|
15+
= help: try using `{}` instead
16+
17+
error: expected `{}`, found `;`
18+
--> $DIR/item-needs-block.rs:7:10
19+
|
20+
LL | enum Enum;
21+
| ^
22+
|
23+
= help: try using `{}` instead
24+
25+
error: aborting due to 3 previous errors
26+

0 commit comments

Comments
 (0)