@@ -1250,11 +1250,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
12501250 candidates : & mut [ & mut Candidate < ' pat , ' tcx > ] ,
12511251 refutable : bool ,
12521252 ) -> BasicBlock {
1253+ // This will generate code to test scrutinee_place and branch to the appropriate arm block.
12531254 // See the doc comment on `match_candidates` for why we have an otherwise block.
1254- let otherwise_block = self . cfg . start_new_block ( ) ;
1255-
1256- // This will generate code to test scrutinee_place and branch to the appropriate arm block
1257- self . match_candidates ( match_start_span, scrutinee_span, block, otherwise_block, candidates) ;
1255+ let otherwise_block =
1256+ self . match_candidates ( match_start_span, scrutinee_span, block, candidates) ;
12581257
12591258 // Link each leaf candidate to the `false_edge_start_block` of the next one.
12601259 let mut previous_candidate: Option < & mut Candidate < ' _ , ' _ > > = None ;
@@ -1305,27 +1304,24 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
13051304 otherwise_block
13061305 }
13071306
1308- /// The main match algorithm. It begins with a set of candidates
1309- /// `candidates` and has the job of generating code to determine
1310- /// which of these candidates, if any, is the correct one . The
1307+ /// The main match algorithm. It begins with a set of candidates `candidates` and has the job of
1308+ /// generating code that branches to an appropriate block if the scrutinee matches one of these
1309+ /// candidates. The
13111310 /// candidates are sorted such that the first item in the list
13121311 /// has the highest priority. When a candidate is found to match
13131312 /// the value, we will set and generate a branch to the appropriate
13141313 /// pre-binding block.
13151314 ///
1316- /// If we find that *NONE* of the candidates apply, we branch to `otherwise_block`.
1315+ /// If none of the candidates apply, we continue to the returned `otherwise_block`.
13171316 ///
13181317 /// It might be surprising that the input can be non-exhaustive.
1319- /// Indeed, initially, it is not, because all matches are
1318+ /// Indeed, for matches, initially, it is not, because all matches are
13201319 /// exhaustive in Rust. But during processing we sometimes divide
13211320 /// up the list of candidates and recurse with a non-exhaustive
13221321 /// list. This is how our lowering approach (called "backtracking
13231322 /// automaton" in the literature) works.
13241323 /// See [`Builder::test_candidates`] for more details.
13251324 ///
1326- /// If `fake_borrows` is `Some`, then places which need fake borrows
1327- /// will be added to it.
1328- ///
13291325 /// For an example of how we use `otherwise_block`, consider:
13301326 /// ```
13311327 /// # fn foo((x, y): (bool, bool)) -> u32 {
@@ -1350,7 +1346,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
13501346 /// }
13511347 /// if y {
13521348 /// if x {
1353- /// // This is actually unreachable because the `(true, true)` case was handled above.
1349+ /// // This is actually unreachable because the `(true, true)` case was handled above,
1350+ /// // but we don't know that from within the lowering algorithm.
13541351 /// // continue
13551352 /// } else {
13561353 /// return 3
@@ -1359,33 +1356,26 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
13591356 /// return 2
13601357 /// }
13611358 /// // this is the final `otherwise_block`, which is unreachable because the match was exhaustive.
1362- /// unreachable! ()
1359+ /// unreachable_unchecked ()
13631360 /// # }
13641361 /// ```
13651362 ///
13661363 /// Every `continue` is an instance of branching to some `otherwise_block` somewhere deep within
13671364 /// the algorithm. For more details on why we lower like this, see [`Builder::test_candidates`].
13681365 ///
13691366 /// Note how we test `x` twice. This is the tradeoff of backtracking automata: we prefer smaller
1370- /// code size at the expense of non-optimal code paths.
1367+ /// code size so we accept non-optimal code paths.
13711368 #[ instrument( skip( self ) , level = "debug" ) ]
13721369 fn match_candidates (
13731370 & mut self ,
13741371 span : Span ,
13751372 scrutinee_span : Span ,
13761373 start_block : BasicBlock ,
1377- otherwise_block : BasicBlock ,
13781374 candidates : & mut [ & mut Candidate < ' _ , ' tcx > ] ,
1379- ) {
1375+ ) -> BasicBlock {
13801376 ensure_sufficient_stack ( || {
1381- self . match_candidates_with_enough_stack (
1382- span,
1383- scrutinee_span,
1384- start_block,
1385- otherwise_block,
1386- candidates,
1387- )
1388- } ) ;
1377+ self . match_candidates_with_enough_stack ( span, scrutinee_span, start_block, candidates)
1378+ } )
13891379 }
13901380
13911381 /// Construct the decision tree for `candidates`. Don't call this, call `match_candidates`
@@ -1395,9 +1385,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
13951385 span : Span ,
13961386 scrutinee_span : Span ,
13971387 start_block : BasicBlock ,
1398- otherwise_block : BasicBlock ,
13991388 candidates : & mut [ & mut Candidate < ' _ , ' tcx > ] ,
1400- ) {
1389+ ) -> BasicBlock {
14011390 if let [ first, ..] = candidates {
14021391 if first. false_edge_start_block . is_none ( ) {
14031392 first. false_edge_start_block = Some ( start_block) ;
@@ -1408,9 +1397,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
14081397 let rest = match candidates {
14091398 [ ] => {
14101399 // If there are no candidates that still need testing, we're done.
1411- let source_info = self . source_info ( span) ;
1412- self . cfg . goto ( start_block, source_info, otherwise_block) ;
1413- return ;
1400+ return start_block;
14141401 }
14151402 [ first, remaining @ ..] if first. match_pairs . is_empty ( ) => {
14161403 // The first candidate has satisfied all its match pairs; we link it up and continue
@@ -1431,13 +1418,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
14311418
14321419 // Process any candidates that remain.
14331420 let BlockAnd ( start_block, remaining_candidates) = rest;
1434- self . match_candidates (
1435- span,
1436- scrutinee_span,
1437- start_block,
1438- otherwise_block,
1439- remaining_candidates,
1440- ) ;
1421+ self . match_candidates ( span, scrutinee_span, start_block, remaining_candidates)
14411422 }
14421423
14431424 /// Link up matched candidates.
@@ -1542,14 +1523,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
15421523 }
15431524
15441525 // Process the expanded candidates.
1545- let remainder_start = self . cfg . start_new_block ( ) ;
1546- // There might be new or-patterns obtained from expanding the old ones, so we call
1547- // `match_candidates` again.
1548- self . match_candidates (
1526+ let remainder_start = self . match_candidates (
15491527 span,
15501528 scrutinee_span,
15511529 start_block,
1552- remainder_start,
15531530 expanded_candidates. as_mut_slice ( ) ,
15541531 ) ;
15551532
@@ -1648,6 +1625,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
16481625 self . merge_trivial_subcandidates ( candidate) ;
16491626
16501627 if !candidate. match_pairs . is_empty ( ) {
1628+ let or_span = candidate. or_span . unwrap_or ( candidate. extra_data . span ) ;
1629+ let source_info = self . source_info ( or_span) ;
16511630 // If more match pairs remain, test them after each subcandidate.
16521631 // We could add them to the or-candidates before the call to `test_or_pattern` but this
16531632 // would make it impossible to detect simplifiable or-patterns. That would guarantee
@@ -1661,6 +1640,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
16611640 assert ! ( leaf_candidate. match_pairs. is_empty( ) ) ;
16621641 leaf_candidate. match_pairs . extend ( remaining_match_pairs. iter ( ) . cloned ( ) ) ;
16631642 let or_start = leaf_candidate. pre_binding_block . unwrap ( ) ;
1643+ let otherwise =
1644+ self . match_candidates ( span, scrutinee_span, or_start, & mut [ leaf_candidate] ) ;
16641645 // In a case like `(P | Q, R | S)`, if `P` succeeds and `R | S` fails, we know `(Q,
16651646 // R | S)` will fail too. If there is no guard, we skip testing of `Q` by branching
16661647 // directly to `last_otherwise`. If there is a guard,
@@ -1671,13 +1652,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
16711652 } else {
16721653 last_otherwise. unwrap ( )
16731654 } ;
1674- self . match_candidates (
1675- span,
1676- scrutinee_span,
1677- or_start,
1678- or_otherwise,
1679- & mut [ leaf_candidate] ,
1680- ) ;
1655+ self . cfg . goto ( otherwise, source_info, or_otherwise) ;
16811656 } ) ;
16821657 }
16831658 }
@@ -1956,15 +1931,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
19561931 let target_blocks: FxIndexMap < _ , _ > = target_candidates
19571932 . into_iter ( )
19581933 . map ( |( branch, mut candidates) | {
1959- let candidate_start = self . cfg . start_new_block ( ) ;
1960- self . match_candidates (
1961- span,
1962- scrutinee_span,
1963- candidate_start,
1964- remainder_start,
1965- & mut * candidates,
1966- ) ;
1967- ( branch, candidate_start)
1934+ let branch_start = self . cfg . start_new_block ( ) ;
1935+ let branch_otherwise =
1936+ self . match_candidates ( span, scrutinee_span, branch_start, & mut * candidates) ;
1937+ let source_info = self . source_info ( span) ;
1938+ self . cfg . goto ( branch_otherwise, source_info, remainder_start) ;
1939+ ( branch, branch_start)
19681940 } )
19691941 . collect ( ) ;
19701942
0 commit comments