@@ -1313,11 +1313,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
13131313candidates : & mut [ & mut Candidate < ' pat , ' tcx > ] ,
13141314refutable : 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.
13231322let 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" ) ]
14351432fn match_candidates (
14361433& mut self ,
14371434span : Span ,
14381435scrutinee_span : Span ,
14391436start_block : BasicBlock ,
1440- otherwise_block : BasicBlock ,
14411437candidates : & mut [ & mut Candidate < ' _ , ' tcx > ] ,
1442- ) {
1438+ ) -> BasicBlock {
14431439ensure_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> {
14581448span : Span ,
14591449scrutinee_span : Span ,
14601450start_block : BasicBlock ,
1461- otherwise_block : BasicBlock ,
14621451candidates : & mut [ & mut Candidate < ' _ , ' tcx > ] ,
1463- ) {
1452+ ) -> BasicBlock {
14641453if let [ first, ..] = candidates {
14651454if 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> {
14711460let 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.
14961483let 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> {
17111688self . merge_trivial_subcandidates ( candidate) ;
17121689
17131690if !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> {
17241703assert ! ( leaf_candidate. match_pairs. is_empty( ) ) ;
17251704 leaf_candidate. match_pairs . extend ( remaining_match_pairs. iter ( ) . cloned ( ) ) ;
17261705let 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> {
20191994let 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