@@ -1270,9 +1270,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
12701270 ) {
12711271 let mut split_or_candidate = false ;
12721272 for candidate in & mut * candidates {
1273- if let [ MatchPair { test_case : TestCase :: Or { pats, .. } , .. } ] =
1274- & * candidate. match_pairs
1275- {
1273+ if let [ MatchPair { test_case : TestCase :: Or { .. } , .. } ] = & * candidate. match_pairs {
12761274 // Split a candidate in which the only match-pair is an or-pattern into multiple
12771275 // candidates. This is so that
12781276 //
@@ -1282,9 +1280,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
12821280 // }
12831281 //
12841282 // only generates a single switch.
1285- candidate. subcandidates = self . create_or_subcandidates ( pats, candidate. has_guard ) ;
1286- let first_match_pair = candidate. match_pairs . pop ( ) . unwrap ( ) ;
1287- candidate. or_span = Some ( first_match_pair. pattern . span ) ;
1283+ let match_pair = candidate. match_pairs . pop ( ) . unwrap ( ) ;
1284+ self . create_or_subcandidates ( candidate, match_pair) ;
12881285 split_or_candidate = true ;
12891286 }
12901287 }
@@ -1297,7 +1294,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
12971294 for candidate in candidates. iter_mut ( ) {
12981295 candidate. visit_leaves ( |leaf_candidate| new_candidates. push ( leaf_candidate) ) ;
12991296 }
1300- self . match_simplified_candidates (
1297+ self . match_candidates (
13011298 span,
13021299 scrutinee_span,
13031300 start_block,
@@ -1472,14 +1469,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
14721469 return ;
14731470 }
14741471
1475- let match_pairs = mem:: take ( & mut first_candidate. match_pairs ) ;
1476- let ( first_match_pair, remaining_match_pairs) = match_pairs. split_first ( ) . unwrap ( ) ;
1477- let TestCase :: Or { ref pats } = & first_match_pair. test_case else { unreachable ! ( ) } ;
1478-
1472+ let first_match_pair = first_candidate. match_pairs . remove ( 0 ) ;
1473+ let remaining_match_pairs = mem:: take ( & mut first_candidate. match_pairs ) ;
14791474 let remainder_start = self . cfg . start_new_block ( ) ;
1480- let or_span = first_match_pair. pattern . span ;
14811475 // Test the alternatives of this or-pattern.
1482- self . test_or_pattern ( first_candidate, start_block, remainder_start, pats , or_span ) ;
1476+ self . test_or_pattern ( first_candidate, start_block, remainder_start, first_match_pair ) ;
14831477
14841478 if !remaining_match_pairs. is_empty ( ) {
14851479 // If more match pairs remain, test them after each subcandidate.
@@ -1514,56 +1508,58 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
15141508 ) ;
15151509 }
15161510
1517- #[ instrument(
1518- skip( self , start_block, otherwise_block, or_span, candidate, pats) ,
1519- level = "debug"
1520- ) ]
1511+ #[ instrument( skip( self , start_block, otherwise_block, candidate, match_pair) , level = "debug" ) ]
15211512 fn test_or_pattern < ' pat > (
15221513 & mut self ,
15231514 candidate : & mut Candidate < ' pat , ' tcx > ,
15241515 start_block : BasicBlock ,
15251516 otherwise_block : BasicBlock ,
1526- pats : & [ FlatPat < ' pat , ' tcx > ] ,
1527- or_span : Span ,
1517+ match_pair : MatchPair < ' pat , ' tcx > ,
15281518 ) {
1529- debug ! ( "candidate={:#?}\n pats={:#?}" , candidate, pats) ;
1530- let mut or_candidates: Vec < _ > = pats
1531- . iter ( )
1532- . cloned ( )
1533- . map ( |flat_pat| Candidate :: from_flat_pat ( flat_pat, candidate. has_guard ) )
1534- . collect ( ) ;
1535- let mut or_candidate_refs: Vec < _ > = or_candidates. iter_mut ( ) . collect ( ) ;
1519+ let or_span = match_pair. pattern . span ;
1520+ self . create_or_subcandidates ( candidate, match_pair) ;
1521+ let mut or_candidate_refs: Vec < _ > = candidate. subcandidates . iter_mut ( ) . collect ( ) ;
15361522 self . match_candidates (
15371523 or_span,
15381524 or_span,
15391525 start_block,
15401526 otherwise_block,
15411527 & mut or_candidate_refs,
15421528 ) ;
1543- candidate. subcandidates = or_candidates;
1544- candidate. or_span = Some ( or_span) ;
15451529 self . merge_trivial_subcandidates ( candidate) ;
15461530 }
15471531
1548- /// Try to merge all of the subcandidates of the given candidate into one.
1549- /// This avoids exponentially large CFGs in cases like `(1 | 2, 3 | 4, ...)`.
1532+ /// Given a match-pair that corresponds to an or-pattern, expand each subpattern into a new
1533+ /// subcandidate. Any candidate that has been expanded that way should be passed to
1534+ /// `merge_trivial_subcandidates` after its subcandidates have been processed.
1535+ fn create_or_subcandidates < ' pat > (
1536+ & mut self ,
1537+ candidate : & mut Candidate < ' pat , ' tcx > ,
1538+ match_pair : MatchPair < ' pat , ' tcx > ,
1539+ ) {
1540+ let TestCase :: Or { pats } = match_pair. test_case else { bug ! ( ) } ;
1541+ debug ! ( "expanding or-pattern: candidate={:#?}\n pats={:#?}" , candidate, pats) ;
1542+ candidate. or_span = Some ( match_pair. pattern . span ) ;
1543+ candidate. subcandidates = pats
1544+ . into_vec ( )
1545+ . into_iter ( )
1546+ . map ( |flat_pat| Candidate :: from_flat_pat ( flat_pat, candidate. has_guard ) )
1547+ . collect ( ) ;
1548+ }
1549+
1550+ /// Try to merge all of the subcandidates of the given candidate into one. This avoids
1551+ /// exponentially large CFGs in cases like `(1 | 2, 3 | 4, ...)`. The or-pattern should have
1552+ /// been expanded with `create_or_subcandidates`.
15501553 fn merge_trivial_subcandidates ( & mut self , candidate : & mut Candidate < ' _ , ' tcx > ) {
15511554 if candidate. subcandidates . is_empty ( ) || candidate. has_guard {
15521555 // FIXME(or_patterns; matthewjasper) Don't give up if we have a guard.
15531556 return ;
15541557 }
15551558
1556- let mut can_merge = true ;
1557-
1558- // Not `Iterator::all` because we don't want to short-circuit.
1559- for subcandidate in & mut candidate. subcandidates {
1560- self . merge_trivial_subcandidates ( subcandidate) ;
1561-
1562- // FIXME(or_patterns; matthewjasper) Try to be more aggressive here.
1563- can_merge &=
1564- subcandidate. subcandidates . is_empty ( ) && subcandidate. extra_data . is_empty ( ) ;
1565- }
1566-
1559+ // FIXME(or_patterns; matthewjasper) Try to be more aggressive here.
1560+ let can_merge = candidate. subcandidates . iter ( ) . all ( |subcandidate| {
1561+ subcandidate. subcandidates . is_empty ( ) && subcandidate. extra_data . is_empty ( )
1562+ } ) ;
15671563 if can_merge {
15681564 let any_matches = self . cfg . start_new_block ( ) ;
15691565 let or_span = candidate. or_span . take ( ) . unwrap ( ) ;
0 commit comments