@@ -1272,9 +1272,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1272
1272
) {
1273
1273
let mut split_or_candidate = false ;
1274
1274
for candidate in & mut * candidates {
1275
- if let [ MatchPair { test_case : TestCase :: Or { pats, .. } , .. } ] =
1276
- & * candidate. match_pairs
1277
- {
1275
+ if let [ MatchPair { test_case : TestCase :: Or { .. } , .. } ] = & * candidate. match_pairs {
1278
1276
// Split a candidate in which the only match-pair is an or-pattern into multiple
1279
1277
// candidates. This is so that
1280
1278
//
@@ -1284,9 +1282,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1284
1282
// }
1285
1283
//
1286
1284
// only generates a single switch.
1287
- candidate. subcandidates = self . create_or_subcandidates ( pats, candidate. has_guard ) ;
1288
- let first_match_pair = candidate. match_pairs . pop ( ) . unwrap ( ) ;
1289
- candidate. or_span = Some ( first_match_pair. pattern . span ) ;
1285
+ let match_pair = candidate. match_pairs . pop ( ) . unwrap ( ) ;
1286
+ self . create_or_subcandidates ( candidate, match_pair) ;
1290
1287
split_or_candidate = true ;
1291
1288
}
1292
1289
}
@@ -1474,14 +1471,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1474
1471
return ;
1475
1472
}
1476
1473
1477
- let match_pairs = mem:: take ( & mut first_candidate. match_pairs ) ;
1478
- let ( first_match_pair, remaining_match_pairs) = match_pairs. split_first ( ) . unwrap ( ) ;
1479
- let TestCase :: Or { ref pats } = & first_match_pair. test_case else { unreachable ! ( ) } ;
1480
-
1474
+ let first_match_pair = first_candidate. match_pairs . remove ( 0 ) ;
1475
+ let remaining_match_pairs = mem:: take ( & mut first_candidate. match_pairs ) ;
1481
1476
let remainder_start = self . cfg . start_new_block ( ) ;
1482
- let or_span = first_match_pair. pattern . span ;
1483
1477
// Test the alternatives of this or-pattern.
1484
- self . test_or_pattern ( first_candidate, start_block, remainder_start, pats , or_span ) ;
1478
+ self . test_or_pattern ( first_candidate, start_block, remainder_start, first_match_pair ) ;
1485
1479
1486
1480
if !remaining_match_pairs. is_empty ( ) {
1487
1481
// If more match pairs remain, test them after each subcandidate.
@@ -1516,52 +1510,58 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1516
1510
) ;
1517
1511
}
1518
1512
1519
- #[ instrument(
1520
- skip( self , start_block, otherwise_block, or_span, candidate, pats) ,
1521
- level = "debug"
1522
- ) ]
1513
+ #[ instrument( skip( self , start_block, otherwise_block, candidate, match_pair) , level = "debug" ) ]
1523
1514
fn test_or_pattern < ' pat > (
1524
1515
& mut self ,
1525
1516
candidate : & mut Candidate < ' pat , ' tcx > ,
1526
1517
start_block : BasicBlock ,
1527
1518
otherwise_block : BasicBlock ,
1528
- pats : & [ FlatPat < ' pat , ' tcx > ] ,
1529
- or_span : Span ,
1519
+ match_pair : MatchPair < ' pat , ' tcx > ,
1530
1520
) {
1531
- debug ! ( "candidate={:#?}\n pats={:#?}" , candidate, pats) ;
1532
- let mut or_candidates: Vec < _ > = pats
1533
- . iter ( )
1534
- . cloned ( )
1535
- . map ( |flat_pat| Candidate :: from_flat_pat ( flat_pat, candidate. has_guard ) )
1536
- . collect ( ) ;
1537
- let mut or_candidate_refs: Vec < _ > = or_candidates. iter_mut ( ) . collect ( ) ;
1521
+ let or_span = match_pair. pattern . span ;
1522
+ self . create_or_subcandidates ( candidate, match_pair) ;
1523
+ let mut or_candidate_refs: Vec < _ > = candidate. subcandidates . iter_mut ( ) . collect ( ) ;
1538
1524
self . match_candidates (
1539
1525
or_span,
1540
1526
or_span,
1541
1527
start_block,
1542
1528
otherwise_block,
1543
1529
& mut or_candidate_refs,
1544
1530
) ;
1545
- candidate. subcandidates = or_candidates;
1546
- candidate. or_span = Some ( or_span) ;
1547
1531
self . merge_trivial_subcandidates ( candidate) ;
1548
1532
}
1549
1533
1550
- /// Try to merge all of the subcandidates of the given candidate into one.
1551
- /// This avoids exponentially large CFGs in cases like `(1 | 2, 3 | 4, ...)`.
1534
+ /// Given a match-pair that corresponds to an or-pattern, expand each subpattern into a new
1535
+ /// subcandidate. Any candidate that has been expanded that way should be passed to
1536
+ /// `merge_trivial_subcandidates` after its subcandidates have been processed.
1537
+ fn create_or_subcandidates < ' pat > (
1538
+ & mut self ,
1539
+ candidate : & mut Candidate < ' pat , ' tcx > ,
1540
+ match_pair : MatchPair < ' pat , ' tcx > ,
1541
+ ) {
1542
+ let TestCase :: Or { pats } = match_pair. test_case else { bug ! ( ) } ;
1543
+ debug ! ( "expanding or-pattern: candidate={:#?}\n pats={:#?}" , candidate, pats) ;
1544
+ candidate. or_span = Some ( match_pair. pattern . span ) ;
1545
+ candidate. subcandidates = pats
1546
+ . into_vec ( )
1547
+ . into_iter ( )
1548
+ . map ( |flat_pat| Candidate :: from_flat_pat ( flat_pat, candidate. has_guard ) )
1549
+ . collect ( ) ;
1550
+ }
1551
+
1552
+ /// Try to merge all of the subcandidates of the given candidate into one. This avoids
1553
+ /// exponentially large CFGs in cases like `(1 | 2, 3 | 4, ...)`. The or-pattern should have
1554
+ /// been expanded with `create_or_subcandidates`.
1552
1555
fn merge_trivial_subcandidates ( & mut self , candidate : & mut Candidate < ' _ , ' tcx > ) {
1553
1556
if candidate. subcandidates . is_empty ( ) || candidate. has_guard {
1554
1557
// FIXME(or_patterns; matthewjasper) Don't give up if we have a guard.
1555
1558
return ;
1556
1559
}
1557
1560
1558
- let mut can_merge = true ;
1559
- for subcandidate in & mut candidate. subcandidates {
1560
- // FIXME(or_patterns; matthewjasper) Try to be more aggressive here.
1561
- can_merge &=
1562
- subcandidate. subcandidates . is_empty ( ) && subcandidate. extra_data . is_empty ( ) ;
1563
- }
1564
-
1561
+ // FIXME(or_patterns; matthewjasper) Try to be more aggressive here.
1562
+ let can_merge = candidate. subcandidates . iter ( ) . all ( |subcandidate| {
1563
+ subcandidate. subcandidates . is_empty ( ) && subcandidate. extra_data . is_empty ( )
1564
+ } ) ;
1565
1565
if can_merge {
1566
1566
let any_matches = self . cfg . start_new_block ( ) ;
1567
1567
let or_span = candidate. or_span . take ( ) . unwrap ( ) ;
0 commit comments