@@ -696,9 +696,9 @@ impl<'tcx> Usefulness<'tcx> {
696696 }
697697 }
698698
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 ) {
702702 // If we have detected some unreachable sub-branches, we only want to keep them when they
703703 // were unreachable in _all_ branches. Eg. in the following, the last `true` is unreachable
704704 // 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> {
709709 // (false | true, false | true) => {}
710710 // }
711711 // ```
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.
715716 // ```
716717 // match None {
717718 // Some(false) => {}
718719 // None | Some(true | false) => {}
719720 // }
720721 // ```
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+ }
721730
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 ;
728735 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 ( ) {
731739 // 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;
749741 }
750742 }
751743 }
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
760745 }
761746
762747 /// After calculating the usefulness for a branch of an or-pattern, call this to make this
0 commit comments