@@ -1240,9 +1240,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1240
1240
) {
1241
1241
let mut split_or_candidate = false ;
1242
1242
for candidate in & mut * candidates {
1243
- if let [ MatchPair { test_case : TestCase :: Or { pats, .. } , .. } ] =
1244
- & * candidate. match_pairs
1245
- {
1243
+ if let [ MatchPair { test_case : TestCase :: Or { .. } , .. } ] = & * candidate. match_pairs {
1246
1244
// Split a candidate in which the only match-pair is an or-pattern into multiple
1247
1245
// candidates. This is so that
1248
1246
//
@@ -1252,9 +1250,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1252
1250
// }
1253
1251
//
1254
1252
// only generates a single switch.
1255
- candidate. subcandidates = self . create_or_subcandidates ( pats, candidate. has_guard ) ;
1256
- let first_match_pair = candidate. match_pairs . pop ( ) . unwrap ( ) ;
1257
- candidate. or_span = Some ( first_match_pair. pattern . span ) ;
1253
+ let match_pair = candidate. match_pairs . pop ( ) . unwrap ( ) ;
1254
+ self . create_or_subcandidates ( candidate, & match_pair) ;
1258
1255
split_or_candidate = true ;
1259
1256
}
1260
1257
}
@@ -1444,12 +1441,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1444
1441
1445
1442
let match_pairs = mem:: take ( & mut first_candidate. match_pairs ) ;
1446
1443
let ( first_match_pair, remaining_match_pairs) = match_pairs. split_first ( ) . unwrap ( ) ;
1447
- let TestCase :: Or { ref pats } = & first_match_pair. test_case else { unreachable ! ( ) } ;
1448
1444
1449
1445
let remainder_start = self . cfg . start_new_block ( ) ;
1450
- let or_span = first_match_pair. pattern . span ;
1451
1446
// Test the alternatives of this or-pattern.
1452
- self . test_or_pattern ( first_candidate, start_block, remainder_start, pats , or_span ) ;
1447
+ self . test_or_pattern ( first_candidate, start_block, remainder_start, first_match_pair ) ;
1453
1448
1454
1449
if !remaining_match_pairs. is_empty ( ) {
1455
1450
// If more match pairs remain, test them after each subcandidate.
@@ -1484,39 +1479,48 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1484
1479
) ;
1485
1480
}
1486
1481
1487
- #[ instrument(
1488
- skip( self , start_block, otherwise_block, or_span, candidate, pats) ,
1489
- level = "debug"
1490
- ) ]
1482
+ #[ instrument( skip( self , start_block, otherwise_block, candidate, match_pair) , level = "debug" ) ]
1491
1483
fn test_or_pattern < ' pat > (
1492
1484
& mut self ,
1493
1485
candidate : & mut Candidate < ' pat , ' tcx > ,
1494
1486
start_block : BasicBlock ,
1495
1487
otherwise_block : BasicBlock ,
1496
- pats : & [ FlatPat < ' pat , ' tcx > ] ,
1497
- or_span : Span ,
1488
+ match_pair : & MatchPair < ' pat , ' tcx > ,
1498
1489
) {
1499
- debug ! ( "candidate={:#?}\n pats={:#?}" , candidate, pats) ;
1500
- let mut or_candidates: Vec < _ > = pats
1501
- . iter ( )
1502
- . cloned ( )
1503
- . map ( |flat_pat| Candidate :: from_flat_pat ( flat_pat, candidate. has_guard ) )
1504
- . collect ( ) ;
1505
- let mut or_candidate_refs: Vec < _ > = or_candidates. iter_mut ( ) . collect ( ) ;
1490
+ self . create_or_subcandidates ( candidate, match_pair) ;
1491
+ let mut or_candidate_refs: Vec < _ > = candidate. subcandidates . iter_mut ( ) . collect ( ) ;
1492
+ let or_span = match_pair. pattern . span ;
1506
1493
self . match_candidates (
1507
1494
or_span,
1508
1495
or_span,
1509
1496
start_block,
1510
1497
otherwise_block,
1511
1498
& mut or_candidate_refs,
1512
1499
) ;
1513
- candidate. subcandidates = or_candidates;
1514
- candidate. or_span = Some ( or_span) ;
1515
1500
self . merge_trivial_subcandidates ( candidate) ;
1516
1501
}
1517
1502
1518
- /// Try to merge all of the subcandidates of the given candidate into one.
1519
- /// This avoids exponentially large CFGs in cases like `(1 | 2, 3 | 4, ...)`.
1503
+ /// Given a match-pair that corresponds to an or-pattern, expand each subpattern into a new
1504
+ /// subcandidate. Any candidate that has been expanded that way should be passed to
1505
+ /// `merge_trivial_subcandidates` after its subcandidates have been processed.
1506
+ fn create_or_subcandidates < ' pat > (
1507
+ & mut self ,
1508
+ candidate : & mut Candidate < ' pat , ' tcx > ,
1509
+ match_pair : & MatchPair < ' pat , ' tcx > ,
1510
+ ) {
1511
+ let TestCase :: Or { ref pats } = & match_pair. test_case else { bug ! ( ) } ;
1512
+ debug ! ( "expanding or-pattern: candidate={:#?}\n pats={:#?}" , candidate, pats) ;
1513
+ candidate. or_span = Some ( match_pair. pattern . span ) ;
1514
+ candidate. subcandidates = pats
1515
+ . iter ( )
1516
+ . cloned ( )
1517
+ . map ( |flat_pat| Candidate :: from_flat_pat ( flat_pat, candidate. has_guard ) )
1518
+ . collect ( ) ;
1519
+ }
1520
+
1521
+ /// Try to merge all of the subcandidates of the given candidate into one. This avoids
1522
+ /// exponentially large CFGs in cases like `(1 | 2, 3 | 4, ...)`. The or-pattern should have
1523
+ /// been expanded with `create_or_subcandidates`.
1520
1524
fn merge_trivial_subcandidates ( & mut self , candidate : & mut Candidate < ' _ , ' tcx > ) {
1521
1525
if candidate. subcandidates . is_empty ( ) || candidate. has_guard {
1522
1526
// FIXME(or_patterns; matthewjasper) Don't give up if we have a guard.
0 commit comments