@@ -713,13 +713,9 @@ impl<'tcx> Usefulness<'tcx> {
713713 }
714714 }
715715
716- fn is_useful ( & self ) -> bool {
717- !matches ! ( * self , NotUseful )
718- }
719-
720716 /// When trying several branches and each returns a `Usefulness`, we need to combine the
721717 /// results together.
722- fn merge ( usefulnesses : impl Iterator < Item = ( Self , Span ) > ) -> Self {
718+ fn merge_or_patterns ( usefulnesses : impl Iterator < Item = ( Self , Span ) > ) -> Self {
723719 // If we have detected some unreachable sub-branches, we only want to keep them when they
724720 // were unreachable in _all_ branches. Eg. in the following, the last `true` is unreachable
725721 // in the second branch of the first or-pattern, but not otherwise. Therefore we don't want
@@ -789,6 +785,27 @@ impl<'tcx> Usefulness<'tcx> {
789785 }
790786 }
791787
788+ /// When trying several branches and each returns a `Usefulness`, we need to combine the
789+ /// results together.
790+ fn merge_split_constructors ( usefulnesses : impl Iterator < Item = Self > ) -> Self {
791+ // Witnesses of usefulness, if any.
792+ let mut witnesses = Vec :: new ( ) ;
793+
794+ for u in usefulnesses {
795+ match u {
796+ Useful ( ..) => {
797+ return u;
798+ }
799+ NotUseful => { }
800+ UsefulWithWitness ( wits) => {
801+ witnesses. extend ( wits) ;
802+ }
803+ }
804+ }
805+
806+ if !witnesses. is_empty ( ) { UsefulWithWitness ( witnesses) } else { NotUseful }
807+ }
808+
792809 fn apply_constructor < ' p > (
793810 self ,
794811 pcx : PatCtxt < ' _ , ' p , ' tcx > ,
@@ -975,29 +992,22 @@ fn is_useful<'p, 'tcx>(
975992 }
976993 ( u, span)
977994 } ) ;
978- Usefulness :: merge ( usefulnesses)
995+ Usefulness :: merge_or_patterns ( usefulnesses)
979996 } else {
980- v. head_ctor ( cx)
981- . split ( pcx, Some ( hir_id) )
982- . into_iter ( )
983- . map ( |ctor| {
984- // We cache the result of `Fields::wildcards` because it is used a lot.
985- let ctor_wild_subpatterns = Fields :: wildcards ( pcx, & ctor) ;
986- let matrix = pcx. matrix . specialize_constructor ( pcx, & ctor, & ctor_wild_subpatterns) ;
987- let v = v. pop_head_constructor ( & ctor_wild_subpatterns) ;
988- let usefulness = is_useful (
989- pcx. cx ,
990- & matrix,
991- & v,
992- witness_preference,
993- hir_id,
994- is_under_guard,
995- false ,
996- ) ;
997- usefulness. apply_constructor ( pcx, & ctor, & ctor_wild_subpatterns)
998- } )
999- . find ( |result| result. is_useful ( ) )
1000- . unwrap_or ( NotUseful )
997+ // We split the head constructor of `v`.
998+ let ctors = v. head_ctor ( cx) . split ( pcx, Some ( hir_id) ) ;
999+ // For each constructor, we compute whether there's a value that starts with it that would
1000+ // witness the usefulness of `v`.
1001+ let usefulnesses = ctors. into_iter ( ) . map ( |ctor| {
1002+ // We cache the result of `Fields::wildcards` because it is used a lot.
1003+ let ctor_wild_subpatterns = Fields :: wildcards ( pcx, & ctor) ;
1004+ let matrix = pcx. matrix . specialize_constructor ( pcx, & ctor, & ctor_wild_subpatterns) ;
1005+ let v = v. pop_head_constructor ( & ctor_wild_subpatterns) ;
1006+ let usefulness =
1007+ is_useful ( pcx. cx , & matrix, & v, witness_preference, hir_id, is_under_guard, false ) ;
1008+ usefulness. apply_constructor ( pcx, & ctor, & ctor_wild_subpatterns)
1009+ } ) ;
1010+ Usefulness :: merge_split_constructors ( usefulnesses)
10011011 } ;
10021012 debug ! ( "is_useful::returns({:#?}, {:#?}) = {:?}" , matrix, v, ret) ;
10031013 ret
0 commit comments