diff options
Diffstat (limited to 'compiler/rustc_pattern_analysis/src/cx.rs')
| -rw-r--r-- | compiler/rustc_pattern_analysis/src/cx.rs | 114 |
1 files changed, 83 insertions, 31 deletions
diff --git a/compiler/rustc_pattern_analysis/src/cx.rs b/compiler/rustc_pattern_analysis/src/cx.rs index a4bc99c8013..de42764c9bc 100644 --- a/compiler/rustc_pattern_analysis/src/cx.rs +++ b/compiler/rustc_pattern_analysis/src/cx.rs @@ -9,7 +9,7 @@ use rustc_index::Idx; use rustc_index::IndexVec; use rustc_middle::middle::stability::EvalResult; use rustc_middle::mir::interpret::Scalar; -use rustc_middle::mir::{self}; +use rustc_middle::mir::{self, Const}; use rustc_middle::thir::{FieldPat, Pat, PatKind, PatRange, PatRangeBoundary}; use rustc_middle::ty::layout::IntegerExt; use rustc_middle::ty::{self, Ty, TyCtxt, VariantDef}; @@ -18,13 +18,26 @@ use rustc_target::abi::{FieldIdx, Integer, VariantIdx, FIRST_VARIANT}; use smallvec::SmallVec; use crate::constructor::{ - Constructor, ConstructorSet, IntRange, MaybeInfiniteInt, OpaqueId, Slice, SliceKind, - VariantVisibility, + IntRange, MaybeInfiniteInt, OpaqueId, Slice, SliceKind, VariantVisibility, }; -use crate::pat::{DeconstructedPat, WitnessPat}; +use crate::MatchCx; -use Constructor::*; +use crate::constructor::Constructor::*; +pub type Constructor<'p, 'tcx> = crate::constructor::Constructor<MatchCheckCtxt<'p, 'tcx>>; +pub type ConstructorSet<'p, 'tcx> = crate::constructor::ConstructorSet<MatchCheckCtxt<'p, 'tcx>>; +pub type DeconstructedPat<'p, 'tcx> = crate::pat::DeconstructedPat<'p, MatchCheckCtxt<'p, 'tcx>>; +pub type MatchArm<'p, 'tcx> = crate::MatchArm<'p, MatchCheckCtxt<'p, 'tcx>>; +pub(crate) type PatCtxt<'a, 'p, 'tcx> = + crate::usefulness::PatCtxt<'a, 'p, MatchCheckCtxt<'p, 'tcx>>; +pub(crate) type SplitConstructorSet<'p, 'tcx> = + crate::constructor::SplitConstructorSet<MatchCheckCtxt<'p, 'tcx>>; +pub type Usefulness = crate::usefulness::Usefulness<Span>; +pub type UsefulnessReport<'p, 'tcx> = + crate::usefulness::UsefulnessReport<'p, MatchCheckCtxt<'p, 'tcx>>; +pub type WitnessPat<'p, 'tcx> = crate::pat::WitnessPat<MatchCheckCtxt<'p, 'tcx>>; + +#[derive(Clone)] pub struct MatchCheckCtxt<'p, 'tcx> { pub tcx: TyCtxt<'tcx>, /// The module in which the match occurs. This is necessary for @@ -49,15 +62,17 @@ pub struct MatchCheckCtxt<'p, 'tcx> { pub known_valid_scrutinee: bool, } +impl<'p, 'tcx> fmt::Debug for MatchCheckCtxt<'p, 'tcx> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("MatchCheckCtxt").finish() + } +} + impl<'p, 'tcx> MatchCheckCtxt<'p, 'tcx> { pub(crate) fn is_uninhabited(&self, ty: Ty<'tcx>) -> bool { !ty.is_inhabited_from(self.tcx, self.module, self.param_env) } - pub(crate) fn is_opaque(ty: Ty<'tcx>) -> bool { - matches!(ty.kind(), ty::Alias(ty::Opaque, ..)) - } - /// Returns whether the given type is an enum from another crate declared `#[non_exhaustive]`. pub fn is_foreign_non_exhaustive_enum(&self, ty: Ty<'tcx>) -> bool { match ty.kind() { @@ -68,6 +83,20 @@ impl<'p, 'tcx> MatchCheckCtxt<'p, 'tcx> { } } + /// Whether the range denotes the fictitious values before `isize::MIN` or after + /// `usize::MAX`/`isize::MAX` (see doc of [`IntRange::split`] for why these exist). + pub fn is_range_beyond_boundaries(&self, range: &IntRange, ty: Ty<'tcx>) -> bool { + ty.is_ptr_sized_integral() && { + // The two invalid ranges are `NegInfinity..isize::MIN` (represented as + // `NegInfinity..0`), and `{u,i}size::MAX+1..PosInfinity`. `hoist_pat_range_bdy` + // converts `MAX+1` to `PosInfinity`, and we couldn't have `PosInfinity` in `range.lo` + // otherwise. + let lo = self.hoist_pat_range_bdy(range.lo, ty); + matches!(lo, PatRangeBoundary::PosInfinity) + || matches!(range.hi, MaybeInfiniteInt::Finite(0)) + } + } + // In the cases of either a `#[non_exhaustive]` field list or a non-public field, we hide // uninhabited fields in order not to reveal the uninhabitedness of the whole variant. // This lists the fields we keep along with their types. @@ -97,7 +126,7 @@ impl<'p, 'tcx> MatchCheckCtxt<'p, 'tcx> { } pub(crate) fn variant_index_for_adt( - ctor: &Constructor<'tcx>, + ctor: &Constructor<'p, 'tcx>, adt: ty::AdtDef<'tcx>, ) -> VariantIdx { match *ctor { @@ -113,7 +142,7 @@ impl<'p, 'tcx> MatchCheckCtxt<'p, 'tcx> { /// Returns the types of the fields for a given constructor. The result must have a length of /// `ctor.arity()`. #[instrument(level = "trace", skip(self))] - pub(crate) fn ctor_sub_tys(&self, ctor: &Constructor<'tcx>, ty: Ty<'tcx>) -> &[Ty<'tcx>] { + pub(crate) fn ctor_sub_tys(&self, ctor: &Constructor<'p, 'tcx>, ty: Ty<'tcx>) -> &[Ty<'tcx>] { let cx = self; match ctor { Struct | Variant(_) | UnionField => match ty.kind() { @@ -159,9 +188,8 @@ impl<'p, 'tcx> MatchCheckCtxt<'p, 'tcx> { } } - /// The number of fields for this constructor. This must be kept in sync with - /// `Fields::wildcards`. - pub(crate) fn ctor_arity(&self, ctor: &Constructor<'tcx>, ty: Ty<'tcx>) -> usize { + /// The number of fields for this constructor. + pub(crate) fn ctor_arity(&self, ctor: &Constructor<'p, 'tcx>, ty: Ty<'tcx>) -> usize { match ctor { Struct | Variant(_) | UnionField => match ty.kind() { ty::Tuple(fs) => fs.len(), @@ -198,7 +226,7 @@ impl<'p, 'tcx> MatchCheckCtxt<'p, 'tcx> { /// /// See [`crate::constructor`] for considerations of emptiness. #[instrument(level = "debug", skip(self), ret)] - pub fn ctors_for_ty(&self, ty: Ty<'tcx>) -> ConstructorSet { + pub fn ctors_for_ty(&self, ty: Ty<'tcx>) -> ConstructorSet<'p, 'tcx> { let cx = self; let make_uint_range = |start, end| { IntRange::from_range( @@ -599,20 +627,6 @@ impl<'p, 'tcx> MatchCheckCtxt<'p, 'tcx> { } } - /// Whether the range denotes the fictitious values before `isize::MIN` or after - /// `usize::MAX`/`isize::MAX` (see doc of [`IntRange::split`] for why these exist). - pub fn is_range_beyond_boundaries(&self, range: &IntRange, ty: Ty<'tcx>) -> bool { - ty.is_ptr_sized_integral() && { - // The two invalid ranges are `NegInfinity..isize::MIN` (represented as - // `NegInfinity..0`), and `{u,i}size::MAX+1..PosInfinity`. `hoist_pat_range_bdy` - // converts `MAX+1` to `PosInfinity`, and we couldn't have `PosInfinity` in `range.lo` - // otherwise. - let lo = self.hoist_pat_range_bdy(range.lo, ty); - matches!(lo, PatRangeBoundary::PosInfinity) - || matches!(range.hi, MaybeInfiniteInt::Finite(0)) - } - } - /// Convert back to a `thir::Pat` for diagnostic purposes. pub(crate) fn hoist_pat_range(&self, range: &IntRange, ty: Ty<'tcx>) -> Pat<'tcx> { use MaybeInfiniteInt::*; @@ -652,7 +666,7 @@ impl<'p, 'tcx> MatchCheckCtxt<'p, 'tcx> { } /// Convert back to a `thir::Pat` for diagnostic purposes. This panics for patterns that don't /// appear in diagnostics, like float ranges. - pub fn hoist_witness_pat(&self, pat: &WitnessPat<'tcx>) -> Pat<'tcx> { + pub fn hoist_witness_pat(&self, pat: &WitnessPat<'p, 'tcx>) -> Pat<'tcx> { let cx = self; let is_wildcard = |pat: &Pat<'_>| matches!(pat.kind, PatKind::Wild); let mut subpatterns = pat.iter_fields().map(|p| Box::new(cx.hoist_witness_pat(p))); @@ -746,7 +760,7 @@ impl<'p, 'tcx> MatchCheckCtxt<'p, 'tcx> { /// Best-effort `Debug` implementation. pub(crate) fn debug_pat( f: &mut fmt::Formatter<'_>, - pat: &DeconstructedPat<'p, 'tcx>, + pat: &crate::pat::DeconstructedPat<'_, Self>, ) -> fmt::Result { let mut first = true; let mut start_or_continue = |s| { @@ -840,6 +854,44 @@ impl<'p, 'tcx> MatchCheckCtxt<'p, 'tcx> { } } +impl<'p, 'tcx> MatchCx for MatchCheckCtxt<'p, 'tcx> { + type Ty = Ty<'tcx>; + type Span = Span; + type VariantIdx = VariantIdx; + type StrLit = Const<'tcx>; + + fn is_exhaustive_patterns_feature_on(&self) -> bool { + self.tcx.features().exhaustive_patterns + } + fn is_opaque_ty(ty: Self::Ty) -> bool { + matches!(ty.kind(), ty::Alias(ty::Opaque, ..)) + } + + fn ctor_arity(&self, ctor: &crate::constructor::Constructor<Self>, ty: Self::Ty) -> usize { + self.ctor_arity(ctor, ty) + } + fn ctor_sub_tys( + &self, + ctor: &crate::constructor::Constructor<Self>, + ty: Self::Ty, + ) -> &[Self::Ty] { + self.ctor_sub_tys(ctor, ty) + } + fn ctors_for_ty(&self, ty: Self::Ty) -> crate::constructor::ConstructorSet<Self> { + self.ctors_for_ty(ty) + } + + fn debug_pat( + f: &mut fmt::Formatter<'_>, + pat: &crate::pat::DeconstructedPat<'_, Self>, + ) -> fmt::Result { + Self::debug_pat(f, pat) + } + fn bug(&self, fmt: fmt::Arguments<'_>) -> ! { + span_bug!(self.scrut_span, "{}", fmt) + } +} + /// Recursively expand this pattern into its subpatterns. Only useful for or-patterns. fn expand_or_pat<'p, 'tcx>(pat: &'p Pat<'tcx>) -> Vec<&'p Pat<'tcx>> { fn expand<'p, 'tcx>(pat: &'p Pat<'tcx>, vec: &mut Vec<&'p Pat<'tcx>>) { |
