@@ -1426,56 +1426,70 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
14261426 fake_borrows : & mut Option < FxIndexSet < Place < ' tcx > > > ,
14271427 ) {
14281428 let ( first_candidate, remaining_candidates) = candidates. split_first_mut ( ) . unwrap ( ) ;
1429-
1430- // All of the or-patterns have been sorted to the end, so if the first
1431- // pattern is an or-pattern we only have or-patterns.
1432- match first_candidate. match_pairs [ 0 ] . pattern . kind {
1433- PatKind :: Or { .. } => ( ) ,
1434- _ => {
1435- self . test_candidates (
1436- span,
1437- scrutinee_span,
1438- candidates,
1439- start_block,
1440- otherwise_block,
1441- fake_borrows,
1442- ) ;
1443- return ;
1444- }
1429+ assert ! ( first_candidate. subcandidates. is_empty( ) ) ;
1430+ if !matches ! ( first_candidate. match_pairs[ 0 ] . pattern. kind, PatKind :: Or { .. } ) {
1431+ self . test_candidates (
1432+ span,
1433+ scrutinee_span,
1434+ candidates,
1435+ start_block,
1436+ otherwise_block,
1437+ fake_borrows,
1438+ ) ;
1439+ return ;
14451440 }
14461441
14471442 let match_pairs = mem:: take ( & mut first_candidate. match_pairs ) ;
1443+ let ( first_match_pair, remaining_match_pairs) = match_pairs. split_first ( ) . unwrap ( ) ;
1444+ let PatKind :: Or { ref pats } = & first_match_pair. pattern . kind else { unreachable ! ( ) } ;
14481445
14491446 let remainder_start = self . cfg . start_new_block ( ) ;
1450- for match_pair in match_pairs {
1451- let PatKind :: Or { ref pats } = & match_pair. pattern . kind else {
1452- bug ! ( "Or-patterns should have been sorted to the end" ) ;
1453- } ;
1454- let or_span = match_pair. pattern . span ;
1447+ let or_span = first_match_pair. pattern . span ;
1448+ // Test the alternatives of this or-pattern.
1449+ self . test_or_pattern (
1450+ first_candidate,
1451+ start_block,
1452+ remainder_start,
1453+ pats,
1454+ or_span,
1455+ & first_match_pair. place ,
1456+ fake_borrows,
1457+ ) ;
14551458
1459+ if !remaining_match_pairs. is_empty ( ) {
1460+ // If more match pairs remain, test them after each subcandidate.
1461+ // We could add them to the or-candidates before the call to `test_or_pattern` but this
1462+ // would make it impossible to detect simplifiable or-patterns. That would guarantee
1463+ // exponentially large CFGs for cases like `(1 | 2, 3 | 4, ...)`.
14561464 first_candidate. visit_leaves ( |leaf_candidate| {
1457- let or_start = leaf_candidate. pre_binding_block . unwrap_or ( start_block) ;
1465+ assert ! ( leaf_candidate. match_pairs. is_empty( ) ) ;
1466+ leaf_candidate. match_pairs . extend ( remaining_match_pairs. iter ( ) . cloned ( ) ) ;
1467+ let or_start = leaf_candidate. pre_binding_block . unwrap ( ) ;
1468+ // In a case like `(a | b, c | d)`, if `a` succeeds and `c | d` fails, we know `(b,
1469+ // c | d)` will fail too. If there is no guard, we skip testing of `b` by branching
1470+ // directly to `remainder_start`. If there is a guard, we have to try `(b, c | d)`
1471+ // anyway.
14581472 let or_otherwise = leaf_candidate. otherwise_block . unwrap_or ( remainder_start) ;
1459- self . test_or_pattern (
1460- leaf_candidate,
1473+ self . test_candidates_with_or (
1474+ span,
1475+ scrutinee_span,
1476+ & mut [ leaf_candidate] ,
14611477 or_start,
14621478 or_otherwise,
1463- pats,
1464- or_span,
1465- & match_pair. place ,
14661479 fake_borrows,
14671480 ) ;
14681481 } ) ;
14691482 }
14701483
1484+ // Test the remaining candidates.
14711485 self . match_candidates (
14721486 span,
14731487 scrutinee_span,
14741488 remainder_start,
14751489 otherwise_block,
14761490 remaining_candidates,
14771491 fake_borrows,
1478- )
1492+ ) ;
14791493 }
14801494
14811495 #[ instrument(
0 commit comments