mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 16:24:46 +00:00
Simplify
This commit is contained in:
parent
ea38166390
commit
39441e4cdd
@ -10,7 +10,7 @@ use rustc_middle::mir::interpret::Scalar;
|
|||||||
use rustc_middle::mir::{self, Const};
|
use rustc_middle::mir::{self, Const};
|
||||||
use rustc_middle::thir::{FieldPat, Pat, PatKind, PatRange, PatRangeBoundary};
|
use rustc_middle::thir::{FieldPat, Pat, PatKind, PatRange, PatRangeBoundary};
|
||||||
use rustc_middle::ty::layout::IntegerExt;
|
use rustc_middle::ty::layout::IntegerExt;
|
||||||
use rustc_middle::ty::{self, OpaqueTypeKey, Ty, TyCtxt, TypeVisitableExt, VariantDef};
|
use rustc_middle::ty::{self, FieldDef, OpaqueTypeKey, Ty, TyCtxt, TypeVisitableExt, VariantDef};
|
||||||
use rustc_session::lint;
|
use rustc_session::lint;
|
||||||
use rustc_span::{ErrorGuaranteed, Span, DUMMY_SP};
|
use rustc_span::{ErrorGuaranteed, Span, DUMMY_SP};
|
||||||
use rustc_target::abi::{FieldIdx, Integer, VariantIdx, FIRST_VARIANT};
|
use rustc_target::abi::{FieldIdx, Integer, VariantIdx, FIRST_VARIANT};
|
||||||
@ -158,32 +158,19 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// In the cases of either a `#[non_exhaustive]` field list or a non-public field, we hide
|
pub(crate) fn variant_sub_tys(
|
||||||
// uninhabited fields in order not to reveal the uninhabitedness of the whole variant.
|
|
||||||
// This lists the fields we keep along with their types.
|
|
||||||
pub(crate) fn list_variant_nonhidden_fields(
|
|
||||||
&self,
|
&self,
|
||||||
ty: RevealedTy<'tcx>,
|
ty: RevealedTy<'tcx>,
|
||||||
variant: &'tcx VariantDef,
|
variant: &'tcx VariantDef,
|
||||||
) -> impl Iterator<Item = (FieldIdx, RevealedTy<'tcx>, bool)> + Captures<'p> + Captures<'_>
|
) -> impl Iterator<Item = (&'tcx FieldDef, RevealedTy<'tcx>)> + Captures<'p> + Captures<'_>
|
||||||
{
|
{
|
||||||
let cx = self;
|
let ty::Adt(_, args) = ty.kind() else { bug!() };
|
||||||
let ty::Adt(adt, args) = ty.kind() else { bug!() };
|
variant.fields.iter().map(move |field| {
|
||||||
// Whether we must avoid matching the fields of this variant exhaustively.
|
let ty = field.ty(self.tcx, args);
|
||||||
let is_non_exhaustive = variant.is_field_list_non_exhaustive() && !adt.did().is_local();
|
|
||||||
|
|
||||||
variant.fields.iter().enumerate().map(move |(i, field)| {
|
|
||||||
let ty = field.ty(cx.tcx, args);
|
|
||||||
// `field.ty()` doesn't normalize after instantiating.
|
// `field.ty()` doesn't normalize after instantiating.
|
||||||
let ty = cx.tcx.normalize_erasing_regions(cx.param_env, ty);
|
let ty = self.tcx.normalize_erasing_regions(self.param_env, ty);
|
||||||
let is_visible = adt.is_enum() || field.vis.is_accessible_from(cx.module, cx.tcx);
|
let ty = self.reveal_opaque_ty(ty);
|
||||||
let is_uninhabited = (cx.tcx.features().exhaustive_patterns
|
(field, ty)
|
||||||
|| cx.tcx.features().min_exhaustive_patterns)
|
|
||||||
&& cx.is_uninhabited(ty);
|
|
||||||
|
|
||||||
let skip = is_uninhabited && (!is_visible || is_non_exhaustive);
|
|
||||||
let ty = cx.reveal_opaque_ty(ty);
|
|
||||||
(FieldIdx::new(i), ty, skip)
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -230,9 +217,21 @@ 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));
|
||||||
let tys = cx
|
|
||||||
.list_variant_nonhidden_fields(ty, variant)
|
// In the cases of either a `#[non_exhaustive]` field list or a non-public
|
||||||
.map(|(_, ty, skip)| (ty, SkipField(skip)));
|
// field, we skip uninhabited fields in order not to reveal the
|
||||||
|
// uninhabitedness of the whole variant.
|
||||||
|
let is_non_exhaustive =
|
||||||
|
variant.is_field_list_non_exhaustive() && !adt.did().is_local();
|
||||||
|
let tys = cx.variant_sub_tys(ty, variant).map(|(field, ty)| {
|
||||||
|
let is_visible =
|
||||||
|
adt.is_enum() || field.vis.is_accessible_from(cx.module, cx.tcx);
|
||||||
|
let is_uninhabited = (cx.tcx.features().exhaustive_patterns
|
||||||
|
|| cx.tcx.features().min_exhaustive_patterns)
|
||||||
|
&& cx.is_uninhabited(*ty);
|
||||||
|
let skip = is_uninhabited && (!is_visible || is_non_exhaustive);
|
||||||
|
(ty, SkipField(skip))
|
||||||
|
});
|
||||||
cx.dropless_arena.alloc_from_iter(tys)
|
cx.dropless_arena.alloc_from_iter(tys)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -269,9 +268,8 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> {
|
|||||||
// patterns. If we're here we can assume this is a box pattern.
|
// patterns. If we're here we can assume this is a box pattern.
|
||||||
1
|
1
|
||||||
} else {
|
} else {
|
||||||
let variant =
|
let variant_idx = RustcMatchCheckCtxt::variant_index_for_adt(&ctor, *adt);
|
||||||
&adt.variant(RustcMatchCheckCtxt::variant_index_for_adt(&ctor, *adt));
|
adt.variant(variant_idx).fields.len()
|
||||||
self.list_variant_nonhidden_fields(ty, variant).count()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => bug!("Unexpected type for constructor `{ctor:?}`: {ty:?}"),
|
_ => bug!("Unexpected type for constructor `{ctor:?}`: {ty:?}"),
|
||||||
@ -507,20 +505,12 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> {
|
|||||||
};
|
};
|
||||||
let variant =
|
let variant =
|
||||||
&adt.variant(RustcMatchCheckCtxt::variant_index_for_adt(&ctor, *adt));
|
&adt.variant(RustcMatchCheckCtxt::variant_index_for_adt(&ctor, *adt));
|
||||||
// For each field in the variant, we store the relevant index into `self.fields` if any.
|
fields = cx
|
||||||
let mut field_id_to_id: Vec<Option<usize>> =
|
.variant_sub_tys(ty, variant)
|
||||||
(0..variant.fields.len()).map(|_| None).collect();
|
.map(|(_, ty)| DeconstructedPat::wildcard(ty))
|
||||||
let tys = cx.list_variant_nonhidden_fields(ty, variant).enumerate().map(
|
.collect();
|
||||||
|(i, (field, ty, _))| {
|
|
||||||
field_id_to_id[field.index()] = Some(i);
|
|
||||||
ty
|
|
||||||
},
|
|
||||||
);
|
|
||||||
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()] {
|
fields[pat.field.index()] = self.lower_pat(&pat.pattern);
|
||||||
fields[i] = self.lower_pat(&pat.pattern);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => bug!("pattern has unexpected type: pat: {:?}, ty: {:?}", pat, ty),
|
_ => bug!("pattern has unexpected type: pat: {:?}, ty: {:?}", pat, ty),
|
||||||
@ -762,11 +752,9 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> {
|
|||||||
ty::Adt(adt_def, args) => {
|
ty::Adt(adt_def, args) => {
|
||||||
let variant_index =
|
let variant_index =
|
||||||
RustcMatchCheckCtxt::variant_index_for_adt(&pat.ctor(), *adt_def);
|
RustcMatchCheckCtxt::variant_index_for_adt(&pat.ctor(), *adt_def);
|
||||||
let variant = &adt_def.variant(variant_index);
|
let subpatterns = subpatterns
|
||||||
let subpatterns = cx
|
.enumerate()
|
||||||
.list_variant_nonhidden_fields(*pat.ty(), variant)
|
.map(|(i, pattern)| FieldPat { field: FieldIdx::new(i), pattern })
|
||||||
.zip(subpatterns)
|
|
||||||
.map(|((field, _ty, _), pattern)| FieldPat { field, pattern })
|
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
if adt_def.is_enum() {
|
if adt_def.is_enum() {
|
||||||
|
Loading…
Reference in New Issue
Block a user