@@ -34,10 +34,11 @@ impl<H:Hair> Builder<H> {
3434 let discriminant_lvalue =
3535 unpack ! ( block = self . as_lvalue( block, discriminant) ) ;
3636
37- let arm_blocks: Vec < BasicBlock > =
38- arms. iter ( )
39- . map ( |_| self . cfg . start_new_block ( ) )
40- . collect ( ) ;
37+ let mut arm_blocks = ArmBlocks {
38+ blocks : arms. iter ( )
39+ . map ( |_| self . cfg . start_new_block ( ) )
40+ . collect ( ) ,
41+ } ;
4142
4243 let arm_bodies: Vec < ExprRef < H > > =
4344 arms. iter ( )
@@ -52,34 +53,34 @@ impl<H:Hair> Builder<H> {
5253 // source.
5354 let candidates: Vec < Candidate < H > > =
5455 arms. into_iter ( )
55- . zip ( arm_blocks . iter ( ) )
56+ . enumerate ( )
5657 . rev ( ) // highest priority comes last
57- . flat_map ( |( arm , & arm_block ) | {
58+ . flat_map ( |( arm_index , arm ) | {
5859 let guard = arm. guard ;
5960 arm. patterns . into_iter ( )
6061 . rev ( )
61- . map ( move |pat| ( arm_block , pat, guard. clone ( ) ) )
62+ . map ( move |pat| ( arm_index , pat, guard. clone ( ) ) )
6263 } )
63- . map ( |( arm_block , pattern, guard) | {
64+ . map ( |( arm_index , pattern, guard) | {
6465 Candidate {
6566 match_pairs : vec ! [ self . match_pair( discriminant_lvalue. clone( ) , pattern) ] ,
6667 bindings : vec ! [ ] ,
6768 guard : guard,
68- arm_block : arm_block ,
69+ arm_index : arm_index ,
6970 }
7071 } )
7172 . collect ( ) ;
7273
7374 // this will generate code to test discriminant_lvalue and
7475 // branch to the appropriate arm block
7576 let var_extent = self . extent_of_innermost_scope ( ) . unwrap ( ) ;
76- self . match_candidates ( span, var_extent, candidates, block) ;
77+ self . match_candidates ( span, var_extent, & mut arm_blocks , candidates, block) ;
7778
7879 // all the arm blocks will rejoin here
7980 let end_block = self . cfg . start_new_block ( ) ;
8081
81- for ( arm_body , & arm_block ) in arm_bodies. into_iter ( ) . zip ( arm_blocks . iter ( ) ) {
82- let mut arm_block = arm_block ;
82+ for ( arm_index , arm_body ) in arm_bodies. into_iter ( ) . enumerate ( ) {
83+ let mut arm_block = arm_blocks . blocks [ arm_index ] ;
8384 unpack ! ( arm_block = self . into( destination, arm_block, arm_body) ) ;
8485 self . cfg . terminate ( arm_block, Terminator :: Goto { target : end_block } ) ;
8586 }
@@ -127,7 +128,7 @@ impl<H:Hair> Builder<H> {
127128 match_pairs : vec ! [ self . match_pair( initializer. clone( ) , irrefutable_pat) ] ,
128129 bindings : vec ! [ ] ,
129130 guard : None ,
130- arm_block : block
131+ arm_index : 0 , // since we don't call `match_candidates`, this field is unused
131132 } ;
132133
133134 // Simplify the candidate. Since the pattern is irrefutable, this should
@@ -180,6 +181,12 @@ impl<H:Hair> Builder<H> {
180181 }
181182}
182183
184+ /// List of blocks for each arm (and potentially other metadata in the
185+ /// future).
186+ struct ArmBlocks {
187+ blocks : Vec < BasicBlock > ,
188+ }
189+
183190#[ derive( Clone , Debug ) ]
184191struct Candidate < H : Hair > {
185192 // all of these must be satisfied...
@@ -191,8 +198,8 @@ struct Candidate<H:Hair> {
191198 // ...and the guard must be evaluated...
192199 guard : Option < ExprRef < H > > ,
193200
194- // ...and then we branch here .
195- arm_block : BasicBlock ,
201+ // ...and then we branch to arm with this index .
202+ arm_index : usize ,
196203}
197204
198205#[ derive( Clone , Debug ) ]
@@ -243,6 +250,7 @@ impl<H:Hair> Builder<H> {
243250 fn match_candidates ( & mut self ,
244251 span : H :: Span ,
245252 var_extent : H :: CodeExtent ,
253+ arm_blocks : & mut ArmBlocks ,
246254 mut candidates : Vec < Candidate < H > > ,
247255 mut block : BasicBlock )
248256 {
@@ -267,7 +275,8 @@ impl<H:Hair> Builder<H> {
267275 // If so, apply any bindings, test the guard (if any), and
268276 // branch to the arm.
269277 let candidate = candidates. pop ( ) . unwrap ( ) ;
270- if let Some ( b) = self . bind_and_guard_matched_candidate ( block, var_extent, candidate) {
278+ if let Some ( b) = self . bind_and_guard_matched_candidate ( block, var_extent,
279+ arm_blocks, candidate) {
271280 block = b;
272281 } else {
273282 // if None is returned, then any remaining candidates
@@ -300,7 +309,7 @@ impl<H:Hair> Builder<H> {
300309 candidate) )
301310 } )
302311 . collect ( ) ;
303- self . match_candidates ( span, var_extent, applicable_candidates, target_block) ;
312+ self . match_candidates ( span, var_extent, arm_blocks , applicable_candidates, target_block) ;
304313 }
305314 }
306315
@@ -319,6 +328,7 @@ impl<H:Hair> Builder<H> {
319328 fn bind_and_guard_matched_candidate ( & mut self ,
320329 mut block : BasicBlock ,
321330 var_extent : H :: CodeExtent ,
331+ arm_blocks : & mut ArmBlocks ,
322332 candidate : Candidate < H > )
323333 -> Option < BasicBlock > {
324334 debug ! ( "bind_and_guard_matched_candidate(block={:?}, var_extent={:?}, candidate={:?})" ,
@@ -328,16 +338,18 @@ impl<H:Hair> Builder<H> {
328338
329339 self . bind_matched_candidate ( block, var_extent, candidate. bindings ) ;
330340
341+ let arm_block = arm_blocks. blocks [ candidate. arm_index ] ;
342+
331343 if let Some ( guard) = candidate. guard {
332344 // the block to branch to if the guard fails; if there is no
333345 // guard, this block is simply unreachable
334346 let cond = unpack ! ( block = self . as_operand( block, guard) ) ;
335347 let otherwise = self . cfg . start_new_block ( ) ;
336348 self . cfg . terminate ( block, Terminator :: If { cond : cond,
337- targets : [ candidate . arm_block , otherwise] } ) ;
349+ targets : [ arm_block, otherwise] } ) ;
338350 Some ( otherwise)
339351 } else {
340- self . cfg . terminate ( block, Terminator :: Goto { target : candidate . arm_block } ) ;
352+ self . cfg . terminate ( block, Terminator :: Goto { target : arm_block } ) ;
341353 None
342354 }
343355 }
0 commit comments