@@ -12,6 +12,7 @@ use crate::build::{GuardFrame, GuardFrameLocal, LocalsForNode};
12
12
use crate :: hair:: { self , * } ;
13
13
use rustc:: hir:: HirId ;
14
14
use rustc:: mir:: * ;
15
+ use rustc:: middle:: region;
15
16
use rustc:: ty:: { self , CanonicalUserTypeAnnotation , Ty } ;
16
17
use rustc:: ty:: layout:: VariantIdx ;
17
18
use rustc_data_structures:: bit_set:: BitSet ;
@@ -251,45 +252,47 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
251
252
252
253
// Step 5. Create everything else: the guards and the arms.
253
254
254
- let outer_source_info = self . source_info ( span) ;
255
255
let arm_end_blocks: Vec < _ > = arm_candidates. into_iter ( ) . map ( |( arm, candidates) | {
256
- let mut arm_block = self . cfg . start_new_block ( ) ;
257
-
258
- let body = self . hir . mirror ( arm. body . clone ( ) ) ;
259
- let scope = self . declare_bindings (
260
- None ,
261
- body. span ,
262
- & arm. patterns [ 0 ] ,
263
- ArmHasGuard ( arm. guard . is_some ( ) ) ,
264
- Some ( ( Some ( & scrutinee_place) , scrutinee_span) ) ,
265
- ) ;
266
-
267
- if let Some ( source_scope) = scope {
268
- this. source_scope = source_scope;
269
- }
270
-
271
- for candidate in candidates {
272
- self . bind_and_guard_matched_candidate (
273
- candidate,
274
- arm. guard . clone ( ) ,
275
- arm_block,
276
- & fake_borrow_temps,
277
- scrutinee_span,
256
+ let arm_source_info = self . source_info ( arm. span ) ;
257
+ let region_scope = ( arm. scope , arm_source_info) ;
258
+ self . in_scope ( region_scope, arm. lint_level , |this| {
259
+ let arm_block = this. cfg . start_new_block ( ) ;
260
+
261
+ let body = this. hir . mirror ( arm. body . clone ( ) ) ;
262
+ let scope = this. declare_bindings (
263
+ None ,
264
+ arm. span ,
265
+ & arm. patterns [ 0 ] ,
266
+ ArmHasGuard ( arm. guard . is_some ( ) ) ,
267
+ Some ( ( Some ( & scrutinee_place) , scrutinee_span) ) ,
278
268
) ;
279
- }
280
269
270
+ if let Some ( source_scope) = scope {
271
+ this. source_scope = source_scope;
272
+ }
281
273
282
- unpack ! ( arm_block = self . into( destination, arm_block, body) ) ;
274
+ for candidate in candidates {
275
+ this. clear_top_scope ( arm. scope ) ;
276
+ this. bind_and_guard_matched_candidate (
277
+ candidate,
278
+ arm. guard . clone ( ) ,
279
+ arm_block,
280
+ & fake_borrow_temps,
281
+ scrutinee_span,
282
+ region_scope,
283
+ ) ;
284
+ }
283
285
284
- arm_block
286
+ this. into ( destination, arm_block, body)
287
+ } )
285
288
} ) . collect ( ) ;
286
289
287
290
// all the arm blocks will rejoin here
288
291
let end_block = self . cfg . start_new_block ( ) ;
289
292
290
293
for arm_block in arm_end_blocks {
291
294
self . cfg . terminate (
292
- arm_block,
295
+ unpack ! ( arm_block) ,
293
296
outer_source_info,
294
297
TerminatorKind :: Goto { target : end_block } ,
295
298
) ;
@@ -502,7 +505,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
502
505
visibility_scope =
503
506
Some ( this. new_source_scope ( scope_span, LintLevel :: Inherited , None ) ) ;
504
507
}
505
- let source_info = SourceInfo { span, this. source_scope } ;
508
+ let source_info = SourceInfo { span, scope : this. source_scope } ;
506
509
let visibility_scope = visibility_scope. unwrap ( ) ;
507
510
this. declare_binding (
508
511
source_info,
@@ -1315,6 +1318,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
1315
1318
arm_block : BasicBlock ,
1316
1319
fake_borrows : & Vec < ( & Place < ' tcx > , Local ) > ,
1317
1320
scrutinee_span : Span ,
1321
+ region_scope : ( region:: Scope , SourceInfo ) ,
1318
1322
) {
1319
1323
debug ! ( "bind_and_guard_matched_candidate(candidate={:?})" , candidate) ;
1320
1324
@@ -1497,17 +1501,40 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
1497
1501
//
1498
1502
// and that is clearly not correct.
1499
1503
let post_guard_block = self . cfg . start_new_block ( ) ;
1504
+ let otherwise_post_guard_block = self . cfg . start_new_block ( ) ;
1500
1505
self . cfg . terminate (
1501
1506
block,
1502
1507
source_info,
1503
1508
TerminatorKind :: if_ (
1504
1509
self . hir . tcx ( ) ,
1505
- cond,
1510
+ cond. clone ( ) ,
1506
1511
post_guard_block,
1507
- candidate . otherwise_block . unwrap ( )
1512
+ otherwise_post_guard_block ,
1508
1513
) ,
1509
1514
) ;
1510
1515
1516
+ self . exit_scope (
1517
+ source_info. span ,
1518
+ region_scope,
1519
+ otherwise_post_guard_block,
1520
+ candidate. otherwise_block . unwrap ( ) ,
1521
+ ) ;
1522
+
1523
+ if let Operand :: Copy ( cond_place) | Operand :: Move ( cond_place) = cond {
1524
+ if let Place :: Base ( PlaceBase :: Local ( cond_temp) ) = cond_place {
1525
+ // We will call `clear_top_scope` if there's another guard. So
1526
+ // we have to drop this variable now or it will be "storage
1527
+ // leaked".
1528
+ self . pop_variable (
1529
+ post_guard_block,
1530
+ region_scope. 0 ,
1531
+ cond_temp
1532
+ ) ;
1533
+ } else {
1534
+ bug ! ( "Expected as_local_operand to produce a temporary" ) ;
1535
+ }
1536
+ }
1537
+
1511
1538
let by_value_bindings = candidate. bindings . iter ( ) . filter ( |binding| {
1512
1539
if let BindingMode :: ByValue = binding. binding_mode { true } else { false }
1513
1540
} ) ;
0 commit comments