@@ -143,19 +143,10 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
143143
144144 // create binding start block for link them by false edges
145145 let candidate_count = arms. iter ( ) . map ( |c| c. patterns . len ( ) ) . sum :: < usize > ( ) ;
146- let pre_binding_blocks: Vec < _ > = ( 0 ..= candidate_count)
146+ let pre_binding_blocks: Vec < _ > = ( 0 ..candidate_count)
147147 . map ( |_| self . cfg . start_new_block ( ) )
148148 . collect ( ) ;
149149
150- // There's one more pre_binding block than there are candidates so that
151- // every candidate can have a `next_candidate_pre_binding_block`.
152- let outer_source_info = self . source_info ( span) ;
153- self . cfg . terminate (
154- * pre_binding_blocks. last ( ) . unwrap ( ) ,
155- outer_source_info,
156- TerminatorKind :: Unreachable ,
157- ) ;
158-
159150 let mut match_has_guard = false ;
160151
161152 let mut candidate_pre_binding_blocks = pre_binding_blocks. iter ( ) ;
@@ -171,9 +162,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
171162 let arm_candidates: Vec < _ > = arm. patterns
172163 . iter ( )
173164 . zip ( candidate_pre_binding_blocks. by_ref ( ) )
174- . zip ( next_candidate_pre_binding_blocks. by_ref ( ) )
175165 . map (
176- |( ( pattern, pre_binding_block) , next_candidate_pre_binding_block ) | {
166+ |( pattern, pre_binding_block) | {
177167 Candidate {
178168 span : pattern. span ,
179169 match_pairs : vec ! [
@@ -188,7 +178,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
188178 } ,
189179 pre_binding_block : * pre_binding_block,
190180 next_candidate_pre_binding_block :
191- * next_candidate_pre_binding_block ,
181+ next_candidate_pre_binding_blocks . next ( ) . copied ( ) ,
192182 }
193183 } ,
194184 )
@@ -225,6 +215,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
225215 & mut fake_borrows,
226216 ) ;
227217
218+ let outer_source_info = self . source_info ( span) ;
219+
228220 if !otherwise. is_empty ( ) {
229221 // All matches are exhaustive. However, because some matches
230222 // only have exponentially-large exhaustive decision trees, we
@@ -251,12 +243,11 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
251243 } ;
252244
253245 // Step 5. Create everything else: the guards and the arms.
254-
255- let arm_end_blocks: Vec < _ > = arm_candidates. into_iter ( ) . map ( |( arm, candidates) | {
246+ let arm_end_blocks: Vec < _ > = arm_candidates. into_iter ( ) . map ( |( arm, mut candidates) | {
256247 let arm_source_info = self . source_info ( arm. span ) ;
257248 let region_scope = ( arm. scope , arm_source_info) ;
258249 self . in_scope ( region_scope, arm. lint_level , |this| {
259- let arm_block = this. cfg . start_new_block ( ) ;
250+ let mut arm_block = this. cfg . start_new_block ( ) ;
260251
261252 let body = this. hir . mirror ( arm. body . clone ( ) ) ;
262253 let scope = this. declare_bindings (
@@ -267,6 +258,30 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
267258 Some ( ( Some ( & scrutinee_place) , scrutinee_span) ) ,
268259 ) ;
269260
261+ if candidates. len ( ) == 1 {
262+ arm_block = self . bind_and_guard_matched_candidate (
263+ candidates. pop ( ) . unwrap ( ) ,
264+ arm. guard . clone ( ) ,
265+ & fake_borrow_temps,
266+ scrutinee_span,
267+ ) ;
268+ } else {
269+ arm_block = self . cfg . start_new_block ( ) ;
270+ for candidate in candidates {
271+ let binding_end = self . bind_and_guard_matched_candidate (
272+ candidate,
273+ arm. guard . clone ( ) ,
274+ & fake_borrow_temps,
275+ scrutinee_span,
276+ ) ;
277+ self . cfg . terminate (
278+ binding_end,
279+ source_info,
280+ TerminatorKind :: Goto { target : arm_block } ,
281+ ) ;
282+ }
283+ }
284+
270285 if let Some ( source_scope) = scope {
271286 this. source_scope = source_scope;
272287 }
@@ -434,7 +449,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
434449 // since we don't call `match_candidates`, next fields are unused
435450 otherwise_block : None ,
436451 pre_binding_block : block,
437- next_candidate_pre_binding_block : block ,
452+ next_candidate_pre_binding_block : None ,
438453 } ;
439454
440455 // Simplify the candidate. Since the pattern is irrefutable, this should
@@ -691,7 +706,7 @@ pub struct Candidate<'pat, 'tcx: 'pat> {
691706
692707 // ...and the blocks for add false edges between candidates
693708 pre_binding_block : BasicBlock ,
694- next_candidate_pre_binding_block : BasicBlock ,
709+ next_candidate_pre_binding_block : Option < BasicBlock > ,
695710}
696711
697712#[ derive( Clone , Debug ) ]
@@ -958,14 +973,12 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
958973 if let [ first_candidate, second_candidate] = window {
959974 let source_info = self . source_info ( first_candidate. span ) ;
960975 if let Some ( otherwise_block) = first_candidate. otherwise_block {
961- self . cfg . terminate (
976+ self . false_edges (
962977 otherwise_block,
978+ second_candidate. pre_binding_block ,
979+ first_candidate. next_candidate_pre_binding_block ,
963980 source_info,
964- TerminatorKind :: FalseEdges {
965- real_target : second_candidate. pre_binding_block ,
966- imaginary_target : first_candidate. next_candidate_pre_binding_block ,
967- }
968- )
981+ ) ;
969982 } else {
970983 bug ! ( "candidate other than the last has no guard" ) ;
971984 }
@@ -979,13 +992,11 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
979992 if let Some ( otherwise) = candidate. otherwise_block {
980993 let source_info = self . source_info ( candidate. span ) ;
981994 let unreachable = self . cfg . start_new_block ( ) ;
982- self . cfg . terminate (
995+ self . false_edges (
983996 otherwise,
997+ unreachable,
998+ candidate. next_candidate_pre_binding_block ,
984999 source_info,
985- TerminatorKind :: FalseEdges {
986- real_target : unreachable,
987- imaginary_targets : candidate. next_candidate_pre_binding_block ,
988- }
9891000 ) ;
9901001 self . cfg . terminate ( unreachable, source_info, TerminatorKind :: Unreachable ) ;
9911002 }
@@ -996,13 +1007,11 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
9961007 if let Some ( otherwise) = last_candidate. otherwise_block {
9971008 let source_info = self . source_info ( last_candidate. span ) ;
9981009 let block = self . cfg . start_new_block ( ) ;
999- self . cfg . terminate (
1010+ self . false_edges (
10001011 otherwise,
1012+ block,
1013+ last_candidate. next_candidate_pre_binding_block ,
10011014 source_info,
1002- TerminatorKind :: FalseEdges {
1003- real_target : block,
1004- imaginary_target : last_candidate. next_candidate_pre_binding_block ,
1005- }
10061015 ) ;
10071016 Some ( block)
10081017 } else {
@@ -1313,27 +1322,38 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
13131322 & mut self ,
13141323 candidate : Candidate < ' pat , ' tcx > ,
13151324 guard : Option < Guard < ' tcx > > ,
1316- arm_block : BasicBlock ,
13171325 fake_borrows : & Vec < ( & Place < ' tcx > , Local ) > ,
13181326 scrutinee_span : Span ,
13191327 region_scope : ( region:: Scope , SourceInfo ) ,
13201328 ) {
1329+ ) -> BasicBlock {
13211330 debug ! ( "bind_and_guard_matched_candidate(candidate={:?})" , candidate) ;
13221331
13231332 debug_assert ! ( candidate. match_pairs. is_empty( ) ) ;
13241333
13251334 let candidate_source_info = self . source_info ( candidate. span ) ;
13261335
1327- let mut block = self . cfg . start_new_block ( ) ;
1328- self . cfg . terminate (
1329- candidate. pre_binding_block ,
1336+ let mut block = candidate. pre_binding_block ;
1337+
1338+ // If we are adding our own statements, then we need a fresh block.
1339+ let create_fresh_block = candidate. next_candidate_pre_binding_block . is_some ( )
1340+ || !candidate. bindings . is_empty ( )
1341+ || !candidate. ascriptions . is_empty ( )
1342+ || guard. is_some ( ) ;
1343+
1344+ if create_fresh_block {
1345+ let fresh_block = self . cfg . start_new_block ( ) ;
1346+ self . false_edges (
1347+ block,
1348+ fresh_block,
1349+ candidate. next_candidate_pre_binding_block ,
13301350 candidate_source_info,
1331- TerminatorKind :: FalseEdges {
1332- real_target : block,
1333- imaginary_target : candidate. next_candidate_pre_binding_block ,
1334- } ,
13351351 ) ;
1352+ block = fresh_block;
13361353 self . ascribe_types ( block, & candidate. ascriptions ) ;
1354+ } else {
1355+ return block;
1356+ }
13371357
13381358 // rust-lang/rust#27282: The `autoref` business deserves some
13391359 // explanation here.
@@ -1478,7 +1498,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
14781498 // because that would be before we've checked the result
14791499 // from the guard.
14801500 //
1481- // But binding them on `arm_block` is *too late*, because
1501+ // But binding them on the arm is *too late*, because
14821502 // then all of the candidates for a single arm would be
14831503 // bound in the same place, that would cause a case like:
14841504 //
@@ -1554,22 +1574,14 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
15541574 by_value_bindings,
15551575 ) ;
15561576
1557- self . cfg . terminate (
1558- post_guard_block,
1559- source_info,
1560- TerminatorKind :: Goto { target : arm_block } ,
1561- ) ;
1577+ post_guard_block
15621578 } else {
15631579 assert ! ( candidate. otherwise_block. is_none( ) ) ;
15641580 // (Here, it is not too early to bind the matched
15651581 // candidate on `block`, because there is no guard result
15661582 // that we have to inspect before we bind them.)
15671583 self . bind_matched_candidate_for_arm_body ( block, & candidate. bindings ) ;
1568- self . cfg . terminate (
1569- block,
1570- candidate_source_info,
1571- TerminatorKind :: Goto { target : arm_block } ,
1572- ) ;
1584+ block
15731585 }
15741586 }
15751587
0 commit comments