@@ -1260,9 +1260,34 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
12601260 fake_borrows,
12611261 )
12621262 }
1263+ [ first, remaining @ ..]
1264+ if matches ! ( first. match_pairs[ 0 ] . pattern. kind, PatKind :: Or { .. } ) =>
1265+ {
1266+ // The first candidate has an or-pattern.
1267+ let remainder_start = self . cfg . start_new_block ( ) ;
1268+ // Test the or-pattern.
1269+ self . test_or_candidate (
1270+ span,
1271+ scrutinee_span,
1272+ first,
1273+ start_block,
1274+ remainder_start,
1275+ fake_borrows,
1276+ ) ;
1277+ // Test the remaining candidates.
1278+ self . match_candidates (
1279+ span,
1280+ scrutinee_span,
1281+ remainder_start,
1282+ otherwise_block,
1283+ remaining,
1284+ fake_borrows,
1285+ ) ;
1286+ }
12631287 candidates => {
1264- // The first candidate has some unsatisfied match pairs; we proceed to do more tests.
1265- self . test_candidates_with_or (
1288+ // The first candidate has some unsatisfied match pairs that aren't or-patterns; we
1289+ // proceed to do more tests.
1290+ self . test_candidates (
12661291 span,
12671292 scrutinee_span,
12681293 candidates,
@@ -1350,8 +1375,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
13501375 otherwise_block
13511376 }
13521377
1353- /// Tests a candidate where there are only or-patterns left to test, or
1354- /// forwards to [Builder::test_candidates].
1378+ /// Tests a candidate whose first match-pair is an or-pattern.
13551379 ///
13561380 /// Given a pattern `(P | Q, R | S)` we (in principle) generate a CFG like
13571381 /// so:
@@ -1403,40 +1427,28 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
14031427 /// |
14041428 /// ...
14051429 /// ```
1406- fn test_candidates_with_or (
1430+ fn test_or_candidate (
14071431 & mut self ,
14081432 span : Span ,
14091433 scrutinee_span : Span ,
1410- candidates : & mut [ & mut Candidate < ' _ , ' tcx > ] ,
1434+ candidate : & mut Candidate < ' _ , ' tcx > ,
14111435 start_block : BasicBlock ,
14121436 otherwise_block : BasicBlock ,
14131437 fake_borrows : & mut Option < FxIndexSet < Place < ' tcx > > > ,
14141438 ) {
1415- let ( first_candidate, remaining_candidates) = candidates. split_first_mut ( ) . unwrap ( ) ;
1416- assert ! ( first_candidate. subcandidates. is_empty( ) ) ;
1417- if !matches ! ( first_candidate. match_pairs[ 0 ] . pattern. kind, PatKind :: Or { .. } ) {
1418- self . test_candidates (
1419- span,
1420- scrutinee_span,
1421- candidates,
1422- start_block,
1423- otherwise_block,
1424- fake_borrows,
1425- ) ;
1426- return ;
1427- }
1428-
1429- let match_pairs = mem:: take ( & mut first_candidate. match_pairs ) ;
1439+ assert ! ( candidate. subcandidates. is_empty( ) ) ;
1440+ let match_pairs = mem:: take ( & mut candidate. match_pairs ) ;
14301441 let ( first_match_pair, remaining_match_pairs) = match_pairs. split_first ( ) . unwrap ( ) ;
1431- let PatKind :: Or { ref pats } = & first_match_pair. pattern . kind else { unreachable ! ( ) } ;
1442+ let PatKind :: Or { ref pats } = & first_match_pair. pattern . kind else {
1443+ bug ! ( "Only call `test_or_candidate` if the first match pair is an or-pattern" )
1444+ } ;
14321445
1433- let remainder_start = self . cfg . start_new_block ( ) ;
14341446 let or_span = first_match_pair. pattern . span ;
14351447 // Test the alternatives of this or-pattern.
14361448 self . test_or_pattern (
1437- first_candidate ,
1449+ candidate ,
14381450 start_block,
1439- remainder_start ,
1451+ otherwise_block ,
14401452 pats,
14411453 or_span,
14421454 & first_match_pair. place ,
@@ -1448,34 +1460,24 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
14481460 // We could add them to the or-candidates before the call to `test_or_pattern` but this
14491461 // would make it impossible to detect simplifiable or-patterns. That would guarantee
14501462 // exponentially large CFGs for cases like `(1 | 2, 3 | 4, ...)`.
1451- first_candidate . visit_leaves ( |leaf_candidate| {
1463+ candidate . visit_leaves ( |leaf_candidate| {
14521464 assert ! ( leaf_candidate. match_pairs. is_empty( ) ) ;
14531465 leaf_candidate. match_pairs . extend ( remaining_match_pairs. iter ( ) . cloned ( ) ) ;
14541466 let or_start = leaf_candidate. pre_binding_block . unwrap ( ) ;
14551467 // In a case like `(a | b, c | d)`, if `a` succeeds and `c | d` fails, we know `(b,
14561468 // c | d)` will fail too. If there is no guard, we skip testing of `b` by branching
1457- // directly to `remainder_start `. If there is a guard, we have to try `(b, c | d)`.
1458- let or_otherwise = leaf_candidate. otherwise_block . unwrap_or ( remainder_start ) ;
1459- self . test_candidates_with_or (
1469+ // directly to `otherwise_block `. If there is a guard, we have to try `(b, c | d)`.
1470+ let or_otherwise = leaf_candidate. otherwise_block . unwrap_or ( otherwise_block ) ;
1471+ self . match_simplified_candidates (
14601472 span,
14611473 scrutinee_span,
1462- & mut [ leaf_candidate] ,
14631474 or_start,
14641475 or_otherwise,
1476+ & mut [ leaf_candidate] ,
14651477 fake_borrows,
14661478 ) ;
14671479 } ) ;
14681480 }
1469-
1470- // Test the remaining candidates.
1471- self . match_candidates (
1472- span,
1473- scrutinee_span,
1474- remainder_start,
1475- otherwise_block,
1476- remaining_candidates,
1477- fake_borrows,
1478- ) ;
14791481 }
14801482
14811483 #[ instrument(
0 commit comments