diff options
| author | Michael Goulet <michael@errs.io> | 2022-09-25 22:20:01 +0000 |
|---|---|---|
| committer | Michael Goulet <michael@errs.io> | 2022-09-25 22:34:25 +0000 |
| commit | 4d0d688a3cfd3d58cbd5d8065a7af774a7bb82b6 (patch) | |
| tree | c72acae92de5d053ca511c65197ace59d0e3a9d0 /compiler/rustc_parse/src | |
| parent | f3fafbb006ee98635874f73e480655912b465e65 (diff) | |
| download | rust-4d0d688a3cfd3d58cbd5d8065a7af774a7bb82b6.tar.gz rust-4d0d688a3cfd3d58cbd5d8065a7af774a7bb82b6.zip | |
Recover some items that expect braces and don't take semicolons
Diffstat (limited to 'compiler/rustc_parse/src')
| -rw-r--r-- | compiler/rustc_parse/src/parser/diagnostics.rs | 8 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/item.rs | 29 |
2 files changed, 30 insertions, 7 deletions
diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index dcea11eadcb..8750873c3a4 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -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. diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index e55b5ce71cd..802dfc048f8 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -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}; @@ -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()?); @@ -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))) |
