Don't filter out skipped fields
This commit is contained in:
parent
4f7f06777b
commit
ea38166390
4 changed files with 28 additions and 22 deletions
|
@ -109,8 +109,7 @@ pub trait TypeCx: Sized + fmt::Debug {
|
||||||
/// The number of fields for this constructor.
|
/// The number of fields for this constructor.
|
||||||
fn ctor_arity(&self, ctor: &Constructor<Self>, ty: &Self::Ty) -> usize;
|
fn ctor_arity(&self, ctor: &Constructor<Self>, ty: &Self::Ty) -> usize;
|
||||||
|
|
||||||
/// The types of the fields for this constructor. The result must contain `ctor_arity()`-many
|
/// The types of the fields for this constructor. The result must contain `ctor_arity()` fields.
|
||||||
/// fields that are not skipped.
|
|
||||||
fn ctor_sub_tys<'a>(
|
fn ctor_sub_tys<'a>(
|
||||||
&'a self,
|
&'a self,
|
||||||
ctor: &'a Constructor<Self>,
|
ctor: &'a Constructor<Self>,
|
||||||
|
|
|
@ -23,11 +23,6 @@ impl PatId {
|
||||||
/// Values and patterns can be represented as a constructor applied to some fields. This represents
|
/// 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
|
/// 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.
|
/// 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<Cx: TypeCx> {
|
pub struct DeconstructedPat<Cx: TypeCx> {
|
||||||
ctor: Constructor<Cx>,
|
ctor: Constructor<Cx>,
|
||||||
fields: Vec<DeconstructedPat<Cx>>,
|
fields: Vec<DeconstructedPat<Cx>>,
|
||||||
|
|
|
@ -271,9 +271,7 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> {
|
||||||
} else {
|
} else {
|
||||||
let variant =
|
let variant =
|
||||||
&adt.variant(RustcMatchCheckCtxt::variant_index_for_adt(&ctor, *adt));
|
&adt.variant(RustcMatchCheckCtxt::variant_index_for_adt(&ctor, *adt));
|
||||||
self.list_variant_nonhidden_fields(ty, variant)
|
self.list_variant_nonhidden_fields(ty, variant).count()
|
||||||
.filter(|(_, _, skip)| !skip)
|
|
||||||
.count()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => bug!("Unexpected type for constructor `{ctor:?}`: {ty:?}"),
|
_ => 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.
|
// For each field in the variant, we store the relevant index into `self.fields` if any.
|
||||||
let mut field_id_to_id: Vec<Option<usize>> =
|
let mut field_id_to_id: Vec<Option<usize>> =
|
||||||
(0..variant.fields.len()).map(|_| None).collect();
|
(0..variant.fields.len()).map(|_| None).collect();
|
||||||
let tys = cx
|
let tys = cx.list_variant_nonhidden_fields(ty, variant).enumerate().map(
|
||||||
.list_variant_nonhidden_fields(ty, variant)
|
|(i, (field, ty, _))| {
|
||||||
.filter(|(_, _, skip)| !skip)
|
|
||||||
.enumerate()
|
|
||||||
.map(|(i, (field, ty, _))| {
|
|
||||||
field_id_to_id[field.index()] = Some(i);
|
field_id_to_id[field.index()] = Some(i);
|
||||||
ty
|
ty
|
||||||
});
|
},
|
||||||
|
);
|
||||||
fields = tys.map(|ty| DeconstructedPat::wildcard(ty)).collect();
|
fields = tys.map(|ty| DeconstructedPat::wildcard(ty)).collect();
|
||||||
for pat in subpatterns {
|
for pat in subpatterns {
|
||||||
if let Some(i) = field_id_to_id[pat.field.index()] {
|
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 variant = &adt_def.variant(variant_index);
|
||||||
let subpatterns = cx
|
let subpatterns = cx
|
||||||
.list_variant_nonhidden_fields(*pat.ty(), variant)
|
.list_variant_nonhidden_fields(*pat.ty(), variant)
|
||||||
.filter(|(_, _, skip)| !skip)
|
|
||||||
.zip(subpatterns)
|
.zip(subpatterns)
|
||||||
.map(|((field, _ty, _), pattern)| FieldPat { field, pattern })
|
.map(|((field, _ty, _), pattern)| FieldPat { field, pattern })
|
||||||
.collect();
|
.collect();
|
||||||
|
|
|
@ -817,6 +817,9 @@ impl fmt::Display for ValidityConstraint {
|
||||||
struct PlaceInfo<Cx: TypeCx> {
|
struct PlaceInfo<Cx: TypeCx> {
|
||||||
/// The type of the place.
|
/// The type of the place.
|
||||||
ty: Cx::Ty,
|
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.
|
/// Whether the place is known to contain valid data.
|
||||||
validity: ValidityConstraint,
|
validity: ValidityConstraint,
|
||||||
/// Whether the place is the scrutinee itself or a subplace of it.
|
/// Whether the place is the scrutinee itself or a subplace of it.
|
||||||
|
@ -833,10 +836,9 @@ impl<Cx: TypeCx> PlaceInfo<Cx> {
|
||||||
) -> impl Iterator<Item = Self> + ExactSizeIterator + Captures<'a> {
|
) -> impl Iterator<Item = Self> + ExactSizeIterator + Captures<'a> {
|
||||||
let ctor_sub_tys = cx.ctor_sub_tys(ctor, &self.ty);
|
let ctor_sub_tys = cx.ctor_sub_tys(ctor, &self.ty);
|
||||||
let ctor_sub_validity = self.validity.specialize(ctor);
|
let ctor_sub_validity = self.validity.specialize(ctor);
|
||||||
// Collect to keep the `ExactSizeIterator` bound. This is a temporary measure.
|
ctor_sub_tys.map(move |(ty, skip)| PlaceInfo {
|
||||||
let tmp: Vec<_> = ctor_sub_tys.filter(|(_, SkipField(skip))| !skip).collect();
|
|
||||||
tmp.into_iter().map(move |(ty, _)| PlaceInfo {
|
|
||||||
ty,
|
ty,
|
||||||
|
skip,
|
||||||
validity: ctor_sub_validity,
|
validity: ctor_sub_validity,
|
||||||
is_scrutinee: false,
|
is_scrutinee: false,
|
||||||
})
|
})
|
||||||
|
@ -858,6 +860,11 @@ impl<Cx: TypeCx> PlaceInfo<Cx> {
|
||||||
where
|
where
|
||||||
Cx: 'a,
|
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)?;
|
let ctors_for_ty = cx.ctors_for_ty(&self.ty)?;
|
||||||
|
|
||||||
// We treat match scrutinees of type `!` or `EmptyEnum` differently.
|
// We treat match scrutinees of type `!` or `EmptyEnum` differently.
|
||||||
|
@ -916,7 +923,12 @@ impl<Cx: TypeCx> PlaceInfo<Cx> {
|
||||||
|
|
||||||
impl<Cx: TypeCx> Clone for PlaceInfo<Cx> {
|
impl<Cx: TypeCx> Clone for PlaceInfo<Cx> {
|
||||||
fn clone(&self) -> Self {
|
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_ty: Cx::Ty,
|
||||||
scrut_validity: ValidityConstraint,
|
scrut_validity: ValidityConstraint,
|
||||||
) -> Self {
|
) -> 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 {
|
let mut matrix = Matrix {
|
||||||
rows: Vec::with_capacity(arms.len()),
|
rows: Vec::with_capacity(arms.len()),
|
||||||
place_info: smallvec![place_info],
|
place_info: smallvec![place_info],
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue