@@ -319,54 +319,52 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
319
319
// them.
320
320
let mut fake_borrows = match_has_guard. then ( FxIndexSet :: default) ;
321
321
322
- let mut otherwise = None ;
322
+ let otherwise_block = self . cfg . start_new_block ( ) ;
323
323
324
324
// This will generate code to test scrutinee_place and
325
325
// branch to the appropriate arm block
326
326
self . match_candidates (
327
327
match_start_span,
328
328
scrutinee_span,
329
329
block,
330
- & mut otherwise ,
330
+ otherwise_block ,
331
331
candidates,
332
332
& mut fake_borrows,
333
333
) ;
334
334
335
- if let Some ( otherwise_block) = otherwise {
336
- // See the doc comment on `match_candidates` for why we may have an
337
- // otherwise block. Match checking will ensure this is actually
338
- // unreachable.
339
- let source_info = self . source_info ( scrutinee_span) ;
340
-
341
- // Matching on a `scrutinee_place` with an uninhabited type doesn't
342
- // generate any memory reads by itself, and so if the place "expression"
343
- // contains unsafe operations like raw pointer dereferences or union
344
- // field projections, we wouldn't know to require an `unsafe` block
345
- // around a `match` equivalent to `std::intrinsics::unreachable()`.
346
- // See issue #47412 for this hole being discovered in the wild.
347
- //
348
- // HACK(eddyb) Work around the above issue by adding a dummy inspection
349
- // of `scrutinee_place`, specifically by applying `ReadForMatch`.
350
- //
351
- // NOTE: ReadForMatch also checks that the scrutinee is initialized.
352
- // This is currently needed to not allow matching on an uninitialized,
353
- // uninhabited value. If we get never patterns, those will check that
354
- // the place is initialized, and so this read would only be used to
355
- // check safety.
356
- let cause_matched_place = FakeReadCause :: ForMatchedPlace ( None ) ;
357
-
358
- if let Some ( scrutinee_place) = scrutinee_place_builder. try_to_place ( self ) {
359
- self . cfg . push_fake_read (
360
- otherwise_block,
361
- source_info,
362
- cause_matched_place,
363
- scrutinee_place,
364
- ) ;
365
- }
335
+ // See the doc comment on `match_candidates` for why we may have an
336
+ // otherwise block. Match checking will ensure this is actually
337
+ // unreachable.
338
+ let source_info = self . source_info ( scrutinee_span) ;
339
+
340
+ // Matching on a `scrutinee_place` with an uninhabited type doesn't
341
+ // generate any memory reads by itself, and so if the place "expression"
342
+ // contains unsafe operations like raw pointer dereferences or union
343
+ // field projections, we wouldn't know to require an `unsafe` block
344
+ // around a `match` equivalent to `std::intrinsics::unreachable()`.
345
+ // See issue #47412 for this hole being discovered in the wild.
346
+ //
347
+ // HACK(eddyb) Work around the above issue by adding a dummy inspection
348
+ // of `scrutinee_place`, specifically by applying `ReadForMatch`.
349
+ //
350
+ // NOTE: ReadForMatch also checks that the scrutinee is initialized.
351
+ // This is currently needed to not allow matching on an uninitialized,
352
+ // uninhabited value. If we get never patterns, those will check that
353
+ // the place is initialized, and so this read would only be used to
354
+ // check safety.
355
+ let cause_matched_place = FakeReadCause :: ForMatchedPlace ( None ) ;
366
356
367
- self . cfg . terminate ( otherwise_block, source_info, TerminatorKind :: Unreachable ) ;
357
+ if let Some ( scrutinee_place) = scrutinee_place_builder. try_to_place ( self ) {
358
+ self . cfg . push_fake_read (
359
+ otherwise_block,
360
+ source_info,
361
+ cause_matched_place,
362
+ scrutinee_place,
363
+ ) ;
368
364
}
369
365
366
+ self . cfg . terminate ( otherwise_block, source_info, TerminatorKind :: Unreachable ) ;
367
+
370
368
// Link each leaf candidate to the `pre_binding_block` of the next one.
371
369
let mut previous_candidate: Option < & mut Candidate < ' _ , ' _ > > = None ;
372
370
@@ -1163,7 +1161,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1163
1161
span : Span ,
1164
1162
scrutinee_span : Span ,
1165
1163
start_block : BasicBlock ,
1166
- otherwise_block : & mut Option < BasicBlock > ,
1164
+ otherwise_block : BasicBlock ,
1167
1165
candidates : & mut [ & mut Candidate < ' pat , ' tcx > ] ,
1168
1166
fake_borrows : & mut Option < FxIndexSet < Place < ' tcx > > > ,
1169
1167
) {
@@ -1210,7 +1208,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1210
1208
span : Span ,
1211
1209
scrutinee_span : Span ,
1212
1210
start_block : BasicBlock ,
1213
- otherwise_block : & mut Option < BasicBlock > ,
1211
+ otherwise_block : BasicBlock ,
1214
1212
candidates : & mut [ & mut Candidate < ' _ , ' tcx > ] ,
1215
1213
fake_borrows : & mut Option < FxIndexSet < Place < ' tcx > > > ,
1216
1214
) {
@@ -1243,11 +1241,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1243
1241
// never reach this point.
1244
1242
if unmatched_candidates. is_empty ( ) {
1245
1243
let source_info = self . source_info ( span) ;
1246
- if let Some ( otherwise) = * otherwise_block {
1247
- self . cfg . goto ( block, source_info, otherwise) ;
1248
- } else {
1249
- * otherwise_block = Some ( block) ;
1250
- }
1244
+ self . cfg . goto ( block, source_info, otherwise_block) ;
1251
1245
return ;
1252
1246
}
1253
1247
@@ -1428,7 +1422,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1428
1422
scrutinee_span : Span ,
1429
1423
candidates : & mut [ & mut Candidate < ' _ , ' tcx > ] ,
1430
1424
block : BasicBlock ,
1431
- otherwise_block : & mut Option < BasicBlock > ,
1425
+ otherwise_block : BasicBlock ,
1432
1426
fake_borrows : & mut Option < FxIndexSet < Place < ' tcx > > > ,
1433
1427
) {
1434
1428
let ( first_candidate, remaining_candidates) = candidates. split_first_mut ( ) . unwrap ( ) ;
@@ -1453,7 +1447,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1453
1447
let match_pairs = mem:: take ( & mut first_candidate. match_pairs ) ;
1454
1448
first_candidate. pre_binding_block = Some ( block) ;
1455
1449
1456
- let mut otherwise = None ;
1450
+ let remainder_start = self . cfg . start_new_block ( ) ;
1457
1451
for match_pair in match_pairs {
1458
1452
let PatKind :: Or { ref pats } = & match_pair. pattern . kind else {
1459
1453
bug ! ( "Or-patterns should have been sorted to the end" ) ;
@@ -1463,7 +1457,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1463
1457
first_candidate. visit_leaves ( |leaf_candidate| {
1464
1458
self . test_or_pattern (
1465
1459
leaf_candidate,
1466
- & mut otherwise ,
1460
+ remainder_start ,
1467
1461
pats,
1468
1462
or_span,
1469
1463
& match_pair. place ,
@@ -1472,8 +1466,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1472
1466
} ) ;
1473
1467
}
1474
1468
1475
- let remainder_start = otherwise. unwrap_or_else ( || self . cfg . start_new_block ( ) ) ;
1476
-
1477
1469
self . match_candidates (
1478
1470
span,
1479
1471
scrutinee_span,
@@ -1491,7 +1483,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1491
1483
fn test_or_pattern < ' pat > (
1492
1484
& mut self ,
1493
1485
candidate : & mut Candidate < ' pat , ' tcx > ,
1494
- otherwise : & mut Option < BasicBlock > ,
1486
+ otherwise : BasicBlock ,
1495
1487
pats : & ' pat [ Box < Pat < ' tcx > > ] ,
1496
1488
or_span : Span ,
1497
1489
place : & PlaceBuilder < ' tcx > ,
@@ -1503,8 +1495,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1503
1495
. map ( |pat| Candidate :: new ( place. clone ( ) , pat, candidate. has_guard , self ) )
1504
1496
. collect ( ) ;
1505
1497
let mut or_candidate_refs: Vec < _ > = or_candidates. iter_mut ( ) . collect ( ) ;
1506
- let otherwise = if candidate. otherwise_block . is_some ( ) {
1507
- & mut candidate . otherwise_block
1498
+ let otherwise = if let Some ( otherwise_block ) = candidate. otherwise_block {
1499
+ otherwise_block
1508
1500
} else {
1509
1501
otherwise
1510
1502
} ;
@@ -1680,8 +1672,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1680
1672
span : Span ,
1681
1673
scrutinee_span : Span ,
1682
1674
mut candidates : & ' b mut [ & ' c mut Candidate < ' pat , ' tcx > ] ,
1683
- block : BasicBlock ,
1684
- otherwise_block : & mut Option < BasicBlock > ,
1675
+ start_block : BasicBlock ,
1676
+ otherwise_block : BasicBlock ,
1685
1677
fake_borrows : & mut Option < FxIndexSet < Place < ' tcx > > > ,
1686
1678
) {
1687
1679
// extract the match-pair from the highest priority candidate
@@ -1749,12 +1741,21 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1749
1741
debug ! ( "untested_candidates: {}" , candidates. len( ) ) ;
1750
1742
1751
1743
// The block that we should branch to if none of the
1752
- // `target_candidates` match. This is either the block where we
1753
- // start matching the untested candidates if there are any,
1754
- // otherwise it's the `otherwise_block`.
1755
- let remainder_start = & mut None ;
1756
- let remainder_start =
1757
- if candidates. is_empty ( ) { & mut * otherwise_block } else { remainder_start } ;
1744
+ // `target_candidates` match.
1745
+ let remainder_start = if !candidates. is_empty ( ) {
1746
+ let remainder_start = self . cfg . start_new_block ( ) ;
1747
+ self . match_candidates (
1748
+ span,
1749
+ scrutinee_span,
1750
+ remainder_start,
1751
+ otherwise_block,
1752
+ candidates,
1753
+ fake_borrows,
1754
+ ) ;
1755
+ remainder_start
1756
+ } else {
1757
+ otherwise_block
1758
+ } ;
1758
1759
1759
1760
// For each outcome of test, process the candidates that still
1760
1761
// apply. Collect a list of blocks where control flow will
@@ -1775,24 +1776,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1775
1776
) ;
1776
1777
candidate_start
1777
1778
} else {
1778
- * remainder_start. get_or_insert_with ( || self . cfg . start_new_block ( ) )
1779
+ remainder_start
1779
1780
}
1780
1781
} )
1781
1782
. collect ( ) ;
1782
1783
1783
- if !candidates. is_empty ( ) {
1784
- let remainder_start = remainder_start. unwrap_or_else ( || self . cfg . start_new_block ( ) ) ;
1785
- self . match_candidates (
1786
- span,
1787
- scrutinee_span,
1788
- remainder_start,
1789
- otherwise_block,
1790
- candidates,
1791
- fake_borrows,
1792
- ) ;
1793
- }
1794
-
1795
- self . perform_test ( span, scrutinee_span, block, & match_place, & test, target_blocks) ;
1784
+ // Perform the test, branching to one of N blocks.
1785
+ self . perform_test ( span, scrutinee_span, start_block, & match_place, & test, target_blocks) ;
1796
1786
}
1797
1787
1798
1788
/// Determine the fake borrows that are needed from a set of places that
0 commit comments