Skip to content

Commit c4f840d

Browse files
committed
Move tcx-dependent code out of deconstruct_pat
1 parent 474e763 commit c4f840d

File tree

3 files changed

+207
-196
lines changed

3 files changed

+207
-196
lines changed

compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs

+4-169
Original file line numberDiff line numberDiff line change
@@ -45,18 +45,15 @@
4545
use self::Constructor::*;
4646
use self::SliceKind::*;
4747

48-
use super::number_type_size;
4948
use super::usefulness::{MatchCheckCtxt, PatCtxt};
5049

5150
use rustc_apfloat::ieee::{DoubleS, IeeeFloat, SingleS};
5251
use rustc_data_structures::captures::Captures;
5352
use rustc_index::vec::Idx;
5453

5554
use rustc_hir::{HirId, RangeEnd};
56-
use rustc_middle::middle::stability::EvalResult;
57-
use rustc_middle::mir::Field;
5855
use rustc_middle::ty::subst::GenericArg;
59-
use rustc_middle::ty::{self, Ty, VariantDef};
56+
use rustc_middle::ty::{self, Ty};
6057
use rustc_span::{Span, DUMMY_SP};
6158
use rustc_target::abi::VariantIdx;
6259

@@ -619,7 +616,7 @@ impl<'tcx> Constructor<'tcx> {
619616
Single | Variant(_) => match pcx.ty.kind() {
620617
ty::Adt(adt, ..) => {
621618
let variant = &adt.variants[self.variant_index_for_adt(adt)];
622-
Fields::list_variant_nonhidden_fields(pcx.cx, pcx.ty, variant).count()
619+
pcx.cx.list_variant_nonhidden_fields(pcx.ty, variant).count()
623620
}
624621
_ => bug!("Unexpected type for `Single` constructor: {:?}", pcx.ty),
625622
},
@@ -806,138 +803,7 @@ pub(super) struct SplitWildcard<'tcx> {
806803

807804
impl<'tcx> SplitWildcard<'tcx> {
808805
pub(super) fn new<'p>(pcx: PatCtxt<'_, 'p, 'tcx>) -> Self {
809-
debug!("SplitWildcard::new({:?})", pcx.ty);
810-
let cx = pcx.cx;
811-
let ty = pcx.ty;
812-
let make_range = |size, start, end| {
813-
IntRange(IntRange::from_bits(ty, size, start, end, &RangeEnd::Included))
814-
};
815-
// This determines the set of all possible constructors for the type `ty`. For numbers,
816-
// arrays and slices we use ranges and variable-length slices when appropriate.
817-
//
818-
// If the `exhaustive_patterns` feature is enabled, we make sure to omit constructors that
819-
// are statically impossible. E.g., for `Option<!>`, we do not include `Some(_)` in the
820-
// returned list of constructors.
821-
// Invariant: this is empty if and only if the type is uninhabited (as determined by
822-
// `cx.is_uninhabited()`).
823-
let all_ctors = match ty.kind() {
824-
_ if cx.is_uninhabited(ty) => smallvec![],
825-
ty::Bool => smallvec![Bool(false), Bool(true)],
826-
ty::Char => {
827-
let size = number_type_size(cx.tcx, ty);
828-
smallvec![
829-
// The valid Unicode Scalar Value ranges.
830-
make_range(size, '\u{0000}' as u128, '\u{D7FF}' as u128),
831-
make_range(size, '\u{E000}' as u128, '\u{10FFFF}' as u128),
832-
]
833-
}
834-
ty::Int(_) | ty::Uint(_)
835-
if ty.is_ptr_sized_integral()
836-
&& !cx.tcx.features().precise_pointer_size_matching =>
837-
{
838-
// `usize`/`isize` are not allowed to be matched exhaustively unless the
839-
// `precise_pointer_size_matching` feature is enabled. So we treat those types like
840-
// `#[non_exhaustive]` enums by returning a special unmatcheable constructor.
841-
smallvec![NonExhaustive]
842-
}
843-
&ty::Int(_) => {
844-
let size = number_type_size(cx.tcx, ty);
845-
let bits = size.bits() as u128;
846-
let min = 1u128 << (bits - 1);
847-
let max = min - 1;
848-
smallvec![make_range(size, min, max)]
849-
}
850-
&ty::Uint(_) => {
851-
let size = number_type_size(cx.tcx, ty);
852-
let max = size.truncate(u128::MAX);
853-
smallvec![make_range(size, 0, max)]
854-
}
855-
ty::Adt(def, substs) if def.is_enum() => {
856-
// If the enum is declared as `#[non_exhaustive]`, we treat it as if it had an
857-
// additional "unknown" constructor.
858-
// There is no point in enumerating all possible variants, because the user can't
859-
// actually match against them all themselves. So we always return only the fictitious
860-
// constructor.
861-
// E.g., in an example like:
862-
//
863-
// ```
864-
// let err: io::ErrorKind = ...;
865-
// match err {
866-
// io::ErrorKind::NotFound => {},
867-
// }
868-
// ```
869-
//
870-
// we don't want to show every possible IO error, but instead have only `_` as the
871-
// witness.
872-
let is_declared_nonexhaustive = cx.is_foreign_non_exhaustive_enum(ty);
873-
874-
let is_exhaustive_pat_feature = cx.tcx.features().exhaustive_patterns;
875-
876-
// If `exhaustive_patterns` is disabled and our scrutinee is an empty enum, we treat it
877-
// as though it had an "unknown" constructor to avoid exposing its emptiness. The
878-
// exception is if the pattern is at the top level, because we want empty matches to be
879-
// considered exhaustive.
880-
let is_secretly_empty =
881-
def.variants.is_empty() && !is_exhaustive_pat_feature && !pcx.is_top_level;
882-
883-
let mut ctors: SmallVec<[_; 1]> = def
884-
.variants
885-
.iter_enumerated()
886-
.filter(|(_, v)| {
887-
// Filter variants that depend on a disabled unstalbe feature.
888-
let is_enabled = !matches!(
889-
cx.tcx.eval_stability(v.def_id, None, DUMMY_SP, None),
890-
EvalResult::Deny { .. }
891-
);
892-
// If `exhaustive_patterns` is enabled, we exclude variants known to be
893-
// uninhabited.
894-
let is_uninhabited = is_exhaustive_pat_feature
895-
&& v.uninhabited_from(cx.tcx, substs, def.adt_kind(), cx.param_env)
896-
.contains(cx.tcx, cx.module);
897-
is_enabled && !is_uninhabited
898-
})
899-
.map(|(idx, _)| Variant(idx))
900-
.collect();
901-
902-
if is_secretly_empty || is_declared_nonexhaustive {
903-
ctors.push(NonExhaustive);
904-
}
905-
ctors
906-
}
907-
// The only legal non-wildcard patterns of type `Box` are box patterns, so we emit
908-
// that.
909-
ty::Adt(def, substs) if def.is_box() => smallvec![BoxPat(substs.type_at(0))],
910-
ty::Adt(..) => smallvec![Single],
911-
ty::Ref(_, ty, _) => smallvec![Ref(*ty)],
912-
ty::Tuple(fs) => smallvec![Tuple(*fs)],
913-
ty::Array(sub_ty, len) => {
914-
match len.try_eval_usize(cx.tcx, cx.param_env) {
915-
Some(len) => {
916-
// The uninhabited case is already handled.
917-
smallvec![Slice(Slice::new(Some(len as usize), VarLen(0, 0)))]
918-
}
919-
None => {
920-
// Treat arrays of a constant but unknown length like slices.
921-
let kind =
922-
if cx.is_uninhabited(sub_ty) { FixedLen(0) } else { VarLen(0, 0) };
923-
smallvec![Slice(Slice::new(None, kind))]
924-
}
925-
}
926-
}
927-
ty::Slice(sub_ty) => {
928-
let kind = if cx.is_uninhabited(sub_ty) { FixedLen(0) } else { VarLen(0, 0) };
929-
smallvec![Slice(Slice::new(None, kind))]
930-
}
931-
// If `exhaustive_patterns` is disabled and our scrutinee is the never type, we don't
932-
// expose its emptiness and return `NonExhaustive` below. The exception is if the
933-
// pattern is at the top level, because we want empty matches to be considered
934-
// exhaustive.
935-
ty::Never if pcx.is_top_level => smallvec![],
936-
// This type is one for which we cannot list constructors, like `str` or `f64`, or is
937-
// uninhabited but `exhaustive_patterns` is disabled.
938-
_ => smallvec![NonExhaustive],
939-
};
940-
806+
let all_ctors = pcx.cx.list_constructors_for_type(pcx.ty, pcx.is_top_level);
941807
SplitWildcard { matrix_ctors: Vec::new(), all_ctors }
942808
}
943809

@@ -1079,36 +945,6 @@ impl<'p, 'tcx> Fields<'p, 'tcx> {
1079945
Fields::from_iter(cx, tys.into_iter().map(DeconstructedPat::wildcard))
1080946
}
1081947

1082-
// In the cases of either a `#[non_exhaustive]` field list or a non-public field, we hide
1083-
// uninhabited fields in order not to reveal the uninhabitedness of the whole variant.
1084-
// This lists the fields we keep along with their types.
1085-
pub(super) fn list_variant_nonhidden_fields<'a>(
1086-
cx: &'a MatchCheckCtxt<'p, 'tcx>,
1087-
ty: Ty<'tcx>,
1088-
variant: &'a VariantDef,
1089-
) -> impl Iterator<Item = (Field, Ty<'tcx>)> + Captures<'a> + Captures<'p> {
1090-
let (adt, substs) = match ty.kind() {
1091-
ty::Adt(adt, substs) => (adt, substs),
1092-
_ => bug!(),
1093-
};
1094-
// Whether we must not match the fields of this variant exhaustively.
1095-
let is_non_exhaustive = variant.is_field_list_non_exhaustive() && !adt.did.is_local();
1096-
1097-
variant.fields.iter().enumerate().filter_map(move |(i, field)| {
1098-
let ty = field.ty(cx.tcx, substs);
1099-
// `field.ty()` doesn't normalize after substituting.
1100-
let ty = cx.tcx.normalize_erasing_regions(cx.param_env, ty);
1101-
let is_visible = adt.is_enum() || field.vis.is_accessible_from(cx.module, cx.tcx);
1102-
let is_uninhabited = cx.is_uninhabited(ty);
1103-
1104-
if is_uninhabited && (!is_visible || is_non_exhaustive) {
1105-
None
1106-
} else {
1107-
Some((Field::new(i), ty))
1108-
}
1109-
})
1110-
}
1111-
1112948
/// Creates a new list of wildcard fields for a given constructor. The result must have a
1113949
/// length of `constructor.arity()`.
1114950
pub(super) fn wildcards(
@@ -1120,8 +956,7 @@ impl<'p, 'tcx> Fields<'p, 'tcx> {
1120956
Single | Variant(_) => match ty.kind() {
1121957
ty::Adt(adt, _) => {
1122958
let variant = &adt.variants[constructor.variant_index_for_adt(adt)];
1123-
let tys =
1124-
Fields::list_variant_nonhidden_fields(cx, ty, variant).map(|(_, ty)| ty);
959+
let tys = cx.list_variant_nonhidden_fields(ty, variant).map(|(_, ty)| ty);
1125960
Fields::wildcards_from_tys(cx, tys)
1126961
}
1127962
_ => bug!("Unexpected type for `Single` constructor: {:?}", ty),

0 commit comments

Comments
 (0)