@@ -1313,11 +1313,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
13131313 candidates : & mut [ & mut Candidate < ' pat , ' tcx > ] ,
13141314 refutable : bool ,
13151315 ) -> BasicBlock {
1316+ // This will generate code to test scrutinee_place and branch to the appropriate arm block.
13161317 // 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) ;
13211320
13221321 // Link each leaf candidate to the `false_edge_start_block` of the next one.
13231322 let mut previous_candidate: Option < & mut Candidate < ' _ , ' _ > > = None ;
@@ -1368,27 +1367,24 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
13681367 otherwise_block
13691368 }
13701369
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
13741373 /// candidates are sorted such that the first item in the list
13751374 /// has the highest priority. When a candidate is found to match
13761375 /// the value, we will set and generate a branch to the appropriate
13771376 /// pre-binding block.
13781377 ///
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`.
13801379 ///
13811380 /// 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
13831382 /// exhaustive in Rust. But during processing we sometimes divide
13841383 /// up the list of candidates and recurse with a non-exhaustive
13851384 /// list. This is how our lowering approach (called "backtracking
13861385 /// automaton" in the literature) works.
13871386 /// See [`Builder::test_candidates`] for more details.
13881387 ///
1389- /// If `fake_borrows` is `Some`, then places which need fake borrows
1390- /// will be added to it.
1391- ///
13921388 /// For an example of how we use `otherwise_block`, consider:
13931389 /// ```
13941390 /// # fn foo((x, y): (bool, bool)) -> u32 {
@@ -1413,7 +1409,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
14131409 /// }
14141410 /// if y {
14151411 /// 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.
14171414 /// // continue
14181415 /// } else {
14191416 /// return 3
@@ -1430,25 +1427,18 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
14301427 /// the algorithm. For more details on why we lower like this, see [`Builder::test_candidates`].
14311428 ///
14321429 /// 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.
14341431 #[ instrument( skip( self ) , level = "debug" ) ]
14351432 fn match_candidates (
14361433 & mut self ,
14371434 span : Span ,
14381435 scrutinee_span : Span ,
14391436 start_block : BasicBlock ,
1440- otherwise_block : BasicBlock ,
14411437 candidates : & mut [ & mut Candidate < ' _ , ' tcx > ] ,
1442- ) {
1438+ ) -> BasicBlock {
14431439 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+ } )
14521442 }
14531443
14541444 /// Construct the decision tree for `candidates`. Don't call this, call `match_candidates`
@@ -1458,9 +1448,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
14581448 span : Span ,
14591449 scrutinee_span : Span ,
14601450 start_block : BasicBlock ,
1461- otherwise_block : BasicBlock ,
14621451 candidates : & mut [ & mut Candidate < ' _ , ' tcx > ] ,
1463- ) {
1452+ ) -> BasicBlock {
14641453 if let [ first, ..] = candidates {
14651454 if first. false_edge_start_block . is_none ( ) {
14661455 first. false_edge_start_block = Some ( start_block) ;
@@ -1471,9 +1460,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
14711460 let rest = match candidates {
14721461 [ ] => {
14731462 // 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;
14771464 }
14781465 [ first, remaining @ ..] if first. match_pairs . is_empty ( ) => {
14791466 // 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> {
14941481
14951482 // Process any candidates that remain.
14961483 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)
15041485 }
15051486
15061487 /// Link up matched candidates.
@@ -1605,14 +1586,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
16051586 }
16061587
16071588 // 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 (
16121590 span,
16131591 scrutinee_span,
16141592 start_block,
1615- remainder_start,
16161593 expanded_candidates. as_mut_slice ( ) ,
16171594 ) ;
16181595
@@ -1711,6 +1688,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
17111688 self . merge_trivial_subcandidates ( candidate) ;
17121689
17131690 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) ;
17141693 // If more match pairs remain, test them after each subcandidate.
17151694 // We could add them to the or-candidates before the call to `test_or_pattern` but this
17161695 // would make it impossible to detect simplifiable or-patterns. That would guarantee
@@ -1724,6 +1703,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
17241703 assert ! ( leaf_candidate. match_pairs. is_empty( ) ) ;
17251704 leaf_candidate. match_pairs . extend ( remaining_match_pairs. iter ( ) . cloned ( ) ) ;
17261705 let or_start = leaf_candidate. pre_binding_block . unwrap ( ) ;
1706+ let otherwise =
1707+ self . match_candidates ( span, scrutinee_span, or_start, & mut [ leaf_candidate] ) ;
17271708 // In a case like `(P | Q, R | S)`, if `P` succeeds and `R | S` fails, we know `(Q,
17281709 // R | S)` will fail too. If there is no guard, we skip testing of `Q` by branching
17291710 // directly to `last_otherwise`. If there is a guard,
@@ -1734,13 +1715,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
17341715 } else {
17351716 last_otherwise. unwrap ( )
17361717 } ;
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) ;
17441719 } ) ;
17451720 }
17461721 }
@@ -2019,15 +1994,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
20191994 let target_blocks: FxIndexMap < _ , _ > = target_candidates
20201995 . into_iter ( )
20211996 . 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)
20312003 } )
20322004 . collect ( ) ;
20332005
0 commit comments