@@ -1270,9 +1270,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1270
1270
) {
1271
1271
let mut split_or_candidate = false ;
1272
1272
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 {
1276
1274
// Split a candidate in which the only match-pair is an or-pattern into multiple
1277
1275
// candidates. This is so that
1278
1276
//
@@ -1282,9 +1280,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1282
1280
// }
1283
1281
//
1284
1282
// 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) ;
1288
1285
split_or_candidate = true ;
1289
1286
}
1290
1287
}
@@ -1297,7 +1294,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1297
1294
for candidate in candidates. iter_mut ( ) {
1298
1295
candidate. visit_leaves ( |leaf_candidate| new_candidates. push ( leaf_candidate) ) ;
1299
1296
}
1300
- self . match_simplified_candidates (
1297
+ self . match_candidates (
1301
1298
span,
1302
1299
scrutinee_span,
1303
1300
start_block,
@@ -1472,14 +1469,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1472
1469
return ;
1473
1470
}
1474
1471
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 ) ;
1479
1474
let remainder_start = self . cfg . start_new_block ( ) ;
1480
- let or_span = first_match_pair. pattern . span ;
1481
1475
// 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 ) ;
1483
1477
1484
1478
if !remaining_match_pairs. is_empty ( ) {
1485
1479
// If more match pairs remain, test them after each subcandidate.
@@ -1514,56 +1508,58 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1514
1508
) ;
1515
1509
}
1516
1510
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" ) ]
1521
1512
fn test_or_pattern < ' pat > (
1522
1513
& mut self ,
1523
1514
candidate : & mut Candidate < ' pat , ' tcx > ,
1524
1515
start_block : BasicBlock ,
1525
1516
otherwise_block : BasicBlock ,
1526
- pats : & [ FlatPat < ' pat , ' tcx > ] ,
1527
- or_span : Span ,
1517
+ match_pair : MatchPair < ' pat , ' tcx > ,
1528
1518
) {
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 ( ) ;
1536
1522
self . match_candidates (
1537
1523
or_span,
1538
1524
or_span,
1539
1525
start_block,
1540
1526
otherwise_block,
1541
1527
& mut or_candidate_refs,
1542
1528
) ;
1543
- candidate. subcandidates = or_candidates;
1544
- candidate. or_span = Some ( or_span) ;
1545
1529
self . merge_trivial_subcandidates ( candidate) ;
1546
1530
}
1547
1531
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`.
1550
1553
fn merge_trivial_subcandidates ( & mut self , candidate : & mut Candidate < ' _ , ' tcx > ) {
1551
1554
if candidate. subcandidates . is_empty ( ) || candidate. has_guard {
1552
1555
// FIXME(or_patterns; matthewjasper) Don't give up if we have a guard.
1553
1556
return ;
1554
1557
}
1555
1558
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
+ } ) ;
1567
1563
if can_merge {
1568
1564
let any_matches = self . cfg . start_new_block ( ) ;
1569
1565
let or_span = candidate. or_span . take ( ) . unwrap ( ) ;
0 commit comments