Skip to content

Commit 2514c9d

Browse files
committed
Try another recovery strategy
1 parent 5cc403e commit 2514c9d

File tree

4 files changed

+228
-181
lines changed

4 files changed

+228
-181
lines changed

compiler/rustc_ast/src/token.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -486,6 +486,8 @@ impl Token {
486486
Lt | BinOp(Shl) | // associated path
487487
ModSep => true, // global path
488488
Interpolated(ref nt) => matches!(**nt, NtTy(..) | NtPath(..)),
489+
// for anonymous structs or unions, thay only appears in specific positions
490+
// (type of struct fields or union fields), we don't consider them as regular types
489491
_ => false,
490492
}
491493
}

compiler/rustc_parse/src/parser/item.rs

Lines changed: 37 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use super::diagnostics::{dummy_arg, ConsumeClosingDelim};
2-
use super::ty::{AllowPlus, MaybeRecoverAnonStructOrUnion, RecoverQPath, RecoverReturnSign};
2+
use super::ty::{AllowAnonStructOrUnion, AllowPlus, RecoverQPath, RecoverReturnSign};
33
use super::{AttrWrapper, FollowedByType, ForceCollect, Parser, PathStyle, TrailingToken};
44
use crate::errors::{self, MacroExpandsToAdtField};
55
use crate::fluent_generated as fluent;
@@ -562,103 +562,42 @@ impl<'a> Parser<'a> {
562562

563563
let polarity = self.parse_polarity();
564564

565-
let mut snapshot_before_last_ty = self.create_snapshot_for_diagnostic();
566565
// Parse both types and traits as a type, then reinterpret if necessary.
567566
let err_path = |span| ast::Path::from_ident(Ident::new(kw::Empty, span));
568-
let mut ty_first =
569-
if self.token.is_keyword(kw::For) && self.look_ahead(1, |t| t != &token::Lt) {
570-
let span = self.prev_token.span.between(self.token.span);
571-
self.struct_span_err(span, "missing trait in a trait impl")
572-
.span_suggestion(
573-
span,
574-
"add a trait here",
575-
" Trait ",
576-
Applicability::HasPlaceholders,
577-
)
578-
.span_suggestion(
579-
span.to(self.token.span),
580-
"for an inherent impl, drop this `for`",
581-
"",
582-
Applicability::MaybeIncorrect,
583-
)
584-
.emit();
585-
P(Ty {
586-
kind: TyKind::Path(None, err_path(span)),
587-
span,
588-
id: DUMMY_NODE_ID,
589-
tokens: None,
590-
})
591-
} else {
592-
self.parse_ty_with_generics_recovery(&generics)?
593-
};
567+
let ty_first = if self.token.is_keyword(kw::For) && self.look_ahead(1, |t| t != &token::Lt)
568+
{
569+
let span = self.prev_token.span.between(self.token.span);
570+
self.sess.emit_err(errors::MissingTraitInTraitImpl {
571+
span,
572+
for_span: span.to(self.token.span),
573+
});
574+
P(Ty {
575+
kind: TyKind::Path(None, err_path(span)),
576+
span,
577+
id: DUMMY_NODE_ID,
578+
tokens: None,
579+
})
580+
} else {
581+
self.parse_ty_with_generics_recovery(&generics)?
582+
};
594583

595584
// If `for` is missing we try to recover.
596585
let has_for = self.eat_keyword(kw::For);
597586
let missing_for_span = self.prev_token.span.between(self.token.span);
598587

599-
let mut ty_second = if self.token == token::DotDot {
588+
let ty_second = if self.token == token::DotDot {
600589
// We need to report this error after `cfg` expansion for compatibility reasons
601590
self.bump(); // `..`, do not add it to expected tokens
602591
Some(self.mk_ty(self.prev_token.span, TyKind::Err))
603592
} else if has_for || self.token.can_begin_type() {
604-
snapshot_before_last_ty = self.create_snapshot_for_diagnostic();
605-
Some(self.parse_ty()?)
593+
Some(self.parse_second_ty_for_item_impl()?)
606594
} else {
607595
None
608596
};
609597

610598
generics.where_clause = self.parse_where_clause()?;
611599

612-
let (mut impl_items, err) =
613-
self.parse_item_list(attrs, |p| p.parse_impl_item(ForceCollect::No))?;
614-
615-
if let Some(mut err) = err {
616-
let mut snapshot = snapshot_before_last_ty;
617-
618-
if snapshot.can_start_anonymous_union() {
619-
let recover_result = {
620-
let recover_last_ty = match snapshot.parse_ty() {
621-
Ok(ty) => Some(ty),
622-
Err(snapshot_err) => {
623-
snapshot_err.cancel();
624-
None
625-
}
626-
};
627-
628-
let impl_items = match snapshot
629-
.parse_item_list(attrs, |p| p.parse_impl_item(ForceCollect::No))
630-
{
631-
Ok((impl_items, None)) => Some(impl_items),
632-
Ok((_, Some(snapshot_err))) => {
633-
snapshot_err.cancel();
634-
None
635-
}
636-
Err(snapshot_err) => {
637-
snapshot_err.cancel();
638-
None
639-
}
640-
};
641-
642-
(recover_last_ty, impl_items)
643-
};
644-
645-
if let (Some(recover_last_ty), Some(new_impl_items)) = recover_result {
646-
err.delay_as_bug();
647-
self.restore_snapshot(snapshot);
648-
649-
if ty_second.is_some() {
650-
ty_second = Some(recover_last_ty);
651-
} else {
652-
ty_first = recover_last_ty;
653-
}
654-
impl_items = new_impl_items;
655-
} else {
656-
err.emit();
657-
}
658-
} else {
659-
err.emit();
660-
}
661-
}
600+
let impl_items = self.parse_item_list(attrs, |p| p.parse_impl_item(ForceCollect::No))?;
662601

663602
let item_kind = match ty_second {
664603
Some(ty_second) => {
@@ -727,21 +666,20 @@ impl<'a> Parser<'a> {
727666
&mut self,
728667
attrs: &mut AttrVec,
729668
mut parse_item: impl FnMut(&mut Parser<'a>) -> PResult<'a, Option<Option<T>>>,
730-
) -> PResult<'a, (ThinVec<T>, Option<DiagnosticBuilder<'a, ErrorGuaranteed>>)> {
669+
) -> PResult<'a, ThinVec<T>> {
731670
let open_brace_span = self.token.span;
732671

733672
// Recover `impl Ty;` instead of `impl Ty {}`
734673
if self.token == TokenKind::Semi {
735674
self.sess.emit_err(errors::UseEmptyBlockNotSemi { span: self.token.span });
736675
self.bump();
737-
return Ok((ThinVec::new(), None));
676+
return Ok(ThinVec::new());
738677
}
739678

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

743682
let mut items = ThinVec::new();
744-
let mut delayed_err = None;
745683
while !self.eat(&token::CloseDelim(Delimiter::Brace)) {
746684
if self.recover_doc_comment_before_brace() {
747685
continue;
@@ -803,21 +741,21 @@ impl<'a> Parser<'a> {
803741
Applicability::MaybeIncorrect,
804742
);
805743
}
806-
delayed_err = Some(err);
744+
err.emit();
807745
break;
808746
}
809747
Ok(Some(item)) => items.extend(item),
810748
Err(mut err) => {
811749
self.consume_block(Delimiter::Brace, ConsumeClosingDelim::Yes);
812750
err.span_label(open_brace_span, "while parsing this item list starting here")
813-
.span_label(self.prev_token.span, "the item list ends here");
751+
.span_label(self.prev_token.span, "the item list ends here")
752+
.emit();
814753

815-
delayed_err = Some(err);
816754
break;
817755
}
818756
}
819757
}
820-
Ok((items, delayed_err))
758+
Ok(items)
821759
}
822760

823761
/// Recover on a doc comment before `}`.
@@ -908,13 +846,7 @@ impl<'a> Parser<'a> {
908846
} else {
909847
// It's a normal trait.
910848
generics.where_clause = self.parse_where_clause()?;
911-
let (items, err) =
912-
self.parse_item_list(attrs, |p| p.parse_trait_item(ForceCollect::No))?;
913-
914-
if let Some(mut err) = err {
915-
err.emit();
916-
}
917-
849+
let items = self.parse_item_list(attrs, |p| p.parse_trait_item(ForceCollect::No))?;
918850
Ok((
919851
ident,
920852
ItemKind::Trait(Box::new(Trait { is_auto, unsafety, generics, bounds, items })),
@@ -1182,13 +1114,11 @@ impl<'a> Parser<'a> {
11821114
self.eat_keyword(kw::Unsafe);
11831115
}
11841116

1185-
let (items, err) =
1186-
self.parse_item_list(attrs, |p| p.parse_foreign_item(ForceCollect::No))?;
1187-
if let Some(mut err) = err {
1188-
err.emit();
1189-
}
1190-
1191-
let module = ast::ForeignMod { unsafety, abi, items };
1117+
let module = ast::ForeignMod {
1118+
unsafety,
1119+
abi,
1120+
items: self.parse_item_list(attrs, |p| p.parse_foreign_item(ForceCollect::No))?,
1121+
};
11921122
Ok((Ident::empty(), ItemKind::ForeignMod(module)))
11931123
}
11941124

@@ -1675,7 +1605,7 @@ impl<'a> Parser<'a> {
16751605
adt_ty,
16761606
ident_span,
16771607
parsed_where,
1678-
MaybeRecoverAnonStructOrUnion::Parse,
1608+
AllowAnonStructOrUnion::Yes,
16791609
)
16801610
}
16811611

@@ -1684,7 +1614,7 @@ impl<'a> Parser<'a> {
16841614
adt_ty: &str,
16851615
ident_span: Span,
16861616
parsed_where: bool,
1687-
maybe_recover_anon_struct_or_union: MaybeRecoverAnonStructOrUnion,
1617+
allow_anon_struct_or_union: AllowAnonStructOrUnion<'a>,
16881618
) -> PResult<'a, (ThinVec<FieldDef>, /* recovered */ bool)> {
16891619
let mut fields = ThinVec::new();
16901620
let mut recovered = false;
@@ -1704,9 +1634,9 @@ impl<'a> Parser<'a> {
17041634
// record struct body but an `impl` body.
17051635
//
17061636
// Instead, the error should be thrown and handled by the caller
1707-
// `parse_anonymous_struct_or_union`.
1708-
if maybe_recover_anon_struct_or_union
1709-
== MaybeRecoverAnonStructOrUnion::Recover
1637+
// `parse_anon_struct_or_union`.
1638+
if let AllowAnonStructOrUnion::RecoverNonEmptyOrElse(_) =
1639+
allow_anon_struct_or_union
17101640
{
17111641
return Err(err);
17121642
}

0 commit comments

Comments
 (0)