@@ -12,6 +12,7 @@ use crate::build::{GuardFrame, GuardFrameLocal, LocalsForNode};
1212use crate :: hair:: { self , * } ;
1313use rustc:: hir:: HirId ;
1414use rustc:: mir:: * ;
15+ use rustc:: middle:: region;
1516use rustc:: ty:: { self , CanonicalUserTypeAnnotation , Ty } ;
1617use rustc:: ty:: layout:: VariantIdx ;
1718use rustc_data_structures:: bit_set:: BitSet ;
@@ -251,45 +252,47 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
251252
252253 // Step 5. Create everything else: the guards and the arms.
253254
254- let outer_source_info = self . source_info ( span) ;
255255 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) ) ,
278268 ) ;
279- }
280269
270+ if let Some ( source_scope) = scope {
271+ this. source_scope = source_scope;
272+ }
281273
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+ }
283285
284- arm_block
286+ this. into ( destination, arm_block, body)
287+ } )
285288 } ) . collect ( ) ;
286289
287290 // all the arm blocks will rejoin here
288291 let end_block = self . cfg . start_new_block ( ) ;
289292
290293 for arm_block in arm_end_blocks {
291294 self . cfg . terminate (
292- arm_block,
295+ unpack ! ( arm_block) ,
293296 outer_source_info,
294297 TerminatorKind :: Goto { target : end_block } ,
295298 ) ;
@@ -502,7 +505,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
502505 visibility_scope =
503506 Some ( this. new_source_scope ( scope_span, LintLevel :: Inherited , None ) ) ;
504507 }
505- let source_info = SourceInfo { span, this. source_scope } ;
508+ let source_info = SourceInfo { span, scope : this. source_scope } ;
506509 let visibility_scope = visibility_scope. unwrap ( ) ;
507510 this. declare_binding (
508511 source_info,
@@ -1315,6 +1318,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
13151318 arm_block : BasicBlock ,
13161319 fake_borrows : & Vec < ( & Place < ' tcx > , Local ) > ,
13171320 scrutinee_span : Span ,
1321+ region_scope : ( region:: Scope , SourceInfo ) ,
13181322 ) {
13191323 debug ! ( "bind_and_guard_matched_candidate(candidate={:?})" , candidate) ;
13201324
@@ -1497,17 +1501,40 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
14971501 //
14981502 // and that is clearly not correct.
14991503 let post_guard_block = self . cfg . start_new_block ( ) ;
1504+ let otherwise_post_guard_block = self . cfg . start_new_block ( ) ;
15001505 self . cfg . terminate (
15011506 block,
15021507 source_info,
15031508 TerminatorKind :: if_ (
15041509 self . hir . tcx ( ) ,
1505- cond,
1510+ cond. clone ( ) ,
15061511 post_guard_block,
1507- candidate . otherwise_block . unwrap ( )
1512+ otherwise_post_guard_block ,
15081513 ) ,
15091514 ) ;
15101515
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+
15111538 let by_value_bindings = candidate. bindings . iter ( ) . filter ( |binding| {
15121539 if let BindingMode :: ByValue = binding. binding_mode { true } else { false }
15131540 } ) ;
0 commit comments