@@ -1260,9 +1260,34 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1260
1260
fake_borrows,
1261
1261
)
1262
1262
}
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
+ }
1263
1287
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 (
1266
1291
span,
1267
1292
scrutinee_span,
1268
1293
candidates,
@@ -1350,8 +1375,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1350
1375
otherwise_block
1351
1376
}
1352
1377
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.
1355
1379
///
1356
1380
/// Given a pattern `(P | Q, R | S)` we (in principle) generate a CFG like
1357
1381
/// so:
@@ -1403,40 +1427,28 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1403
1427
/// |
1404
1428
/// ...
1405
1429
/// ```
1406
- fn test_candidates_with_or (
1430
+ fn test_or_candidate (
1407
1431
& mut self ,
1408
1432
span : Span ,
1409
1433
scrutinee_span : Span ,
1410
- candidates : & mut [ & mut Candidate < ' _ , ' tcx > ] ,
1434
+ candidate : & mut Candidate < ' _ , ' tcx > ,
1411
1435
start_block : BasicBlock ,
1412
1436
otherwise_block : BasicBlock ,
1413
1437
fake_borrows : & mut Option < FxIndexSet < Place < ' tcx > > > ,
1414
1438
) {
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 ) ;
1430
1441
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
+ } ;
1432
1445
1433
- let remainder_start = self . cfg . start_new_block ( ) ;
1434
1446
let or_span = first_match_pair. pattern . span ;
1435
1447
// Test the alternatives of this or-pattern.
1436
1448
self . test_or_pattern (
1437
- first_candidate ,
1449
+ candidate ,
1438
1450
start_block,
1439
- remainder_start ,
1451
+ otherwise_block ,
1440
1452
pats,
1441
1453
or_span,
1442
1454
& first_match_pair. place ,
@@ -1448,34 +1460,24 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1448
1460
// We could add them to the or-candidates before the call to `test_or_pattern` but this
1449
1461
// would make it impossible to detect simplifiable or-patterns. That would guarantee
1450
1462
// exponentially large CFGs for cases like `(1 | 2, 3 | 4, ...)`.
1451
- first_candidate . visit_leaves ( |leaf_candidate| {
1463
+ candidate . visit_leaves ( |leaf_candidate| {
1452
1464
assert ! ( leaf_candidate. match_pairs. is_empty( ) ) ;
1453
1465
leaf_candidate. match_pairs . extend ( remaining_match_pairs. iter ( ) . cloned ( ) ) ;
1454
1466
let or_start = leaf_candidate. pre_binding_block . unwrap ( ) ;
1455
1467
// In a case like `(a | b, c | d)`, if `a` succeeds and `c | d` fails, we know `(b,
1456
1468
// 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 (
1460
1472
span,
1461
1473
scrutinee_span,
1462
- & mut [ leaf_candidate] ,
1463
1474
or_start,
1464
1475
or_otherwise,
1476
+ & mut [ leaf_candidate] ,
1465
1477
fake_borrows,
1466
1478
) ;
1467
1479
} ) ;
1468
1480
}
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
- ) ;
1479
1481
}
1480
1482
1481
1483
#[ instrument(
0 commit comments