@@ -34,6 +34,15 @@ impl<H:Hair> Builder<H> {
34
34
let discriminant_lvalue =
35
35
unpack ! ( block = self . as_lvalue( block, discriminant) ) ;
36
36
37
+ // Before we do anything, create uninitialized variables with
38
+ // suitable extent for all of the bindings in this match. It's
39
+ // easiest to do this up front because some of these arms may
40
+ // be unreachable or reachable multiple times.
41
+ let var_extent = self . extent_of_innermost_scope ( ) . unwrap ( ) ;
42
+ for arm in & arms {
43
+ self . declare_bindings ( var_extent, arm. patterns [ 0 ] . clone ( ) ) ;
44
+ }
45
+
37
46
let mut arm_blocks = ArmBlocks {
38
47
blocks : arms. iter ( )
39
48
. map ( |_| self . cfg . start_new_block ( ) )
@@ -52,14 +61,13 @@ impl<H:Hair> Builder<H> {
52
61
// reverse of the order in which candidates are written in the
53
62
// source.
54
63
let candidates: Vec < Candidate < H > > =
55
- arms. into_iter ( )
64
+ arms. iter ( )
56
65
. enumerate ( )
57
66
. rev ( ) // highest priority comes last
58
67
. flat_map ( |( arm_index, arm) | {
59
- let guard = arm. guard ;
60
- arm. patterns . into_iter ( )
68
+ arm. patterns . iter ( )
61
69
. rev ( )
62
- . map ( move |pat| ( arm_index, pat, guard. clone ( ) ) )
70
+ . map ( move |pat| ( arm_index, pat. clone ( ) , arm . guard . clone ( ) ) )
63
71
} )
64
72
. map ( |( arm_index, pattern, guard) | {
65
73
Candidate {
@@ -73,8 +81,7 @@ impl<H:Hair> Builder<H> {
73
81
74
82
// this will generate code to test discriminant_lvalue and
75
83
// branch to the appropriate arm block
76
- let var_extent = self . extent_of_innermost_scope ( ) . unwrap ( ) ;
77
- self . match_candidates ( span, var_extent, & mut arm_blocks, candidates, block) ;
84
+ self . match_candidates ( span, & mut arm_blocks, candidates, block) ;
78
85
79
86
// all the arm blocks will rejoin here
80
87
let end_block = self . cfg . start_new_block ( ) ;
@@ -123,9 +130,12 @@ impl<H:Hair> Builder<H> {
123
130
initializer : & Lvalue < H > )
124
131
-> BlockAnd < ( ) >
125
132
{
133
+ // first, creating the bindings
134
+ self . declare_bindings ( var_extent, irrefutable_pat. clone ( ) ) ;
135
+
126
136
// create a dummy candidate
127
137
let mut candidate = Candidate :: < H > {
128
- match_pairs : vec ! [ self . match_pair( initializer. clone( ) , irrefutable_pat) ] ,
138
+ match_pairs : vec ! [ self . match_pair( initializer. clone( ) , irrefutable_pat. clone ( ) ) ] ,
129
139
bindings : vec ! [ ] ,
130
140
guard : None ,
131
141
arm_index : 0 , // since we don't call `match_candidates`, this field is unused
@@ -143,38 +153,38 @@ impl<H:Hair> Builder<H> {
143
153
}
144
154
145
155
// now apply the bindings, which will also declare the variables
146
- self . bind_matched_candidate ( block, var_extent , candidate. bindings ) ;
156
+ self . bind_matched_candidate ( block, candidate. bindings ) ;
147
157
148
158
block. unit ( )
149
159
}
150
160
151
- pub fn declare_uninitialized_variables ( & mut self ,
152
- var_extent : H :: CodeExtent ,
153
- pattern : PatternRef < H > )
161
+ pub fn declare_bindings ( & mut self ,
162
+ var_extent : H :: CodeExtent ,
163
+ pattern : PatternRef < H > )
154
164
{
155
165
let pattern = self . hir . mirror ( pattern) ;
156
166
match pattern. kind {
157
167
PatternKind :: Binding { mutability, name, mode : _, var, ty, subpattern } => {
158
168
self . declare_binding ( var_extent, mutability, name, var, ty, pattern. span ) ;
159
169
if let Some ( subpattern) = subpattern {
160
- self . declare_uninitialized_variables ( var_extent, subpattern) ;
170
+ self . declare_bindings ( var_extent, subpattern) ;
161
171
}
162
172
}
163
173
PatternKind :: Array { prefix, slice, suffix } |
164
174
PatternKind :: Slice { prefix, slice, suffix } => {
165
175
for subpattern in prefix. into_iter ( ) . chain ( slice) . chain ( suffix) {
166
- self . declare_uninitialized_variables ( var_extent, subpattern) ;
176
+ self . declare_bindings ( var_extent, subpattern) ;
167
177
}
168
178
}
169
179
PatternKind :: Constant { .. } | PatternKind :: Range { .. } | PatternKind :: Wild => {
170
180
}
171
181
PatternKind :: Deref { subpattern } => {
172
- self . declare_uninitialized_variables ( var_extent, subpattern) ;
182
+ self . declare_bindings ( var_extent, subpattern) ;
173
183
}
174
184
PatternKind :: Leaf { subpatterns } |
175
185
PatternKind :: Variant { subpatterns, .. } => {
176
186
for subpattern in subpatterns {
177
- self . declare_uninitialized_variables ( var_extent, subpattern. pattern ) ;
187
+ self . declare_bindings ( var_extent, subpattern. pattern ) ;
178
188
}
179
189
}
180
190
}
@@ -249,13 +259,12 @@ struct Test<H:Hair> {
249
259
impl < H : Hair > Builder < H > {
250
260
fn match_candidates ( & mut self ,
251
261
span : H :: Span ,
252
- var_extent : H :: CodeExtent ,
253
262
arm_blocks : & mut ArmBlocks ,
254
263
mut candidates : Vec < Candidate < H > > ,
255
264
mut block : BasicBlock )
256
265
{
257
- debug ! ( "matched_candidate(span={:?}, var_extent={:?}, block={:?}, candidates={:?})" ,
258
- span, var_extent , block, candidates) ;
266
+ debug ! ( "matched_candidate(span={:?}, block={:?}, candidates={:?})" ,
267
+ span, block, candidates) ;
259
268
260
269
// Start by simplifying candidates. Once this process is
261
270
// complete, all the match pairs which remain require some
@@ -275,8 +284,7 @@ impl<H:Hair> Builder<H> {
275
284
// If so, apply any bindings, test the guard (if any), and
276
285
// branch to the arm.
277
286
let candidate = candidates. pop ( ) . unwrap ( ) ;
278
- if let Some ( b) = self . bind_and_guard_matched_candidate ( block, var_extent,
279
- arm_blocks, candidate) {
287
+ if let Some ( b) = self . bind_and_guard_matched_candidate ( block, arm_blocks, candidate) {
280
288
block = b;
281
289
} else {
282
290
// if None is returned, then any remaining candidates
@@ -309,7 +317,7 @@ impl<H:Hair> Builder<H> {
309
317
candidate) )
310
318
} )
311
319
. collect ( ) ;
312
- self . match_candidates ( span, var_extent , arm_blocks, applicable_candidates, target_block) ;
320
+ self . match_candidates ( span, arm_blocks, applicable_candidates, target_block) ;
313
321
}
314
322
}
315
323
@@ -327,16 +335,15 @@ impl<H:Hair> Builder<H> {
327
335
/// MIR).
328
336
fn bind_and_guard_matched_candidate ( & mut self ,
329
337
mut block : BasicBlock ,
330
- var_extent : H :: CodeExtent ,
331
338
arm_blocks : & mut ArmBlocks ,
332
339
candidate : Candidate < H > )
333
340
-> Option < BasicBlock > {
334
- debug ! ( "bind_and_guard_matched_candidate(block={:?}, var_extent={:?}, candidate={:?})" ,
335
- block, var_extent , candidate) ;
341
+ debug ! ( "bind_and_guard_matched_candidate(block={:?}, candidate={:?})" ,
342
+ block, candidate) ;
336
343
337
344
debug_assert ! ( candidate. match_pairs. is_empty( ) ) ;
338
345
339
- self . bind_matched_candidate ( block, var_extent , candidate. bindings ) ;
346
+ self . bind_matched_candidate ( block, candidate. bindings ) ;
340
347
341
348
let arm_block = arm_blocks. blocks [ candidate. arm_index ] ;
342
349
@@ -356,26 +363,16 @@ impl<H:Hair> Builder<H> {
356
363
357
364
fn bind_matched_candidate ( & mut self ,
358
365
block : BasicBlock ,
359
- var_extent : H :: CodeExtent ,
360
366
bindings : Vec < Binding < H > > ) {
361
- debug ! ( "bind_matched_candidate(block={:?}, var_extent={:?}, bindings={:?})" ,
362
- block, var_extent , bindings) ;
367
+ debug ! ( "bind_matched_candidate(block={:?}, bindings={:?})" ,
368
+ block, bindings) ;
363
369
364
370
// Assign each of the bindings. This may trigger moves out of the candidate.
365
371
for binding in bindings {
366
- // Create a variable for the `var_id` being bound. In the
367
- // case where there are multiple patterns for a single
368
- // arm, it may already exist.
369
- let var_index = if !self . var_indices . contains_key ( & binding. var_id ) {
370
- self . declare_binding ( var_extent,
371
- binding. mutability ,
372
- binding. name ,
373
- binding. var_id ,
374
- binding. var_ty ,
375
- binding. span )
376
- } else {
377
- self . var_indices [ & binding. var_id ]
378
- } ;
372
+ // Find the variable for the `var_id` being bound. It
373
+ // should have been created by a previous call to
374
+ // `declare_bindings`.
375
+ let var_index = self . var_indices [ & binding. var_id ] ;
379
376
380
377
let rvalue = match binding. binding_mode {
381
378
BindingMode :: ByValue =>
0 commit comments