@@ -696,9 +696,9 @@ impl<'tcx> Usefulness<'tcx> {
696
696
}
697
697
}
698
698
699
- /// When trying several branches and each returns a `Usefulness`, we need to combine the
700
- /// results together .
701
- fn merge ( usefulnesses : impl Iterator < Item = Self > ) -> Self {
699
+ /// Combine usefulnesses from two branches. This is an associative operation and `NotUseful` is
700
+ /// a unit .
701
+ fn extend ( & mut self , other : Self ) {
702
702
// If we have detected some unreachable sub-branches, we only want to keep them when they
703
703
// were unreachable in _all_ branches. Eg. in the following, the last `true` is unreachable
704
704
// in the second branch of the first or-pattern, but not otherwise. Therefore we don't want
@@ -709,54 +709,39 @@ impl<'tcx> Usefulness<'tcx> {
709
709
// (false | true, false | true) => {}
710
710
// }
711
711
// ```
712
- // Here however we _do_ want to lint that the last `false` is unreachable. So we don't want
713
- // to intersect the spans that come directly from the or-pattern, since each branch of the
714
- // or-pattern brings a new disjoint pattern.
712
+ // Here however we _do_ want to lint that the last `false` is unreachable. In order to
713
+ // handle that correctly, each branch of an or-pattern marks the other branches as
714
+ // unreachable (see `unsplit_or_pat`). That way, intersecting the results will correctly
715
+ // identify unreachable sub-patterns.
715
716
// ```
716
717
// match None {
717
718
// Some(false) => {}
718
719
// None | Some(true | false) => {}
719
720
// }
720
721
// ```
722
+ 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 ! ( ) ,
728
+ }
729
+ }
721
730
722
- // Is `None` when no branch was useful. Will often be `Some(Spanset::new())` because the
723
- // sets are only non-empty in the presence of or-patterns.
724
- let mut unreachables: Option < SpanSet > = None ;
725
- // Witnesses of usefulness, if any.
726
- let mut witnesses = Vec :: new ( ) ;
727
-
731
+ /// When trying several branches and each returns a `Usefulness`, we need to combine the
732
+ /// results together.
733
+ fn merge ( usefulnesses : impl Iterator < Item = Self > ) -> Self {
734
+ let mut ret = NotUseful ;
728
735
for u in usefulnesses {
729
- match u {
730
- Useful ( spans) if spans. is_empty ( ) => {
736
+ ret. extend ( u) ;
737
+ if let Useful ( spans) = & ret {
738
+ if spans. is_empty ( ) {
731
739
// Once we reach the empty set, more intersections won't change the result.
732
- return Useful ( SpanSet :: new ( ) ) ;
733
- }
734
- Useful ( spans) => {
735
- if let Some ( unreachables) = & mut unreachables {
736
- if !unreachables. is_empty ( ) {
737
- unreachables. intersection_mut ( & spans) ;
738
- }
739
- if unreachables. is_empty ( ) {
740
- return Useful ( SpanSet :: new ( ) ) ;
741
- }
742
- } else {
743
- unreachables = Some ( spans) ;
744
- }
745
- }
746
- NotUseful => { }
747
- UsefulWithWitness ( wits) => {
748
- witnesses. extend ( wits) ;
740
+ return ret;
749
741
}
750
742
}
751
743
}
752
-
753
- if !witnesses. is_empty ( ) {
754
- UsefulWithWitness ( witnesses)
755
- } else if let Some ( unreachables) = unreachables {
756
- Useful ( unreachables)
757
- } else {
758
- NotUseful
759
- }
744
+ ret
760
745
}
761
746
762
747
/// After calculating the usefulness for a branch of an or-pattern, call this to make this
0 commit comments