4040//! - That have no non-trivial intersection with any of the constructors in the column (i.e. they're
4141//! each either disjoint with or covered by any given column constructor).
4242//!
43- //! We compute this in two steps: first [`crate::cx::MatchCheckCtxt ::ctors_for_ty`] determines the
43+ //! We compute this in two steps: first [`MatchCx ::ctors_for_ty`] determines the
4444//! set of all possible constructors for the type. Then [`ConstructorSet::split`] looks at the
4545//! column of constructors and splits the set into groups accordingly. The precise invariants of
4646//! [`ConstructorSet::split`] is described in [`SplitConstructorSet`].
136136//! the algorithm can't distinguish them from a nonempty constructor. The only known case where this
137137//! could happen is the `[..]` pattern on `[!; N]` with `N > 0` so we must take care to not emit it.
138138//!
139- //! This is all handled by [`crate::cx::MatchCheckCtxt ::ctors_for_ty`] and
139+ //! This is all handled by [`MatchCx ::ctors_for_ty`] and
140140//! [`ConstructorSet::split`]. The invariants of [`SplitConstructorSet`] are also of interest.
141141//!
142142//!
@@ -158,14 +158,13 @@ use rustc_apfloat::ieee::{DoubleS, IeeeFloat, SingleS};
158158use rustc_data_structures:: fx:: FxHashSet ;
159159use rustc_hir:: RangeEnd ;
160160use rustc_index:: IndexVec ;
161- use rustc_middle:: mir:: Const ;
162- use rustc_target:: abi:: VariantIdx ;
163161
164162use self :: Constructor :: * ;
165163use self :: MaybeInfiniteInt :: * ;
166164use self :: SliceKind :: * ;
167165
168166use crate :: usefulness:: PatCtxt ;
167+ use crate :: MatchCx ;
169168
170169/// Whether we have seen a constructor in the column or not.
171170#[ derive( Debug , Clone , Copy , PartialEq , Eq , PartialOrd , Ord ) ]
@@ -630,11 +629,11 @@ impl OpaqueId {
630629/// constructor. `Constructor::apply` reconstructs the pattern from a pair of `Constructor` and
631630/// `Fields`.
632631#[ derive( Clone , Debug , PartialEq ) ]
633- pub enum Constructor < ' tcx > {
632+ pub enum Constructor < Cx : MatchCx > {
634633 /// Tuples and structs.
635634 Struct ,
636635 /// Enum variants.
637- Variant ( VariantIdx ) ,
636+ Variant ( Cx :: VariantIdx ) ,
638637 /// References
639638 Ref ,
640639 /// Array and slice patterns.
@@ -649,7 +648,7 @@ pub enum Constructor<'tcx> {
649648 F32Range ( IeeeFloat < SingleS > , IeeeFloat < SingleS > , RangeEnd ) ,
650649 F64Range ( IeeeFloat < DoubleS > , IeeeFloat < DoubleS > , RangeEnd ) ,
651650 /// String literals. Strings are not quite the same as `&[u8]` so we treat them separately.
652- Str ( Const < ' tcx > ) ,
651+ Str ( Cx :: StrLit ) ,
653652 /// Constants that must not be matched structurally. They are treated as black boxes for the
654653 /// purposes of exhaustiveness: we must not inspect them, and they don't count towards making a
655654 /// match exhaustive.
@@ -672,12 +671,12 @@ pub enum Constructor<'tcx> {
672671 Missing ,
673672}
674673
675- impl < ' tcx > Constructor < ' tcx > {
674+ impl < Cx : MatchCx > Constructor < Cx > {
676675 pub ( crate ) fn is_non_exhaustive ( & self ) -> bool {
677676 matches ! ( self , NonExhaustive )
678677 }
679678
680- pub ( crate ) fn as_variant ( & self ) -> Option < VariantIdx > {
679+ pub ( crate ) fn as_variant ( & self ) -> Option < Cx :: VariantIdx > {
681680 match self {
682681 Variant ( i) => Some ( * i) ,
683682 _ => None ,
@@ -704,7 +703,7 @@ impl<'tcx> Constructor<'tcx> {
704703
705704 /// The number of fields for this constructor. This must be kept in sync with
706705 /// `Fields::wildcards`.
707- pub ( crate ) fn arity ( & self , pcx : & PatCtxt < ' _ , ' _ , ' tcx > ) -> usize {
706+ pub ( crate ) fn arity ( & self , pcx : & PatCtxt < ' _ , ' _ , Cx > ) -> usize {
708707 pcx. cx . ctor_arity ( self , pcx. ty )
709708 }
710709
@@ -713,14 +712,11 @@ impl<'tcx> Constructor<'tcx> {
713712 /// this checks for inclusion.
714713 // We inline because this has a single call site in `Matrix::specialize_constructor`.
715714 #[ inline]
716- pub ( crate ) fn is_covered_by < ' p > ( & self , pcx : & PatCtxt < ' _ , ' p , ' tcx > , other : & Self ) -> bool {
715+ pub ( crate ) fn is_covered_by < ' p > ( & self , pcx : & PatCtxt < ' _ , ' p , Cx > , other : & Self ) -> bool {
717716 match ( self , other) {
718- ( Wildcard , _) => {
719- span_bug ! (
720- pcx. cx. scrut_span,
721- "Constructor splitting should not have returned `Wildcard`"
722- )
723- }
717+ ( Wildcard , _) => pcx
718+ . cx
719+ . bug ( format_args ! ( "Constructor splitting should not have returned `Wildcard`" ) ) ,
724720 // Wildcards cover anything
725721 ( _, Wildcard ) => true ,
726722 // Only a wildcard pattern can match these special constructors.
@@ -761,12 +757,9 @@ impl<'tcx> Constructor<'tcx> {
761757 ( Opaque ( self_id) , Opaque ( other_id) ) => self_id == other_id,
762758 ( Opaque ( ..) , _) | ( _, Opaque ( ..) ) => false ,
763759
764- _ => span_bug ! (
765- pcx. cx. scrut_span,
766- "trying to compare incompatible constructors {:?} and {:?}" ,
767- self ,
768- other
769- ) ,
760+ _ => pcx. cx . bug ( format_args ! (
761+ "trying to compare incompatible constructors {self:?} and {other:?}"
762+ ) ) ,
770763 }
771764 }
772765}
@@ -790,12 +783,12 @@ pub enum VariantVisibility {
790783/// In terms of division of responsibility, [`ConstructorSet::split`] handles all of the
791784/// `exhaustive_patterns` feature.
792785#[ derive( Debug ) ]
793- pub enum ConstructorSet {
786+ pub enum ConstructorSet < Cx : MatchCx > {
794787 /// The type is a tuple or struct. `empty` tracks whether the type is empty.
795788 Struct { empty : bool } ,
796789 /// This type has the following list of constructors. If `variants` is empty and
797790 /// `non_exhaustive` is false, don't use this; use `NoConstructors` instead.
798- Variants { variants : IndexVec < VariantIdx , VariantVisibility > , non_exhaustive : bool } ,
791+ Variants { variants : IndexVec < Cx :: VariantIdx , VariantVisibility > , non_exhaustive : bool } ,
799792 /// The type is `&T`.
800793 Ref ,
801794 /// The type is a union.
@@ -838,25 +831,25 @@ pub enum ConstructorSet {
838831/// of the `ConstructorSet` for the type, yet if we forgot to include them in `present` we would be
839832/// ignoring any row with `Opaque`s in the algorithm. Hence the importance of point 4.
840833#[ derive( Debug ) ]
841- pub ( crate ) struct SplitConstructorSet < ' tcx > {
842- pub ( crate ) present : SmallVec < [ Constructor < ' tcx > ; 1 ] > ,
843- pub ( crate ) missing : Vec < Constructor < ' tcx > > ,
844- pub ( crate ) missing_empty : Vec < Constructor < ' tcx > > ,
834+ pub ( crate ) struct SplitConstructorSet < Cx : MatchCx > {
835+ pub ( crate ) present : SmallVec < [ Constructor < Cx > ; 1 ] > ,
836+ pub ( crate ) missing : Vec < Constructor < Cx > > ,
837+ pub ( crate ) missing_empty : Vec < Constructor < Cx > > ,
845838}
846839
847- impl ConstructorSet {
840+ impl < Cx : MatchCx > ConstructorSet < Cx > {
848841 /// This analyzes a column of constructors to 1/ determine which constructors of the type (if
849842 /// any) are missing; 2/ split constructors to handle non-trivial intersections e.g. on ranges
850843 /// or slices. This can get subtle; see [`SplitConstructorSet`] for details of this operation
851844 /// and its invariants.
852845 #[ instrument( level = "debug" , skip( self , pcx, ctors) , ret) ]
853- pub ( crate ) fn split < ' a , ' tcx > (
846+ pub ( crate ) fn split < ' a > (
854847 & self ,
855- pcx : & PatCtxt < ' _ , ' _ , ' tcx > ,
856- ctors : impl Iterator < Item = & ' a Constructor < ' tcx > > + Clone ,
857- ) -> SplitConstructorSet < ' tcx >
848+ pcx : & PatCtxt < ' _ , ' _ , Cx > ,
849+ ctors : impl Iterator < Item = & ' a Constructor < Cx > > + Clone ,
850+ ) -> SplitConstructorSet < Cx >
858851 where
859- ' tcx : ' a ,
852+ Cx : ' a ,
860853 {
861854 let mut present: SmallVec < [ _ ; 1 ] > = SmallVec :: new ( ) ;
862855 // Empty constructors found missing.
@@ -997,7 +990,7 @@ impl ConstructorSet {
997990 // We have now grouped all the constructors into 3 buckets: present, missing, missing_empty.
998991 // In the absence of the `exhaustive_patterns` feature however, we don't count nested empty
999992 // types as empty. Only non-nested `!` or `enum Foo {}` are considered empty.
1000- if !pcx. cx . tcx . features ( ) . exhaustive_patterns
993+ if !pcx. cx . is_exhaustive_patterns_feature_on ( )
1001994 && !( pcx. is_top_level && matches ! ( self , Self :: NoConstructors ) )
1002995 {
1003996 // Treat all missing constructors as nonempty.
0 commit comments