@@ -1313,11 +1313,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1313
1313
candidates : & mut [ & mut Candidate < ' pat , ' tcx > ] ,
1314
1314
refutable : bool ,
1315
1315
) -> BasicBlock {
1316
+ // This will generate code to test scrutinee_place and branch to the appropriate arm block.
1316
1317
// See the doc comment on `match_candidates` for why we have an otherwise block.
1317
- let otherwise_block = self . cfg . start_new_block ( ) ;
1318
-
1319
- // This will generate code to test scrutinee_place and branch to the appropriate arm block
1320
- self . match_candidates ( match_start_span, scrutinee_span, block, otherwise_block, candidates) ;
1318
+ let otherwise_block =
1319
+ self . match_candidates ( match_start_span, scrutinee_span, block, candidates) ;
1321
1320
1322
1321
// Link each leaf candidate to the `false_edge_start_block` of the next one.
1323
1322
let mut previous_candidate: Option < & mut Candidate < ' _ , ' _ > > = None ;
@@ -1368,27 +1367,24 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1368
1367
otherwise_block
1369
1368
}
1370
1369
1371
- /// The main match algorithm. It begins with a set of candidates
1372
- /// `candidates` and has the job of generating code to determine
1373
- /// which of these candidates, if any, is the correct one . The
1370
+ /// The main match algorithm. It begins with a set of candidates `candidates` and has the job of
1371
+ /// generating code that branches to an appropriate block if the scrutinee matches one of these
1372
+ /// candidates. The
1374
1373
/// candidates are sorted such that the first item in the list
1375
1374
/// has the highest priority. When a candidate is found to match
1376
1375
/// the value, we will set and generate a branch to the appropriate
1377
1376
/// pre-binding block.
1378
1377
///
1379
- /// If we find that *NONE* of the candidates apply, we branch to `otherwise_block`.
1378
+ /// If none of the candidates apply, we continue to the returned `otherwise_block`.
1380
1379
///
1381
1380
/// It might be surprising that the input can be non-exhaustive.
1382
- /// Indeed, initially, it is not, because all matches are
1381
+ /// Indeed, for matches, initially, it is not, because all matches are
1383
1382
/// exhaustive in Rust. But during processing we sometimes divide
1384
1383
/// up the list of candidates and recurse with a non-exhaustive
1385
1384
/// list. This is how our lowering approach (called "backtracking
1386
1385
/// automaton" in the literature) works.
1387
1386
/// See [`Builder::test_candidates`] for more details.
1388
1387
///
1389
- /// If `fake_borrows` is `Some`, then places which need fake borrows
1390
- /// will be added to it.
1391
- ///
1392
1388
/// For an example of how we use `otherwise_block`, consider:
1393
1389
/// ```
1394
1390
/// # fn foo((x, y): (bool, bool)) -> u32 {
@@ -1413,7 +1409,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1413
1409
/// }
1414
1410
/// if y {
1415
1411
/// if x {
1416
- /// // This is actually unreachable because the `(true, true)` case was handled above.
1412
+ /// // This is actually unreachable because the `(true, true)` case was handled above,
1413
+ /// // but we don't know that from within the lowering algorithm.
1417
1414
/// // continue
1418
1415
/// } else {
1419
1416
/// return 3
@@ -1430,25 +1427,18 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1430
1427
/// the algorithm. For more details on why we lower like this, see [`Builder::test_candidates`].
1431
1428
///
1432
1429
/// Note how we test `x` twice. This is the tradeoff of backtracking automata: we prefer smaller
1433
- /// code size at the expense of non-optimal code paths.
1430
+ /// code size so we accept non-optimal code paths.
1434
1431
#[ instrument( skip( self ) , level = "debug" ) ]
1435
1432
fn match_candidates (
1436
1433
& mut self ,
1437
1434
span : Span ,
1438
1435
scrutinee_span : Span ,
1439
1436
start_block : BasicBlock ,
1440
- otherwise_block : BasicBlock ,
1441
1437
candidates : & mut [ & mut Candidate < ' _ , ' tcx > ] ,
1442
- ) {
1438
+ ) -> BasicBlock {
1443
1439
ensure_sufficient_stack ( || {
1444
- self . match_candidates_with_enough_stack (
1445
- span,
1446
- scrutinee_span,
1447
- start_block,
1448
- otherwise_block,
1449
- candidates,
1450
- )
1451
- } ) ;
1440
+ self . match_candidates_with_enough_stack ( span, scrutinee_span, start_block, candidates)
1441
+ } )
1452
1442
}
1453
1443
1454
1444
/// Construct the decision tree for `candidates`. Don't call this, call `match_candidates`
@@ -1458,9 +1448,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1458
1448
span : Span ,
1459
1449
scrutinee_span : Span ,
1460
1450
start_block : BasicBlock ,
1461
- otherwise_block : BasicBlock ,
1462
1451
candidates : & mut [ & mut Candidate < ' _ , ' tcx > ] ,
1463
- ) {
1452
+ ) -> BasicBlock {
1464
1453
if let [ first, ..] = candidates {
1465
1454
if first. false_edge_start_block . is_none ( ) {
1466
1455
first. false_edge_start_block = Some ( start_block) ;
@@ -1471,9 +1460,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1471
1460
let rest = match candidates {
1472
1461
[ ] => {
1473
1462
// If there are no candidates that still need testing, we're done.
1474
- let source_info = self . source_info ( span) ;
1475
- self . cfg . goto ( start_block, source_info, otherwise_block) ;
1476
- return ;
1463
+ return start_block;
1477
1464
}
1478
1465
[ first, remaining @ ..] if first. match_pairs . is_empty ( ) => {
1479
1466
// The first candidate has satisfied all its match pairs; we link it up and continue
@@ -1494,13 +1481,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1494
1481
1495
1482
// Process any candidates that remain.
1496
1483
let BlockAnd ( start_block, remaining_candidates) = rest;
1497
- self . match_candidates (
1498
- span,
1499
- scrutinee_span,
1500
- start_block,
1501
- otherwise_block,
1502
- remaining_candidates,
1503
- ) ;
1484
+ self . match_candidates ( span, scrutinee_span, start_block, remaining_candidates)
1504
1485
}
1505
1486
1506
1487
/// Link up matched candidates.
@@ -1605,14 +1586,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1605
1586
}
1606
1587
1607
1588
// Process the expanded candidates.
1608
- let remainder_start = self . cfg . start_new_block ( ) ;
1609
- // There might be new or-patterns obtained from expanding the old ones, so we call
1610
- // `match_candidates` again.
1611
- self . match_candidates (
1589
+ let remainder_start = self . match_candidates (
1612
1590
span,
1613
1591
scrutinee_span,
1614
1592
start_block,
1615
- remainder_start,
1616
1593
expanded_candidates. as_mut_slice ( ) ,
1617
1594
) ;
1618
1595
@@ -1711,6 +1688,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1711
1688
self . merge_trivial_subcandidates ( candidate) ;
1712
1689
1713
1690
if !candidate. match_pairs . is_empty ( ) {
1691
+ let or_span = candidate. or_span . unwrap_or ( candidate. extra_data . span ) ;
1692
+ let source_info = self . source_info ( or_span) ;
1714
1693
// If more match pairs remain, test them after each subcandidate.
1715
1694
// We could add them to the or-candidates before the call to `test_or_pattern` but this
1716
1695
// would make it impossible to detect simplifiable or-patterns. That would guarantee
@@ -1724,6 +1703,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1724
1703
assert ! ( leaf_candidate. match_pairs. is_empty( ) ) ;
1725
1704
leaf_candidate. match_pairs . extend ( remaining_match_pairs. iter ( ) . cloned ( ) ) ;
1726
1705
let or_start = leaf_candidate. pre_binding_block . unwrap ( ) ;
1706
+ let otherwise =
1707
+ self . match_candidates ( span, scrutinee_span, or_start, & mut [ leaf_candidate] ) ;
1727
1708
// In a case like `(P | Q, R | S)`, if `P` succeeds and `R | S` fails, we know `(Q,
1728
1709
// R | S)` will fail too. If there is no guard, we skip testing of `Q` by branching
1729
1710
// directly to `last_otherwise`. If there is a guard,
@@ -1734,13 +1715,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1734
1715
} else {
1735
1716
last_otherwise. unwrap ( )
1736
1717
} ;
1737
- self . match_candidates (
1738
- span,
1739
- scrutinee_span,
1740
- or_start,
1741
- or_otherwise,
1742
- & mut [ leaf_candidate] ,
1743
- ) ;
1718
+ self . cfg . goto ( otherwise, source_info, or_otherwise) ;
1744
1719
} ) ;
1745
1720
}
1746
1721
}
@@ -2019,15 +1994,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
2019
1994
let target_blocks: FxIndexMap < _ , _ > = target_candidates
2020
1995
. into_iter ( )
2021
1996
. map ( |( branch, mut candidates) | {
2022
- let candidate_start = self . cfg . start_new_block ( ) ;
2023
- self . match_candidates (
2024
- span,
2025
- scrutinee_span,
2026
- candidate_start,
2027
- remainder_start,
2028
- & mut * candidates,
2029
- ) ;
2030
- ( branch, candidate_start)
1997
+ let branch_start = self . cfg . start_new_block ( ) ;
1998
+ let branch_otherwise =
1999
+ self . match_candidates ( span, scrutinee_span, branch_start, & mut * candidates) ;
2000
+ let source_info = self . source_info ( span) ;
2001
+ self . cfg . goto ( branch_otherwise, source_info, remainder_start) ;
2002
+ ( branch, branch_start)
2031
2003
} )
2032
2004
. collect ( ) ;
2033
2005
0 commit comments