@@ -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
@@ -689,7 +704,7 @@ pub struct Candidate<'pat, 'tcx: 'pat> {
689704
690705 // ...and the blocks for add false edges between candidates
691706 pre_binding_block : BasicBlock ,
692- next_candidate_pre_binding_block : BasicBlock ,
707+ next_candidate_pre_binding_block : Option < BasicBlock > ,
693708}
694709
695710#[ derive( Clone , Debug ) ]
@@ -956,14 +971,12 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
956971 if let [ first_candidate, second_candidate] = window {
957972 let source_info = self . source_info ( first_candidate. span ) ;
958973 if let Some ( otherwise_block) = first_candidate. otherwise_block {
959- self . cfg . terminate (
974+ self . false_edges (
960975 otherwise_block,
976+ second_candidate. pre_binding_block ,
977+ first_candidate. next_candidate_pre_binding_block ,
961978 source_info,
962- TerminatorKind :: FalseEdges {
963- real_target : second_candidate. pre_binding_block ,
964- imaginary_target : first_candidate. next_candidate_pre_binding_block ,
965- }
966- )
979+ ) ;
967980 } else {
968981 bug ! ( "candidate other than the last has no guard" ) ;
969982 }
@@ -977,13 +990,11 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
977990 if let Some ( otherwise) = candidate. otherwise_block {
978991 let source_info = self . source_info ( candidate. span ) ;
979992 let unreachable = self . cfg . start_new_block ( ) ;
980- self . cfg . terminate (
993+ self . false_edges (
981994 otherwise,
995+ unreachable,
996+ candidate. next_candidate_pre_binding_block ,
982997 source_info,
983- TerminatorKind :: FalseEdges {
984- real_target : unreachable,
985- imaginary_targets : candidate. next_candidate_pre_binding_block ,
986- }
987998 ) ;
988999 self . cfg . terminate ( unreachable, source_info, TerminatorKind :: Unreachable ) ;
9891000 }
@@ -994,13 +1005,11 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
9941005 if let Some ( otherwise) = last_candidate. otherwise_block {
9951006 let source_info = self . source_info ( last_candidate. span ) ;
9961007 let block = self . cfg . start_new_block ( ) ;
997- self . cfg . terminate (
1008+ self . false_edges (
9981009 otherwise,
1010+ block,
1011+ last_candidate. next_candidate_pre_binding_block ,
9991012 source_info,
1000- TerminatorKind :: FalseEdges {
1001- real_target : block,
1002- imaginary_target : last_candidate. next_candidate_pre_binding_block ,
1003- }
10041013 ) ;
10051014 Some ( block)
10061015 } else {
@@ -1311,27 +1320,38 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
13111320 & mut self ,
13121321 candidate : Candidate < ' pat , ' tcx > ,
13131322 guard : Option < Guard < ' tcx > > ,
1314- arm_block : BasicBlock ,
13151323 fake_borrows : & Vec < ( & Place < ' tcx > , Local ) > ,
13161324 scrutinee_span : Span ,
13171325 region_scope : ( region:: Scope , SourceInfo ) ,
13181326 ) {
1327+ ) -> BasicBlock {
13191328 debug ! ( "bind_and_guard_matched_candidate(candidate={:?})" , candidate) ;
13201329
13211330 debug_assert ! ( candidate. match_pairs. is_empty( ) ) ;
13221331
13231332 let candidate_source_info = self . source_info ( candidate. span ) ;
13241333
1325- let mut block = self . cfg . start_new_block ( ) ;
1326- self . cfg . terminate (
1327- candidate. pre_binding_block ,
1334+ let mut block = candidate. pre_binding_block ;
1335+
1336+ // If we are adding our own statements, then we need a fresh block.
1337+ let create_fresh_block = candidate. next_candidate_pre_binding_block . is_some ( )
1338+ || !candidate. bindings . is_empty ( )
1339+ || !candidate. ascriptions . is_empty ( )
1340+ || guard. is_some ( ) ;
1341+
1342+ if create_fresh_block {
1343+ let fresh_block = self . cfg . start_new_block ( ) ;
1344+ self . false_edges (
1345+ block,
1346+ fresh_block,
1347+ candidate. next_candidate_pre_binding_block ,
13281348 candidate_source_info,
1329- TerminatorKind :: FalseEdges {
1330- real_target : block,
1331- imaginary_target : candidate. next_candidate_pre_binding_block ,
1332- } ,
13331349 ) ;
1350+ block = fresh_block;
13341351 self . ascribe_types ( block, & candidate. ascriptions ) ;
1352+ } else {
1353+ return block;
1354+ }
13351355
13361356 // rust-lang/rust#27282: The `autoref` business deserves some
13371357 // explanation here.
@@ -1476,7 +1496,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
14761496 // because that would be before we've checked the result
14771497 // from the guard.
14781498 //
1479- // But binding them on `arm_block` is *too late*, because
1499+ // But binding them on the arm is *too late*, because
14801500 // then all of the candidates for a single arm would be
14811501 // bound in the same place, that would cause a case like:
14821502 //
@@ -1552,22 +1572,14 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
15521572 by_value_bindings,
15531573 ) ;
15541574
1555- self . cfg . terminate (
1556- post_guard_block,
1557- source_info,
1558- TerminatorKind :: Goto { target : arm_block } ,
1559- ) ;
1575+ post_guard_block
15601576 } else {
15611577 assert ! ( candidate. otherwise_block. is_none( ) ) ;
15621578 // (Here, it is not too early to bind the matched
15631579 // candidate on `block`, because there is no guard result
15641580 // that we have to inspect before we bind them.)
15651581 self . bind_matched_candidate_for_arm_body ( block, & candidate. bindings ) ;
1566- self . cfg . terminate (
1567- block,
1568- candidate_source_info,
1569- TerminatorKind :: Goto { target : arm_block } ,
1570- ) ;
1582+ block
15711583 }
15721584 }
15731585
0 commit comments