From ea381663900b90c0f78c6a64cd5e0b1876047714 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Tue, 6 Feb 2024 03:50:22 +0100 Subject: Don't filter out skipped fields --- compiler/rustc_pattern_analysis/src/lib.rs | 3 +-- compiler/rustc_pattern_analysis/src/pat.rs | 5 ----- compiler/rustc_pattern_analysis/src/rustc.rs | 15 +++++-------- compiler/rustc_pattern_analysis/src/usefulness.rs | 27 ++++++++++++++++++----- 4 files changed, 28 insertions(+), 22 deletions(-) (limited to 'compiler/rustc_pattern_analysis/src') diff --git a/compiler/rustc_pattern_analysis/src/lib.rs b/compiler/rustc_pattern_analysis/src/lib.rs index 0b4bc77a976..e58e322a70d 100644 --- a/compiler/rustc_pattern_analysis/src/lib.rs +++ b/compiler/rustc_pattern_analysis/src/lib.rs @@ -109,8 +109,7 @@ pub trait TypeCx: Sized + fmt::Debug { /// The number of fields for this constructor. fn ctor_arity(&self, ctor: &Constructor, ty: &Self::Ty) -> usize; - /// The types of the fields for this constructor. The result must contain `ctor_arity()`-many - /// fields that are not skipped. + /// The types of the fields for this constructor. The result must contain `ctor_arity()` fields. fn ctor_sub_tys<'a>( &'a self, ctor: &'a Constructor, diff --git a/compiler/rustc_pattern_analysis/src/pat.rs b/compiler/rustc_pattern_analysis/src/pat.rs index 642ab74b8b9..8e1c22b92c8 100644 --- a/compiler/rustc_pattern_analysis/src/pat.rs +++ b/compiler/rustc_pattern_analysis/src/pat.rs @@ -23,11 +23,6 @@ impl PatId { /// Values and patterns can be represented as a constructor applied to some fields. This represents /// a pattern in this form. A `DeconstructedPat` will almost always come from user input; the only /// exception are some `Wildcard`s introduced during pattern lowering. -/// -/// Note that the number of fields may not match the fields declared in the original struct/variant. -/// This happens if a private or `non_exhaustive` field is uninhabited, because the code mustn't -/// observe that it is uninhabited. In that case that field is not included in `fields`. Care must -/// be taken when converting to/from `thir::Pat`. pub struct DeconstructedPat { ctor: Constructor, fields: Vec>, diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs index 3b68dd503ad..4e90d1a7406 100644 --- a/compiler/rustc_pattern_analysis/src/rustc.rs +++ b/compiler/rustc_pattern_analysis/src/rustc.rs @@ -271,9 +271,7 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> { } else { let variant = &adt.variant(RustcMatchCheckCtxt::variant_index_for_adt(&ctor, *adt)); - self.list_variant_nonhidden_fields(ty, variant) - .filter(|(_, _, skip)| !skip) - .count() + self.list_variant_nonhidden_fields(ty, variant).count() } } _ => bug!("Unexpected type for constructor `{ctor:?}`: {ty:?}"), @@ -512,14 +510,12 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> { // For each field in the variant, we store the relevant index into `self.fields` if any. let mut field_id_to_id: Vec> = (0..variant.fields.len()).map(|_| None).collect(); - let tys = cx - .list_variant_nonhidden_fields(ty, variant) - .filter(|(_, _, skip)| !skip) - .enumerate() - .map(|(i, (field, ty, _))| { + let tys = cx.list_variant_nonhidden_fields(ty, variant).enumerate().map( + |(i, (field, ty, _))| { field_id_to_id[field.index()] = Some(i); ty - }); + }, + ); fields = tys.map(|ty| DeconstructedPat::wildcard(ty)).collect(); for pat in subpatterns { if let Some(i) = field_id_to_id[pat.field.index()] { @@ -769,7 +765,6 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> { let variant = &adt_def.variant(variant_index); let subpatterns = cx .list_variant_nonhidden_fields(*pat.ty(), variant) - .filter(|(_, _, skip)| !skip) .zip(subpatterns) .map(|((field, _ty, _), pattern)| FieldPat { field, pattern }) .collect(); diff --git a/compiler/rustc_pattern_analysis/src/usefulness.rs b/compiler/rustc_pattern_analysis/src/usefulness.rs index ec9f3bb0db9..99d1f46e804 100644 --- a/compiler/rustc_pattern_analysis/src/usefulness.rs +++ b/compiler/rustc_pattern_analysis/src/usefulness.rs @@ -817,6 +817,9 @@ impl fmt::Display for ValidityConstraint { struct PlaceInfo { /// The type of the place. ty: Cx::Ty, + /// Whether we must skip this field during analysis. This is used when a private field is empty, + /// so that we don't observe its emptiness. + skip: SkipField, /// Whether the place is known to contain valid data. validity: ValidityConstraint, /// Whether the place is the scrutinee itself or a subplace of it. @@ -833,10 +836,9 @@ impl PlaceInfo { ) -> impl Iterator + ExactSizeIterator + Captures<'a> { let ctor_sub_tys = cx.ctor_sub_tys(ctor, &self.ty); let ctor_sub_validity = self.validity.specialize(ctor); - // Collect to keep the `ExactSizeIterator` bound. This is a temporary measure. - let tmp: Vec<_> = ctor_sub_tys.filter(|(_, SkipField(skip))| !skip).collect(); - tmp.into_iter().map(move |(ty, _)| PlaceInfo { + ctor_sub_tys.map(move |(ty, skip)| PlaceInfo { ty, + skip, validity: ctor_sub_validity, is_scrutinee: false, }) @@ -858,6 +860,11 @@ impl PlaceInfo { where Cx: 'a, { + if matches!(self.skip, SkipField(true)) { + // Skip the whole column + return Ok((smallvec![Constructor::Skip], vec![])); + } + let ctors_for_ty = cx.ctors_for_ty(&self.ty)?; // We treat match scrutinees of type `!` or `EmptyEnum` differently. @@ -916,7 +923,12 @@ impl PlaceInfo { impl Clone for PlaceInfo { fn clone(&self) -> Self { - Self { ty: self.ty.clone(), validity: self.validity, is_scrutinee: self.is_scrutinee } + Self { + ty: self.ty.clone(), + skip: self.skip, + validity: self.validity, + is_scrutinee: self.is_scrutinee, + } } } @@ -1123,7 +1135,12 @@ impl<'p, Cx: TypeCx> Matrix<'p, Cx> { scrut_ty: Cx::Ty, scrut_validity: ValidityConstraint, ) -> Self { - let place_info = PlaceInfo { ty: scrut_ty, validity: scrut_validity, is_scrutinee: true }; + let place_info = PlaceInfo { + ty: scrut_ty, + skip: SkipField(false), + validity: scrut_validity, + is_scrutinee: true, + }; let mut matrix = Matrix { rows: Vec::with_capacity(arms.len()), place_info: smallvec![place_info], -- cgit 1.4.1-3-g733a5