Skip to content

Commit

Permalink
Rollup merge of rust-lang#102286 - compiler-errors:recover-semi-in-bl…
Browse files Browse the repository at this point in the history
…ock-item, r=davidtwco

Recover some items that expect braces and don't take semicolons

Fixes rust-lang#102262
  • Loading branch information
matthiaskrgr authored Sep 26, 2022
2 parents e9bec2f + 4d0d688 commit 6f5e8c2
Show file tree
Hide file tree
Showing 7 changed files with 78 additions and 11 deletions.
3 changes: 3 additions & 0 deletions compiler/rustc_error_messages/locales/en-US/parser.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -158,3 +158,6 @@ parser_remove_let = expected pattern, found `let`
parser_use_eq_instead = unexpected `==`
.suggestion = try using `=` instead
parser_use_empty_block_not_semi = expected { "`{}`" }, found `;`
.suggestion = try using { "`{}`" } instead
8 changes: 8 additions & 0 deletions compiler/rustc_parse/src/parser/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -745,6 +745,14 @@ pub(crate) struct UseEqInstead {
pub span: Span,
}

#[derive(Diagnostic)]
#[diag(parser::use_empty_block_not_semi)]
pub(crate) struct UseEmptyBlockNotSemi {
#[primary_span]
#[suggestion_hidden(applicability = "machine-applicable", code = "{{}}")]
pub span: Span,
}

// SnapshotParser is used to create a snapshot of the parser
// without causing duplicate errors being emitted when the `Parser`
// is dropped.
Expand Down
29 changes: 22 additions & 7 deletions compiler/rustc_parse/src/parser/item.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use super::diagnostics::{dummy_arg, ConsumeClosingDelim, Error};
use super::diagnostics::{dummy_arg, ConsumeClosingDelim, Error, UseEmptyBlockNotSemi};
use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign};
use super::{AttrWrapper, FollowedByType, ForceCollect, Parser, PathStyle, TrailingToken};

Expand Down Expand Up @@ -664,6 +664,14 @@ impl<'a> Parser<'a> {
mut parse_item: impl FnMut(&mut Parser<'a>) -> PResult<'a, Option<Option<T>>>,
) -> PResult<'a, Vec<T>> {
let open_brace_span = self.token.span;

// Recover `impl Ty;` instead of `impl Ty {}`
if self.token == TokenKind::Semi {
self.sess.emit_err(UseEmptyBlockNotSemi { span: self.token.span });
self.bump();
return Ok(vec![]);
}

self.expect(&token::OpenDelim(Delimiter::Brace))?;
attrs.extend(self.parse_inner_attributes()?);

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

let (variants, _) = self
.parse_delim_comma_seq(Delimiter::Brace, |p| p.parse_enum_variant())
.map_err(|e| {
self.recover_stmt();
e
})?;
// Possibly recover `enum Foo;` instead of `enum Foo {}`
let (variants, _) = if self.token == TokenKind::Semi {
self.sess.emit_err(UseEmptyBlockNotSemi { span: self.token.span });
self.bump();
(vec![], false)
} else {
self.parse_delim_comma_seq(Delimiter::Brace, |p| p.parse_enum_variant()).map_err(
|e| {
self.recover_stmt();
e
},
)?
};

let enum_definition = EnumDef { variants: variants.into_iter().flatten().collect() };
Ok((id, ItemKind::Enum(enum_definition, generics)))
Expand Down
5 changes: 4 additions & 1 deletion src/test/ui/parser/empty-impl-semicolon.rs
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
impl Foo; //~ ERROR expected one of `!`, `(`, `+`, `::`, `<`, `for`, `where`, or `{`, found `;`
struct Foo;
impl Foo; //~ ERROR expected `{}`, found `;`

fn main() {}
8 changes: 5 additions & 3 deletions src/test/ui/parser/empty-impl-semicolon.stderr
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
error: expected one of `!`, `(`, `+`, `::`, `<`, `for`, `where`, or `{`, found `;`
--> $DIR/empty-impl-semicolon.rs:1:9
error: expected `{}`, found `;`
--> $DIR/empty-impl-semicolon.rs:2:9
|
LL | impl Foo;
| ^ expected one of 8 possible tokens
| ^
|
= help: try using `{}` instead

error: aborting due to previous error

10 changes: 10 additions & 0 deletions src/test/ui/parser/item-needs-block.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
trait Trait;
//~^ ERROR expected `{}`, found `;`

impl Trait for ();
//~^ ERROR expected `{}`, found `;`

enum Enum;
//~^ ERROR expected `{}`, found `;`

fn main() {}
26 changes: 26 additions & 0 deletions src/test/ui/parser/item-needs-block.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
error: expected `{}`, found `;`
--> $DIR/item-needs-block.rs:1:12
|
LL | trait Trait;
| ^
|
= help: try using `{}` instead

error: expected `{}`, found `;`
--> $DIR/item-needs-block.rs:4:18
|
LL | impl Trait for ();
| ^
|
= help: try using `{}` instead

error: expected `{}`, found `;`
--> $DIR/item-needs-block.rs:7:10
|
LL | enum Enum;
| ^
|
= help: try using `{}` instead

error: aborting due to 3 previous errors

0 comments on commit 6f5e8c2

Please sign in to comment.