Skip to content

Commit 3ff78d4

Browse files
authored
Rollup merge of rust-lang#59266 - estebank:struct-parse-recovery, r=petrochenkov
Do not complain about non-existing fields after parse recovery When failing to parse struct-like enum variants, the ADT gets recorded as having no fields. Record that we have actually recovered during parsing of this variant to avoid complaing about non-existing fields when actually using it. Fix rust-lang#57361.
2 parents e6e1ccb + 757eb67 commit 3ff78d4

File tree

15 files changed

+111
-58
lines changed

15 files changed

+111
-58
lines changed

src/librustc/hir/lowering.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2672,7 +2672,7 @@ impl<'a> LoweringContext<'a> {
26722672

26732673
fn lower_variant_data(&mut self, vdata: &VariantData) -> hir::VariantData {
26742674
match *vdata {
2675-
VariantData::Struct(ref fields, id) => {
2675+
VariantData::Struct(ref fields, id, recovered) => {
26762676
let LoweredNodeId { node_id: _, hir_id } = self.lower_node_id(id);
26772677

26782678
hir::VariantData::Struct(
@@ -2682,6 +2682,7 @@ impl<'a> LoweringContext<'a> {
26822682
.map(|f| self.lower_struct_field(f))
26832683
.collect(),
26842684
hir_id,
2685+
recovered,
26852686
)
26862687
},
26872688
VariantData::Tuple(ref fields, id) => {

src/librustc/hir/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2173,7 +2173,7 @@ impl StructField {
21732173
/// Id of the whole struct lives in `Item`.
21742174
#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
21752175
pub enum VariantData {
2176-
Struct(HirVec<StructField>, HirId),
2176+
Struct(HirVec<StructField>, HirId, /* recovered */ bool),
21772177
Tuple(HirVec<StructField>, HirId),
21782178
Unit(HirId),
21792179
}
@@ -2187,7 +2187,7 @@ impl VariantData {
21872187
}
21882188
pub fn hir_id(&self) -> HirId {
21892189
match *self {
2190-
VariantData::Struct(_, hir_id)
2190+
VariantData::Struct(_, hir_id, _)
21912191
| VariantData::Tuple(_, hir_id)
21922192
| VariantData::Unit(hir_id) => hir_id,
21932193
}

src/librustc/ty/mod.rs

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1811,6 +1811,7 @@ pub struct VariantDef {
18111811
pub fields: Vec<FieldDef>,
18121812
pub ctor_kind: CtorKind,
18131813
flags: VariantFlags,
1814+
pub recovered: bool,
18141815
}
18151816

18161817
impl<'a, 'gcx, 'tcx> VariantDef {
@@ -1829,16 +1830,17 @@ impl<'a, 'gcx, 'tcx> VariantDef {
18291830
///
18301831
/// If someone speeds up attribute loading to not be a performance concern, they can
18311832
/// remove this hack and use the constructor `DefId` everywhere.
1832-
pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>,
1833-
did: DefId,
1834-
ident: Ident,
1835-
discr: VariantDiscr,
1836-
fields: Vec<FieldDef>,
1837-
adt_kind: AdtKind,
1838-
ctor_kind: CtorKind,
1839-
attribute_def_id: DefId)
1840-
-> Self
1841-
{
1833+
pub fn new(
1834+
tcx: TyCtxt<'a, 'gcx, 'tcx>,
1835+
did: DefId,
1836+
ident: Ident,
1837+
discr: VariantDiscr,
1838+
fields: Vec<FieldDef>,
1839+
adt_kind: AdtKind,
1840+
ctor_kind: CtorKind,
1841+
attribute_def_id: DefId,
1842+
recovered: bool,
1843+
) -> Self {
18421844
debug!("VariantDef::new({:?}, {:?}, {:?}, {:?}, {:?}, {:?}, {:?})", did, ident, discr,
18431845
fields, adt_kind, ctor_kind, attribute_def_id);
18441846
let mut flags = VariantFlags::NO_VARIANT_FLAGS;
@@ -1852,7 +1854,8 @@ impl<'a, 'gcx, 'tcx> VariantDef {
18521854
discr,
18531855
fields,
18541856
ctor_kind,
1855-
flags
1857+
flags,
1858+
recovered,
18561859
}
18571860
}
18581861

@@ -1868,7 +1871,8 @@ impl_stable_hash_for!(struct VariantDef {
18681871
discr,
18691872
fields,
18701873
ctor_kind,
1871-
flags
1874+
flags,
1875+
recovered
18721876
});
18731877

18741878
#[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable)]

src/librustc_metadata/decoder.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -576,7 +576,8 @@ impl<'a, 'tcx> CrateMetadata {
576576
}).collect(),
577577
adt_kind,
578578
data.ctor_kind,
579-
attribute_def_id
579+
attribute_def_id,
580+
false,
580581
)
581582
}
582583

src/librustc_save_analysis/dump_visitor.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -481,8 +481,8 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
481481
};
482482

483483
let (value, fields) = match item.node {
484-
ast::ItemKind::Struct(ast::VariantData::Struct(ref fields, _), _) |
485-
ast::ItemKind::Union(ast::VariantData::Struct(ref fields, _), _) => {
484+
ast::ItemKind::Struct(ast::VariantData::Struct(ref fields, ..), _) |
485+
ast::ItemKind::Union(ast::VariantData::Struct(ref fields, ..), _) => {
486486
let include_priv_fields = !self.save_ctxt.config.pub_only;
487487
let fields_str = fields
488488
.iter()
@@ -560,7 +560,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
560560
let name_span = variant.node.ident.span;
561561

562562
match variant.node.data {
563-
ast::VariantData::Struct(ref fields, _) => {
563+
ast::VariantData::Struct(ref fields, ..) => {
564564
let fields_str = fields
565565
.iter()
566566
.enumerate()

src/librustc_save_analysis/sig.rs

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -703,7 +703,7 @@ impl Sig for ast::Variant_ {
703703
fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext<'_, '_>) -> Result {
704704
let mut text = self.ident.to_string();
705705
match self.data {
706-
ast::VariantData::Struct(ref fields, id) => {
706+
ast::VariantData::Struct(ref fields, id, r) => {
707707
let name_def = SigElement {
708708
id: id_from_node_id(id, scx),
709709
start: offset,
@@ -712,12 +712,16 @@ impl Sig for ast::Variant_ {
712712
text.push_str(" { ");
713713
let mut defs = vec![name_def];
714714
let mut refs = vec![];
715-
for f in fields {
716-
let field_sig = f.make(offset + text.len(), Some(id), scx)?;
717-
text.push_str(&field_sig.text);
718-
text.push_str(", ");
719-
defs.extend(field_sig.defs.into_iter());
720-
refs.extend(field_sig.refs.into_iter());
715+
if r {
716+
text.push_str("/* parse error */ ");
717+
} else {
718+
for f in fields {
719+
let field_sig = f.make(offset + text.len(), Some(id), scx)?;
720+
text.push_str(&field_sig.text);
721+
text.push_str(", ");
722+
defs.extend(field_sig.defs.into_iter());
723+
refs.extend(field_sig.refs.into_iter());
724+
}
721725
}
722726
text.push('}');
723727
Ok(Signature { text, defs, refs })

src/librustc_typeck/check/_match.rs

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -918,14 +918,16 @@ https://doc.rust-lang.org/reference/types.html#trait-objects");
918918
pat_ty
919919
}
920920

921-
fn check_struct_pat_fields(&self,
922-
adt_ty: Ty<'tcx>,
923-
pat_id: hir::HirId,
924-
span: Span,
925-
variant: &'tcx ty::VariantDef,
926-
fields: &'gcx [Spanned<hir::FieldPat>],
927-
etc: bool,
928-
def_bm: ty::BindingMode) -> bool {
921+
fn check_struct_pat_fields(
922+
&self,
923+
adt_ty: Ty<'tcx>,
924+
pat_id: hir::HirId,
925+
span: Span,
926+
variant: &'tcx ty::VariantDef,
927+
fields: &'gcx [Spanned<hir::FieldPat>],
928+
etc: bool,
929+
def_bm: ty::BindingMode,
930+
) -> bool {
929931
let tcx = self.tcx;
930932

931933
let (substs, adt) = match adt_ty.sty {
@@ -985,7 +987,7 @@ https://doc.rust-lang.org/reference/types.html#trait-objects");
985987
.map(|field| field.ident.modern())
986988
.filter(|ident| !used_fields.contains_key(&ident))
987989
.collect::<Vec<_>>();
988-
if inexistent_fields.len() > 0 {
990+
if inexistent_fields.len() > 0 && !variant.recovered {
989991
let (field_names, t, plural) = if inexistent_fields.len() == 1 {
990992
(format!("a field named `{}`", inexistent_fields[0].1), "this", "")
991993
} else {

src/librustc_typeck/check/mod.rs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3689,12 +3689,17 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
36893689
field, expr_t)
36903690
}
36913691

3692-
fn report_unknown_field(&self,
3693-
ty: Ty<'tcx>,
3694-
variant: &'tcx ty::VariantDef,
3695-
field: &hir::Field,
3696-
skip_fields: &[hir::Field],
3697-
kind_name: &str) {
3692+
fn report_unknown_field(
3693+
&self,
3694+
ty: Ty<'tcx>,
3695+
variant: &'tcx ty::VariantDef,
3696+
field: &hir::Field,
3697+
skip_fields: &[hir::Field],
3698+
kind_name: &str,
3699+
) {
3700+
if variant.recovered {
3701+
return;
3702+
}
36983703
let mut err = self.type_error_struct_with_diag(
36993704
field.ident.span,
37003705
|actual| match ty.sty {

src/librustc_typeck/collect.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -598,14 +598,19 @@ fn convert_variant<'a, 'tcx>(
598598
}
599599
})
600600
.collect();
601+
let recovered = match def {
602+
hir::VariantData::Struct(_, _, r) => *r,
603+
_ => false,
604+
};
601605
ty::VariantDef::new(tcx,
602606
did,
603607
ident,
604608
discr,
605609
fields,
606610
adt_kind,
607611
CtorKind::from_hir(def),
608-
attribute_def_id
612+
attribute_def_id,
613+
recovered,
609614
)
610615
}
611616

src/libsyntax/ast.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -620,7 +620,7 @@ pub enum PatKind {
620620

621621
/// A struct or struct variant pattern (e.g., `Variant {x, y, ..}`).
622622
/// The `bool` is `true` in the presence of a `..`.
623-
Struct(Path, Vec<Spanned<FieldPat>>, bool),
623+
Struct(Path, Vec<Spanned<FieldPat>>, /* recovered */ bool),
624624

625625
/// A tuple struct/variant pattern (`Variant(x, y, .., z)`).
626626
/// If the `..` pattern fragment is present, then `Option<usize>` denotes its position.
@@ -2133,7 +2133,7 @@ pub enum VariantData {
21332133
/// Struct variant.
21342134
///
21352135
/// E.g., `Bar { .. }` as in `enum Foo { Bar { .. } }`.
2136-
Struct(Vec<StructField>, NodeId),
2136+
Struct(Vec<StructField>, NodeId, bool),
21372137
/// Tuple variant.
21382138
///
21392139
/// E.g., `Bar(..)` as in `enum Foo { Bar(..) }`.
@@ -2147,13 +2147,13 @@ pub enum VariantData {
21472147
impl VariantData {
21482148
pub fn fields(&self) -> &[StructField] {
21492149
match *self {
2150-
VariantData::Struct(ref fields, _) | VariantData::Tuple(ref fields, _) => fields,
2150+
VariantData::Struct(ref fields, ..) | VariantData::Tuple(ref fields, _) => fields,
21512151
_ => &[],
21522152
}
21532153
}
21542154
pub fn id(&self) -> NodeId {
21552155
match *self {
2156-
VariantData::Struct(_, id) | VariantData::Tuple(_, id) | VariantData::Unit(id) => id,
2156+
VariantData::Struct(_, id, _) | VariantData::Tuple(_, id) | VariantData::Unit(id) => id,
21572157
}
21582158
}
21592159
pub fn is_struct(&self) -> bool {

0 commit comments

Comments
 (0)