@@ -34,10 +34,11 @@ impl<H:Hair> Builder<H> {
34
34
let discriminant_lvalue =
35
35
unpack ! ( block = self . as_lvalue( block, discriminant) ) ;
36
36
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
+ } ;
41
42
42
43
let arm_bodies: Vec < ExprRef < H > > =
43
44
arms. iter ( )
@@ -52,34 +53,34 @@ impl<H:Hair> Builder<H> {
52
53
// source.
53
54
let candidates: Vec < Candidate < H > > =
54
55
arms. into_iter ( )
55
- . zip ( arm_blocks . iter ( ) )
56
+ . enumerate ( )
56
57
. rev ( ) // highest priority comes last
57
- . flat_map ( |( arm , & arm_block ) | {
58
+ . flat_map ( |( arm_index , arm ) | {
58
59
let guard = arm. guard ;
59
60
arm. patterns . into_iter ( )
60
61
. rev ( )
61
- . map ( move |pat| ( arm_block , pat, guard. clone ( ) ) )
62
+ . map ( move |pat| ( arm_index , pat, guard. clone ( ) ) )
62
63
} )
63
- . map ( |( arm_block , pattern, guard) | {
64
+ . map ( |( arm_index , pattern, guard) | {
64
65
Candidate {
65
66
match_pairs : vec ! [ self . match_pair( discriminant_lvalue. clone( ) , pattern) ] ,
66
67
bindings : vec ! [ ] ,
67
68
guard : guard,
68
- arm_block : arm_block ,
69
+ arm_index : arm_index ,
69
70
}
70
71
} )
71
72
. collect ( ) ;
72
73
73
74
// this will generate code to test discriminant_lvalue and
74
75
// branch to the appropriate arm block
75
76
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) ;
77
78
78
79
// all the arm blocks will rejoin here
79
80
let end_block = self . cfg . start_new_block ( ) ;
80
81
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 ] ;
83
84
unpack ! ( arm_block = self . into( destination, arm_block, arm_body) ) ;
84
85
self . cfg . terminate ( arm_block, Terminator :: Goto { target : end_block } ) ;
85
86
}
@@ -127,7 +128,7 @@ impl<H:Hair> Builder<H> {
127
128
match_pairs : vec ! [ self . match_pair( initializer. clone( ) , irrefutable_pat) ] ,
128
129
bindings : vec ! [ ] ,
129
130
guard : None ,
130
- arm_block : block
131
+ arm_index : 0 , // since we don't call `match_candidates`, this field is unused
131
132
} ;
132
133
133
134
// Simplify the candidate. Since the pattern is irrefutable, this should
@@ -180,6 +181,12 @@ impl<H:Hair> Builder<H> {
180
181
}
181
182
}
182
183
184
+ /// List of blocks for each arm (and potentially other metadata in the
185
+ /// future).
186
+ struct ArmBlocks {
187
+ blocks : Vec < BasicBlock > ,
188
+ }
189
+
183
190
#[ derive( Clone , Debug ) ]
184
191
struct Candidate < H : Hair > {
185
192
// all of these must be satisfied...
@@ -191,8 +198,8 @@ struct Candidate<H:Hair> {
191
198
// ...and the guard must be evaluated...
192
199
guard : Option < ExprRef < H > > ,
193
200
194
- // ...and then we branch here .
195
- arm_block : BasicBlock ,
201
+ // ...and then we branch to arm with this index .
202
+ arm_index : usize ,
196
203
}
197
204
198
205
#[ derive( Clone , Debug ) ]
@@ -243,6 +250,7 @@ impl<H:Hair> Builder<H> {
243
250
fn match_candidates ( & mut self ,
244
251
span : H :: Span ,
245
252
var_extent : H :: CodeExtent ,
253
+ arm_blocks : & mut ArmBlocks ,
246
254
mut candidates : Vec < Candidate < H > > ,
247
255
mut block : BasicBlock )
248
256
{
@@ -267,7 +275,8 @@ impl<H:Hair> Builder<H> {
267
275
// If so, apply any bindings, test the guard (if any), and
268
276
// branch to the arm.
269
277
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) {
271
280
block = b;
272
281
} else {
273
282
// if None is returned, then any remaining candidates
@@ -300,7 +309,7 @@ impl<H:Hair> Builder<H> {
300
309
candidate) )
301
310
} )
302
311
. 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) ;
304
313
}
305
314
}
306
315
@@ -319,6 +328,7 @@ impl<H:Hair> Builder<H> {
319
328
fn bind_and_guard_matched_candidate ( & mut self ,
320
329
mut block : BasicBlock ,
321
330
var_extent : H :: CodeExtent ,
331
+ arm_blocks : & mut ArmBlocks ,
322
332
candidate : Candidate < H > )
323
333
-> Option < BasicBlock > {
324
334
debug ! ( "bind_and_guard_matched_candidate(block={:?}, var_extent={:?}, candidate={:?})" ,
@@ -328,16 +338,18 @@ impl<H:Hair> Builder<H> {
328
338
329
339
self . bind_matched_candidate ( block, var_extent, candidate. bindings ) ;
330
340
341
+ let arm_block = arm_blocks. blocks [ candidate. arm_index ] ;
342
+
331
343
if let Some ( guard) = candidate. guard {
332
344
// the block to branch to if the guard fails; if there is no
333
345
// guard, this block is simply unreachable
334
346
let cond = unpack ! ( block = self . as_operand( block, guard) ) ;
335
347
let otherwise = self . cfg . start_new_block ( ) ;
336
348
self . cfg . terminate ( block, Terminator :: If { cond : cond,
337
- targets : [ candidate . arm_block , otherwise] } ) ;
349
+ targets : [ arm_block, otherwise] } ) ;
338
350
Some ( otherwise)
339
351
} else {
340
- self . cfg . terminate ( block, Terminator :: Goto { target : candidate . arm_block } ) ;
352
+ self . cfg . terminate ( block, Terminator :: Goto { target : arm_block } ) ;
341
353
None
342
354
}
343
355
}
0 commit comments