@@ -680,24 +680,32 @@ impl SpanSet {
680680
681681#[ derive( Clone , Debug ) ]
682682enum Usefulness < ' tcx > {
683- /// Pontentially carries a set of sub-branches that have been found to be unreachable. Used
683+ /// Potentially carries a set of sub-branches that have been found to be unreachable. Used
684684 /// only in the presence of or-patterns, otherwise it stays empty.
685- Useful ( SpanSet ) ,
686- /// Carries a list of witnesses of non-exhaustiveness.
687- UsefulWithWitness ( Vec < Witness < ' tcx > > ) ,
688- NotUseful ,
685+ NoWitnesses ( SpanSet ) ,
686+ /// When not carrying witnesses, indicates that the whole pattern is unreachable.
687+ NoWitnessesFull ,
688+ /// Carries a list of witnesses of non-exhaustiveness. Non-empty.
689+ WithWitnesses ( Vec < Witness < ' tcx > > ) ,
690+ /// When carrying witnesses, indicates that the whole pattern is unreachable.
691+ WithWitnessesEmpty ,
689692}
690693
691694impl < ' tcx > Usefulness < ' tcx > {
692695 fn new_useful ( preference : WitnessPreference ) -> Self {
693696 match preference {
694- ConstructWitness => UsefulWithWitness ( vec ! [ Witness ( vec![ ] ) ] ) ,
695- LeaveOutWitness => Useful ( Default :: default ( ) ) ,
697+ ConstructWitness => WithWitnesses ( vec ! [ Witness ( vec![ ] ) ] ) ,
698+ LeaveOutWitness => NoWitnesses ( Default :: default ( ) ) ,
699+ }
700+ }
701+ fn new_not_useful ( preference : WitnessPreference ) -> Self {
702+ match preference {
703+ ConstructWitness => WithWitnessesEmpty ,
704+ LeaveOutWitness => NoWitnessesFull ,
696705 }
697706 }
698707
699- /// Combine usefulnesses from two branches. This is an associative operation and `NotUseful` is
700- /// a unit.
708+ /// Combine usefulnesses from two branches. This is an associative operation.
701709 fn extend ( & mut self , other : Self ) {
702710 // If we have detected some unreachable sub-branches, we only want to keep them when they
703711 // were unreachable in _all_ branches. Eg. in the following, the last `true` is unreachable
@@ -720,21 +728,29 @@ impl<'tcx> Usefulness<'tcx> {
720728 // }
721729 // ```
722730 match ( & mut * self , other) {
723- ( Useful ( s) , Useful ( o) ) => s. intersection_mut ( & o) ,
724- ( UsefulWithWitness ( s) , UsefulWithWitness ( o) ) => s. extend ( o) ,
725- ( _, NotUseful ) => { }
726- ( NotUseful , other) => * self = other,
727- ( UsefulWithWitness ( _) , Useful ( _) ) | ( Useful ( _) , UsefulWithWitness ( _) ) => unreachable ! ( ) ,
731+ ( WithWitnesses ( s) , WithWitnesses ( o) ) => s. extend ( o) ,
732+ ( WithWitnessesEmpty , WithWitnesses ( o) ) => * self = WithWitnesses ( o) ,
733+ ( WithWitnesses ( _) , WithWitnessesEmpty ) => { }
734+ ( WithWitnessesEmpty , WithWitnessesEmpty ) => { }
735+
736+ ( NoWitnesses ( s) , NoWitnesses ( o) ) => s. intersection_mut ( & o) ,
737+ ( NoWitnessesFull , NoWitnesses ( o) ) => * self = NoWitnesses ( o) ,
738+ ( NoWitnesses ( _) , NoWitnessesFull ) => { }
739+ ( NoWitnessesFull , NoWitnessesFull ) => { }
740+
741+ _ => {
742+ unreachable ! ( )
743+ }
728744 }
729745 }
730746
731747 /// When trying several branches and each returns a `Usefulness`, we need to combine the
732748 /// results together.
733- fn merge ( usefulnesses : impl Iterator < Item = Self > ) -> Self {
734- let mut ret = NotUseful ;
749+ fn merge ( pref : WitnessPreference , usefulnesses : impl Iterator < Item = Self > ) -> Self {
750+ let mut ret = Self :: new_not_useful ( pref ) ;
735751 for u in usefulnesses {
736752 ret. extend ( u) ;
737- if let Useful ( spans) = & ret {
753+ if let NoWitnesses ( spans) = & ret {
738754 if spans. is_empty ( ) {
739755 // Once we reach the empty set, more intersections won't change the result.
740756 return ret;
@@ -748,7 +764,7 @@ impl<'tcx> Usefulness<'tcx> {
748764 /// usefulness mergeable with those from the other branches.
749765 fn unsplit_or_pat ( self , this_span : Span , or_pat_spans : & [ Span ] ) -> Self {
750766 match self {
751- Useful ( mut spans) => {
767+ NoWitnesses ( mut spans) => {
752768 // We register the spans of the other branches of this or-pattern as being
753769 // unreachable from this one. This ensures that intersecting together the sets of
754770 // spans returns what we want.
@@ -759,9 +775,10 @@ impl<'tcx> Usefulness<'tcx> {
759775 spans. push_nonintersecting ( span) ;
760776 }
761777 }
762- Useful ( spans)
778+ NoWitnesses ( spans)
763779 }
764- x => x,
780+ NoWitnessesFull => NoWitnessesFull ,
781+ WithWitnesses ( _) | WithWitnessesEmpty => bug ! ( ) ,
765782 }
766783 }
767784
@@ -776,7 +793,7 @@ impl<'tcx> Usefulness<'tcx> {
776793 ctor_wild_subpatterns : & Fields < ' p , ' tcx > ,
777794 ) -> Self {
778795 match self {
779- UsefulWithWitness ( witnesses) => {
796+ WithWitnesses ( witnesses) => {
780797 let new_witnesses = if matches ! ( ctor, Constructor :: Missing ) {
781798 let mut split_wildcard = SplitWildcard :: new ( pcx) ;
782799 split_wildcard. split ( pcx, matrix. head_ctors ( pcx. cx ) ) ;
@@ -806,7 +823,7 @@ impl<'tcx> Usefulness<'tcx> {
806823 . map ( |witness| witness. apply_constructor ( pcx, & ctor, ctor_wild_subpatterns) )
807824 . collect ( )
808825 } ;
809- UsefulWithWitness ( new_witnesses)
826+ WithWitnesses ( new_witnesses)
810827 }
811828 x => x,
812829 }
@@ -935,8 +952,11 @@ fn is_useful<'p, 'tcx>(
935952 // first and then, if v is non-empty, the return value is based on whether
936953 // the type of the tuple we're checking is inhabited or not.
937954 if v. is_empty ( ) {
938- let ret =
939- if rows. is_empty ( ) { Usefulness :: new_useful ( witness_preference) } else { NotUseful } ;
955+ let ret = if rows. is_empty ( ) {
956+ Usefulness :: new_useful ( witness_preference)
957+ } else {
958+ Usefulness :: new_not_useful ( witness_preference)
959+ } ;
940960 debug ! ( ?ret) ;
941961 return ret;
942962 }
@@ -966,7 +986,7 @@ fn is_useful<'p, 'tcx>(
966986 }
967987 usefulness. unsplit_or_pat ( v_span, & subspans)
968988 } ) ;
969- Usefulness :: merge ( usefulnesses)
989+ Usefulness :: merge ( witness_preference , usefulnesses)
970990 } else {
971991 let v_ctor = v. head_ctor ( cx) ;
972992 if let Constructor :: IntRange ( ctor_range) = & v_ctor {
@@ -994,7 +1014,7 @@ fn is_useful<'p, 'tcx>(
9941014 is_useful ( cx, & spec_matrix, & v, witness_preference, hir_id, is_under_guard, false ) ;
9951015 usefulness. apply_constructor ( pcx, start_matrix, & ctor, & ctor_wild_subpatterns)
9961016 } ) ;
997- Usefulness :: merge ( usefulnesses)
1017+ Usefulness :: merge ( witness_preference , usefulnesses)
9981018 } ;
9991019 debug ! ( ?ret) ;
10001020 ret
@@ -1049,9 +1069,9 @@ crate fn compute_match_usefulness<'p, 'tcx>(
10491069 matrix. push ( v) ;
10501070 }
10511071 let reachability = match usefulness {
1052- Useful ( spans) => Reachability :: Reachable ( spans) ,
1053- NotUseful => Reachability :: Unreachable ,
1054- UsefulWithWitness ( ..) => bug ! ( ) ,
1072+ NoWitnesses ( spans) => Reachability :: Reachable ( spans) ,
1073+ NoWitnessesFull => Reachability :: Unreachable ,
1074+ WithWitnesses ( ..) | WithWitnessesEmpty => bug ! ( ) ,
10551075 } ;
10561076 ( arm, reachability)
10571077 } )
@@ -1061,15 +1081,15 @@ crate fn compute_match_usefulness<'p, 'tcx>(
10611081 let v = PatStack :: from_pattern ( wild_pattern) ;
10621082 let usefulness = is_useful ( cx, & matrix, & v, ConstructWitness , scrut_hir_id, false , true ) ;
10631083 let non_exhaustiveness_witnesses = match usefulness {
1064- NotUseful => vec ! [ ] , // Wildcard pattern isn't useful, so the match is exhaustive.
1065- UsefulWithWitness ( pats) => {
1084+ WithWitnessesEmpty => vec ! [ ] , // Wildcard pattern isn't useful, so the match is exhaustive.
1085+ WithWitnesses ( pats) => {
10661086 if pats. is_empty ( ) {
10671087 bug ! ( "Exhaustiveness check returned no witnesses" )
10681088 } else {
10691089 pats. into_iter ( ) . map ( |w| w. single_pattern ( ) ) . collect ( )
10701090 }
10711091 }
1072- Useful ( _) => bug ! ( ) ,
1092+ NoWitnesses ( _) | NoWitnessesFull => bug ! ( ) ,
10731093 } ;
10741094 UsefulnessReport { arm_usefulness, non_exhaustiveness_witnesses }
10751095}
0 commit comments