Skip to content

Commit 7529dba

Browse files
committed
Don't filter out skipped fields
1 parent d3ff429 commit 7529dba

File tree

4 files changed

+29
-23
lines changed

4 files changed

+29
-23
lines changed

compiler/rustc_pattern_analysis/src/lib.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -109,8 +109,7 @@ pub trait TypeCx: Sized + fmt::Debug {
109109
/// The number of fields for this constructor.
110110
fn ctor_arity(&self, ctor: &Constructor<Self>, ty: &Self::Ty) -> usize;
111111

112-
/// The types of the fields for this constructor. The result must contain `ctor_arity()`-many
113-
/// fields that are not skipped.
112+
/// The types of the fields for this constructor. The result must contain `ctor_arity()` fields.
114113
fn ctor_sub_tys<'a>(
115114
&'a self,
116115
ctor: &'a Constructor<Self>,

compiler/rustc_pattern_analysis/src/pat.rs

+1-6
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,7 @@ use self::Constructor::*;
1515
/// This also uses interior mutability to keep track of whether the pattern has been found reachable
1616
/// during analysis. For this reason they cannot be cloned.
1717
/// A `DeconstructedPat` will almost always come from user input; the only exception are some
18-
/// `Wildcard`s introduced during specialization.
19-
///
20-
/// Note that the number of fields may not match the fields declared in the original struct/variant.
21-
/// This happens if a private or `non_exhaustive` field is uninhabited, because the code mustn't
22-
/// observe that it is uninhabited. In that case that field is not included in `fields`. Care must
23-
/// be taken when converting to/from `thir::Pat`.
18+
/// `Wildcard`s introduced during pattern lowering.
2419
pub struct DeconstructedPat<Cx: TypeCx> {
2520
ctor: Constructor<Cx>,
2621
fields: Vec<DeconstructedPat<Cx>>,

compiler/rustc_pattern_analysis/src/rustc.rs

+5-10
Original file line numberDiff line numberDiff line change
@@ -271,9 +271,7 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> {
271271
} else {
272272
let variant =
273273
&adt.variant(RustcMatchCheckCtxt::variant_index_for_adt(&ctor, *adt));
274-
self.list_variant_nonhidden_fields(ty, variant)
275-
.filter(|(_, _, skip)| !skip)
276-
.count()
274+
self.list_variant_nonhidden_fields(ty, variant).count()
277275
}
278276
}
279277
_ => bug!("Unexpected type for constructor `{ctor:?}`: {ty:?}"),
@@ -512,14 +510,12 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> {
512510
// For each field in the variant, we store the relevant index into `self.fields` if any.
513511
let mut field_id_to_id: Vec<Option<usize>> =
514512
(0..variant.fields.len()).map(|_| None).collect();
515-
let tys = cx
516-
.list_variant_nonhidden_fields(ty, variant)
517-
.filter(|(_, _, skip)| !skip)
518-
.enumerate()
519-
.map(|(i, (field, ty, _))| {
513+
let tys = cx.list_variant_nonhidden_fields(ty, variant).enumerate().map(
514+
|(i, (field, ty, _))| {
520515
field_id_to_id[field.index()] = Some(i);
521516
ty
522-
});
517+
},
518+
);
523519
fields = tys.map(|ty| DeconstructedPat::wildcard(ty)).collect();
524520
for pat in subpatterns {
525521
if let Some(i) = field_id_to_id[pat.field.index()] {
@@ -769,7 +765,6 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> {
769765
let variant = &adt_def.variant(variant_index);
770766
let subpatterns = cx
771767
.list_variant_nonhidden_fields(*pat.ty(), variant)
772-
.filter(|(_, _, skip)| !skip)
773768
.zip(subpatterns)
774769
.map(|((field, _ty, _), pattern)| FieldPat { field, pattern })
775770
.collect();

compiler/rustc_pattern_analysis/src/usefulness.rs

+22-5
Original file line numberDiff line numberDiff line change
@@ -824,6 +824,9 @@ impl fmt::Display for ValidityConstraint {
824824
struct PlaceInfo<Cx: TypeCx> {
825825
/// The type of the place.
826826
ty: Cx::Ty,
827+
/// Whether we must skip this field during analysis. This is used when a private field is empty,
828+
/// so that we don't observe its emptiness.
829+
skip: SkipField,
827830
/// Whether the place is known to contain valid data.
828831
validity: ValidityConstraint,
829832
/// Whether the place is the scrutinee itself or a subplace of it.
@@ -840,10 +843,9 @@ impl<Cx: TypeCx> PlaceInfo<Cx> {
840843
) -> impl Iterator<Item = Self> + ExactSizeIterator + Captures<'a> {
841844
let ctor_sub_tys = cx.ctor_sub_tys(ctor, &self.ty);
842845
let ctor_sub_validity = self.validity.specialize(ctor);
843-
// Collect to keep the `ExactSizeIterator` bound. This is a temporary measure.
844-
let tmp: Vec<_> = ctor_sub_tys.filter(|(_, SkipField(skip))| !skip).collect();
845-
tmp.into_iter().map(move |(ty, _)| PlaceInfo {
846+
ctor_sub_tys.map(move |(ty, skip)| PlaceInfo {
846847
ty,
848+
skip,
847849
validity: ctor_sub_validity,
848850
is_scrutinee: false,
849851
})
@@ -865,6 +867,11 @@ impl<Cx: TypeCx> PlaceInfo<Cx> {
865867
where
866868
Cx: 'a,
867869
{
870+
if matches!(self.skip, SkipField(true)) {
871+
// Skip the whole column
872+
return Ok((smallvec![Constructor::Skip], vec![]));
873+
}
874+
868875
let ctors_for_ty = cx.ctors_for_ty(&self.ty)?;
869876

870877
// We treat match scrutinees of type `!` or `EmptyEnum` differently.
@@ -923,7 +930,12 @@ impl<Cx: TypeCx> PlaceInfo<Cx> {
923930

924931
impl<Cx: TypeCx> Clone for PlaceInfo<Cx> {
925932
fn clone(&self) -> Self {
926-
Self { ty: self.ty.clone(), validity: self.validity, is_scrutinee: self.is_scrutinee }
933+
Self {
934+
ty: self.ty.clone(),
935+
skip: self.skip,
936+
validity: self.validity,
937+
is_scrutinee: self.is_scrutinee,
938+
}
927939
}
928940
}
929941

@@ -1130,7 +1142,12 @@ impl<'p, Cx: TypeCx> Matrix<'p, Cx> {
11301142
scrut_ty: Cx::Ty,
11311143
scrut_validity: ValidityConstraint,
11321144
) -> Self {
1133-
let place_info = PlaceInfo { ty: scrut_ty, validity: scrut_validity, is_scrutinee: true };
1145+
let place_info = PlaceInfo {
1146+
ty: scrut_ty,
1147+
skip: SkipField(false),
1148+
validity: scrut_validity,
1149+
is_scrutinee: true,
1150+
};
11341151
let mut matrix = Matrix {
11351152
rows: Vec::with_capacity(arms.len()),
11361153
place_info: smallvec![place_info],

0 commit comments

Comments
 (0)