@@ -142,19 +142,10 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
142142
143143 // create binding start block for link them by false edges
144144 let candidate_count = arms. iter ( ) . map ( |c| c. patterns . len ( ) ) . sum :: < usize > ( ) ;
145- let pre_binding_blocks: Vec < _ > = ( 0 ..= candidate_count)
145+ let pre_binding_blocks: Vec < _ > = ( 0 ..candidate_count)
146146 . map ( |_| self . cfg . start_new_block ( ) )
147147 . collect ( ) ;
148148
149- // There's one more pre_binding block than there are candidates so that
150- // every candidate can have a `next_candidate_pre_binding_block`.
151- let outer_source_info = self . source_info ( span) ;
152- self . cfg . terminate (
153- * pre_binding_blocks. last ( ) . unwrap ( ) ,
154- outer_source_info,
155- TerminatorKind :: Unreachable ,
156- ) ;
157-
158149 let mut match_has_guard = false ;
159150
160151 let mut candidate_pre_binding_blocks = pre_binding_blocks. iter ( ) ;
@@ -170,9 +161,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
170161 let arm_candidates: Vec < _ > = arm. patterns
171162 . iter ( )
172163 . zip ( candidate_pre_binding_blocks. by_ref ( ) )
173- . zip ( next_candidate_pre_binding_blocks. by_ref ( ) )
174164 . map (
175- |( ( pattern, pre_binding_block) , next_candidate_pre_binding_block ) | {
165+ |( pattern, pre_binding_block) | {
176166 Candidate {
177167 span : pattern. span ,
178168 match_pairs : vec ! [
@@ -187,7 +177,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
187177 } ,
188178 pre_binding_block : * pre_binding_block,
189179 next_candidate_pre_binding_block :
190- * next_candidate_pre_binding_block ,
180+ next_candidate_pre_binding_blocks . next ( ) . cloned ( ) ,
191181 }
192182 } ,
193183 )
@@ -224,6 +214,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
224214 & mut fake_borrows,
225215 ) ;
226216
217+ let outer_source_info = self . source_info ( span) ;
218+
227219 if !otherwise. is_empty ( ) {
228220 // All matches are exhaustive. However, because some matches
229221 // only have exponentially-large exhaustive decision trees, we
@@ -250,10 +242,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
250242 } ;
251243
252244 // Step 5. Create everything else: the guards and the arms.
253-
254- let outer_source_info = self . source_info ( span) ;
255- let arm_end_blocks: Vec < _ > = arm_candidates. into_iter ( ) . map ( |( arm, candidates) | {
256- let mut arm_block = self . cfg . start_new_block ( ) ;
245+ let arm_end_blocks: Vec < _ > = arm_candidates. into_iter ( ) . map ( |( arm, mut candidates) | {
257246
258247 let body = self . hir . mirror ( arm. body . clone ( ) ) ;
259248 let scope = self . declare_bindings (
@@ -265,14 +254,29 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
265254 Some ( ( Some ( & scrutinee_place) , scrutinee_span) ) ,
266255 ) ;
267256
257+ let mut arm_block;
258+ if candidates. len ( ) == 1 {
259+ arm_block = self . bind_and_guard_matched_candidate (
260+ candidates. pop ( ) . unwrap ( ) ,
261+ arm. guard . clone ( ) ,
262+ & fake_borrow_temps,
263+ scrutinee_span,
264+ ) ;
265+ } else {
266+ arm_block = self . cfg . start_new_block ( ) ;
268267 for candidate in candidates {
269- self . bind_and_guard_matched_candidate (
268+ let binding_end = self . bind_and_guard_matched_candidate (
270269 candidate,
271270 arm. guard . clone ( ) ,
272- arm_block,
273271 & fake_borrow_temps,
274272 scrutinee_span,
275273 ) ;
274+ self . cfg . terminate (
275+ binding_end,
276+ source_info,
277+ TerminatorKind :: Goto { target : arm_block } ,
278+ ) ;
279+ }
276280 }
277281
278282 if let Some ( source_scope) = scope {
@@ -431,7 +435,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
431435 // since we don't call `match_candidates`, next fields are unused
432436 otherwise_block : None ,
433437 pre_binding_block : block,
434- next_candidate_pre_binding_block : block ,
438+ next_candidate_pre_binding_block : None ,
435439 } ;
436440
437441 // Simplify the candidate. Since the pattern is irrefutable, this should
@@ -701,7 +705,7 @@ pub struct Candidate<'pat, 'tcx: 'pat> {
701705
702706 // ...and the blocks for add false edges between candidates
703707 pre_binding_block : BasicBlock ,
704- next_candidate_pre_binding_block : BasicBlock ,
708+ next_candidate_pre_binding_block : Option < BasicBlock > ,
705709}
706710
707711#[ derive( Clone , Debug ) ]
@@ -968,14 +972,12 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
968972 if let [ first_candidate, second_candidate] = window {
969973 let source_info = self . source_info ( first_candidate. span ) ;
970974 if let Some ( otherwise_block) = first_candidate. otherwise_block {
971- self . cfg . terminate (
975+ self . false_edges (
972976 otherwise_block,
977+ second_candidate. pre_binding_block ,
978+ first_candidate. next_candidate_pre_binding_block ,
973979 source_info,
974- TerminatorKind :: FalseEdges {
975- real_target : second_candidate. pre_binding_block ,
976- imaginary_target : first_candidate. next_candidate_pre_binding_block ,
977- }
978- )
980+ ) ;
979981 } else {
980982 bug ! ( "candidate other than the last has no guard" ) ;
981983 }
@@ -989,13 +991,11 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
989991 if let Some ( otherwise) = candidate. otherwise_block {
990992 let source_info = self . source_info ( candidate. span ) ;
991993 let unreachable = self . cfg . start_new_block ( ) ;
992- self . cfg . terminate (
994+ self . false_edges (
993995 otherwise,
996+ unreachable,
997+ candidate. next_candidate_pre_binding_block ,
994998 source_info,
995- TerminatorKind :: FalseEdges {
996- real_target : unreachable,
997- imaginary_targets : candidate. next_candidate_pre_binding_block ,
998- }
999999 ) ;
10001000 self . cfg . terminate ( unreachable, source_info, TerminatorKind :: Unreachable ) ;
10011001 }
@@ -1006,13 +1006,11 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
10061006 if let Some ( otherwise) = last_candidate. otherwise_block {
10071007 let source_info = self . source_info ( last_candidate. span ) ;
10081008 let block = self . cfg . start_new_block ( ) ;
1009- self . cfg . terminate (
1009+ self . false_edges (
10101010 otherwise,
1011+ block,
1012+ last_candidate. next_candidate_pre_binding_block ,
10111013 source_info,
1012- TerminatorKind :: FalseEdges {
1013- real_target : block,
1014- imaginary_target : last_candidate. next_candidate_pre_binding_block ,
1015- }
10161014 ) ;
10171015 Some ( block)
10181016 } else {
@@ -1323,26 +1321,36 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
13231321 & mut self ,
13241322 candidate : Candidate < ' pat , ' tcx > ,
13251323 guard : Option < Guard < ' tcx > > ,
1326- arm_block : BasicBlock ,
13271324 fake_borrows : & Vec < ( & Place < ' tcx > , Local ) > ,
13281325 scrutinee_span : Span ,
1329- ) {
1326+ ) -> BasicBlock {
13301327 debug ! ( "bind_and_guard_matched_candidate(candidate={:?})" , candidate) ;
13311328
13321329 debug_assert ! ( candidate. match_pairs. is_empty( ) ) ;
13331330
13341331 let candidate_source_info = self . source_info ( candidate. span ) ;
13351332
1336- let mut block = self . cfg . start_new_block ( ) ;
1337- self . cfg . terminate (
1338- candidate. pre_binding_block ,
1333+ let mut block = candidate. pre_binding_block ;
1334+
1335+ // If we are adding our own statements, then we need a fresh block.
1336+ let create_fresh_block = candidate. next_candidate_pre_binding_block . is_some ( )
1337+ || !candidate. bindings . is_empty ( )
1338+ || !candidate. ascriptions . is_empty ( )
1339+ || guard. is_some ( ) ;
1340+
1341+ if create_fresh_block {
1342+ let fresh_block = self . cfg . start_new_block ( ) ;
1343+ self . false_edges (
1344+ block,
1345+ fresh_block,
1346+ candidate. next_candidate_pre_binding_block ,
13391347 candidate_source_info,
1340- TerminatorKind :: FalseEdges {
1341- real_target : block,
1342- imaginary_target : candidate. next_candidate_pre_binding_block ,
1343- } ,
13441348 ) ;
1349+ block = fresh_block;
13451350 self . ascribe_types ( block, & candidate. ascriptions ) ;
1351+ } else {
1352+ return block;
1353+ }
13461354
13471355 // rust-lang/rust#27282: The `autoref` business deserves some
13481356 // explanation here.
@@ -1487,7 +1495,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
14871495 // because that would be before we've checked the result
14881496 // from the guard.
14891497 //
1490- // But binding them on `arm_block` is *too late*, because
1498+ // But binding them on the arm is *too late*, because
14911499 // then all of the candidates for a single arm would be
14921500 // bound in the same place, that would cause a case like:
14931501 //
@@ -1540,22 +1548,14 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
15401548 by_value_bindings,
15411549 ) ;
15421550
1543- self . cfg . terminate (
1544- post_guard_block,
1545- source_info,
1546- TerminatorKind :: Goto { target : arm_block } ,
1547- ) ;
1551+ post_guard_block
15481552 } else {
15491553 assert ! ( candidate. otherwise_block. is_none( ) ) ;
15501554 // (Here, it is not too early to bind the matched
15511555 // candidate on `block`, because there is no guard result
15521556 // that we have to inspect before we bind them.)
15531557 self . bind_matched_candidate_for_arm_body ( block, & candidate. bindings ) ;
1554- self . cfg . terminate (
1555- block,
1556- candidate_source_info,
1557- TerminatorKind :: Goto { target : arm_block } ,
1558- ) ;
1558+ block
15591559 }
15601560 }
15611561
0 commit comments