@@ -680,24 +680,32 @@ impl SpanSet {
680
680
681
681
#[ derive( Clone , Debug ) ]
682
682
enum 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
684
684
/// 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 ,
689
692
}
690
693
691
694
impl < ' tcx > Usefulness < ' tcx > {
692
695
fn new_useful ( preference : WitnessPreference ) -> Self {
693
696
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 ,
696
705
}
697
706
}
698
707
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.
701
709
fn extend ( & mut self , other : Self ) {
702
710
// If we have detected some unreachable sub-branches, we only want to keep them when they
703
711
// were unreachable in _all_ branches. Eg. in the following, the last `true` is unreachable
@@ -720,21 +728,29 @@ impl<'tcx> Usefulness<'tcx> {
720
728
// }
721
729
// ```
722
730
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
+ }
728
744
}
729
745
}
730
746
731
747
/// When trying several branches and each returns a `Usefulness`, we need to combine the
732
748
/// 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 ) ;
735
751
for u in usefulnesses {
736
752
ret. extend ( u) ;
737
- if let Useful ( spans) = & ret {
753
+ if let NoWitnesses ( spans) = & ret {
738
754
if spans. is_empty ( ) {
739
755
// Once we reach the empty set, more intersections won't change the result.
740
756
return ret;
@@ -748,7 +764,7 @@ impl<'tcx> Usefulness<'tcx> {
748
764
/// usefulness mergeable with those from the other branches.
749
765
fn unsplit_or_pat ( self , this_span : Span , or_pat_spans : & [ Span ] ) -> Self {
750
766
match self {
751
- Useful ( mut spans) => {
767
+ NoWitnesses ( mut spans) => {
752
768
// We register the spans of the other branches of this or-pattern as being
753
769
// unreachable from this one. This ensures that intersecting together the sets of
754
770
// spans returns what we want.
@@ -759,9 +775,10 @@ impl<'tcx> Usefulness<'tcx> {
759
775
spans. push_nonintersecting ( span) ;
760
776
}
761
777
}
762
- Useful ( spans)
778
+ NoWitnesses ( spans)
763
779
}
764
- x => x,
780
+ NoWitnessesFull => NoWitnessesFull ,
781
+ WithWitnesses ( _) | WithWitnessesEmpty => bug ! ( ) ,
765
782
}
766
783
}
767
784
@@ -776,7 +793,7 @@ impl<'tcx> Usefulness<'tcx> {
776
793
ctor_wild_subpatterns : & Fields < ' p , ' tcx > ,
777
794
) -> Self {
778
795
match self {
779
- UsefulWithWitness ( witnesses) => {
796
+ WithWitnesses ( witnesses) => {
780
797
let new_witnesses = if matches ! ( ctor, Constructor :: Missing ) {
781
798
let mut split_wildcard = SplitWildcard :: new ( pcx) ;
782
799
split_wildcard. split ( pcx, matrix. head_ctors ( pcx. cx ) ) ;
@@ -806,7 +823,7 @@ impl<'tcx> Usefulness<'tcx> {
806
823
. map ( |witness| witness. apply_constructor ( pcx, & ctor, ctor_wild_subpatterns) )
807
824
. collect ( )
808
825
} ;
809
- UsefulWithWitness ( new_witnesses)
826
+ WithWitnesses ( new_witnesses)
810
827
}
811
828
x => x,
812
829
}
@@ -935,8 +952,11 @@ fn is_useful<'p, 'tcx>(
935
952
// first and then, if v is non-empty, the return value is based on whether
936
953
// the type of the tuple we're checking is inhabited or not.
937
954
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
+ } ;
940
960
debug ! ( ?ret) ;
941
961
return ret;
942
962
}
@@ -966,7 +986,7 @@ fn is_useful<'p, 'tcx>(
966
986
}
967
987
usefulness. unsplit_or_pat ( v_span, & subspans)
968
988
} ) ;
969
- Usefulness :: merge ( usefulnesses)
989
+ Usefulness :: merge ( witness_preference , usefulnesses)
970
990
} else {
971
991
let v_ctor = v. head_ctor ( cx) ;
972
992
if let Constructor :: IntRange ( ctor_range) = & v_ctor {
@@ -994,7 +1014,7 @@ fn is_useful<'p, 'tcx>(
994
1014
is_useful ( cx, & spec_matrix, & v, witness_preference, hir_id, is_under_guard, false ) ;
995
1015
usefulness. apply_constructor ( pcx, start_matrix, & ctor, & ctor_wild_subpatterns)
996
1016
} ) ;
997
- Usefulness :: merge ( usefulnesses)
1017
+ Usefulness :: merge ( witness_preference , usefulnesses)
998
1018
} ;
999
1019
debug ! ( ?ret) ;
1000
1020
ret
@@ -1049,9 +1069,9 @@ crate fn compute_match_usefulness<'p, 'tcx>(
1049
1069
matrix. push ( v) ;
1050
1070
}
1051
1071
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 ! ( ) ,
1055
1075
} ;
1056
1076
( arm, reachability)
1057
1077
} )
@@ -1061,15 +1081,15 @@ crate fn compute_match_usefulness<'p, 'tcx>(
1061
1081
let v = PatStack :: from_pattern ( wild_pattern) ;
1062
1082
let usefulness = is_useful ( cx, & matrix, & v, ConstructWitness , scrut_hir_id, false , true ) ;
1063
1083
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) => {
1066
1086
if pats. is_empty ( ) {
1067
1087
bug ! ( "Exhaustiveness check returned no witnesses" )
1068
1088
} else {
1069
1089
pats. into_iter ( ) . map ( |w| w. single_pattern ( ) ) . collect ( )
1070
1090
}
1071
1091
}
1072
- Useful ( _) => bug ! ( ) ,
1092
+ NoWitnesses ( _) | NoWitnessesFull => bug ! ( ) ,
1073
1093
} ;
1074
1094
UsefulnessReport { arm_usefulness, non_exhaustiveness_witnesses }
1075
1095
}
0 commit comments