Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 3141f2d

Browse files
committed
Inline all_constructors
1 parent bbb4ac0 commit 3141f2d

File tree

1 file changed

+115
-121
lines changed

1 file changed

+115
-121
lines changed

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

Lines changed: 115 additions & 121 deletions
Original file line numberDiff line numberDiff line change
@@ -791,124 +791,6 @@ impl<'tcx> Constructor<'tcx> {
791791
}
792792
}
793793

794-
/// This determines the set of all possible constructors of a pattern matching
795-
/// values of type `left_ty`. For vectors, this would normally be an infinite set
796-
/// but is instead bounded by the maximum fixed length of slice patterns in
797-
/// the column of patterns being analyzed.
798-
///
799-
/// We make sure to omit constructors that are statically impossible. E.g., for
800-
/// `Option<!>`, we do not include `Some(_)` in the returned list of constructors.
801-
/// Invariant: this returns an empty `Vec` if and only if the type is uninhabited (as determined by
802-
/// `cx.is_uninhabited()`).
803-
fn all_constructors<'p, 'tcx>(pcx: PatCtxt<'_, 'p, 'tcx>) -> SmallVec<[Constructor<'tcx>; 1]> {
804-
debug!("all_constructors({:?})", pcx.ty);
805-
let cx = pcx.cx;
806-
let make_range = |start, end| {
807-
IntRange(
808-
// `unwrap()` is ok because we know the type is an integer.
809-
IntRange::from_range(cx.tcx, start, end, pcx.ty, &RangeEnd::Included).unwrap(),
810-
)
811-
};
812-
match pcx.ty.kind() {
813-
ty::Bool => smallvec![make_range(0, 1)],
814-
ty::Array(sub_ty, len) if len.try_eval_usize(cx.tcx, cx.param_env).is_some() => {
815-
let len = len.eval_usize(cx.tcx, cx.param_env);
816-
if len != 0 && cx.is_uninhabited(sub_ty) {
817-
smallvec![]
818-
} else {
819-
smallvec![Slice(Slice::new(Some(len), VarLen(0, 0)))]
820-
}
821-
}
822-
// Treat arrays of a constant but unknown length like slices.
823-
ty::Array(sub_ty, _) | ty::Slice(sub_ty) => {
824-
let kind = if cx.is_uninhabited(sub_ty) { FixedLen(0) } else { VarLen(0, 0) };
825-
smallvec![Slice(Slice::new(None, kind))]
826-
}
827-
ty::Adt(def, substs) if def.is_enum() => {
828-
// If the enum is declared as `#[non_exhaustive]`, we treat it as if it had an
829-
// additional "unknown" constructor.
830-
// There is no point in enumerating all possible variants, because the user can't
831-
// actually match against them all themselves. So we always return only the fictitious
832-
// constructor.
833-
// E.g., in an example like:
834-
//
835-
// ```
836-
// let err: io::ErrorKind = ...;
837-
// match err {
838-
// io::ErrorKind::NotFound => {},
839-
// }
840-
// ```
841-
//
842-
// we don't want to show every possible IO error, but instead have only `_` as the
843-
// witness.
844-
let is_declared_nonexhaustive = cx.is_foreign_non_exhaustive_enum(pcx.ty);
845-
846-
// If `exhaustive_patterns` is disabled and our scrutinee is an empty enum, we treat it
847-
// as though it had an "unknown" constructor to avoid exposing its emptiness. The
848-
// exception is if the pattern is at the top level, because we want empty matches to be
849-
// considered exhaustive.
850-
let is_secretly_empty = def.variants.is_empty()
851-
&& !cx.tcx.features().exhaustive_patterns
852-
&& !pcx.is_top_level;
853-
854-
if is_secretly_empty || is_declared_nonexhaustive {
855-
smallvec![NonExhaustive]
856-
} else if cx.tcx.features().exhaustive_patterns {
857-
// If `exhaustive_patterns` is enabled, we exclude variants known to be
858-
// uninhabited.
859-
def.variants
860-
.iter()
861-
.filter(|v| {
862-
!v.uninhabited_from(cx.tcx, substs, def.adt_kind(), cx.param_env)
863-
.contains(cx.tcx, cx.module)
864-
})
865-
.map(|v| Variant(v.def_id))
866-
.collect()
867-
} else {
868-
def.variants.iter().map(|v| Variant(v.def_id)).collect()
869-
}
870-
}
871-
ty::Char => {
872-
smallvec![
873-
// The valid Unicode Scalar Value ranges.
874-
make_range('\u{0000}' as u128, '\u{D7FF}' as u128),
875-
make_range('\u{E000}' as u128, '\u{10FFFF}' as u128),
876-
]
877-
}
878-
ty::Int(_) | ty::Uint(_)
879-
if pcx.ty.is_ptr_sized_integral()
880-
&& !cx.tcx.features().precise_pointer_size_matching =>
881-
{
882-
// `usize`/`isize` are not allowed to be matched exhaustively unless the
883-
// `precise_pointer_size_matching` feature is enabled. So we treat those types like
884-
// `#[non_exhaustive]` enums by returning a special unmatcheable constructor.
885-
smallvec![NonExhaustive]
886-
}
887-
&ty::Int(ity) => {
888-
let bits = Integer::from_attr(&cx.tcx, SignedInt(ity)).size().bits() as u128;
889-
let min = 1u128 << (bits - 1);
890-
let max = min - 1;
891-
smallvec![make_range(min, max)]
892-
}
893-
&ty::Uint(uty) => {
894-
let size = Integer::from_attr(&cx.tcx, UnsignedInt(uty)).size();
895-
let max = size.truncate(u128::MAX);
896-
smallvec![make_range(0, max)]
897-
}
898-
// If `exhaustive_patterns` is disabled and our scrutinee is the never type, we cannot
899-
// expose its emptiness. The exception is if the pattern is at the top level, because we
900-
// want empty matches to be considered exhaustive.
901-
ty::Never if !cx.tcx.features().exhaustive_patterns && !pcx.is_top_level => {
902-
smallvec![NonExhaustive]
903-
}
904-
ty::Never => smallvec![],
905-
_ if cx.is_uninhabited(pcx.ty) => smallvec![],
906-
ty::Adt(..) | ty::Tuple(..) | ty::Ref(..) => smallvec![Single],
907-
// This type is one for which we cannot list constructors, like `str` or `f64`.
908-
_ => smallvec![NonExhaustive],
909-
}
910-
}
911-
912794
/// A wildcard constructor that we split relative to the constructors in the matrix, as explained
913795
/// at the top of the file.
914796
/// For splitting wildcards, there are two groups of constructors: there are the constructors
@@ -926,9 +808,121 @@ pub(super) struct SplitWildcard<'tcx> {
926808

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

934928
/// Pass a set of constructors relative to which to split this one. Don't call twice, it won't

0 commit comments

Comments
 (0)