@@ -62,6 +62,18 @@ pub(crate) enum DeclareLetBindings {
6262 LetNotPermitted ,
6363}
6464
65+ /// Used by [`Builder::bind_matched_candidate_for_arm_body`] to determine
66+ /// whether or not to call [`Builder::storage_live_binding`] to emit
67+ /// [`StatementKind::StorageLive`].
68+ #[ derive( Clone , Copy ) ]
69+ pub ( crate ) enum EmitStorageLive {
70+ /// Yes, emit `StorageLive` as normal.
71+ Yes ,
72+ /// No, don't emit `StorageLive`. The caller has taken responsibility for
73+ /// emitting `StorageLive` as appropriate.
74+ No ,
75+ }
76+
6577impl < ' a , ' tcx > Builder < ' a , ' tcx > {
6678 /// Lowers a condition in a way that ensures that variables bound in any let
6779 /// expressions are definitely initialized in the if body.
@@ -174,7 +186,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
174186 Some ( args. variable_source_info . scope ) ,
175187 args. variable_source_info . span ,
176188 args. declare_let_bindings ,
177- false ,
189+ EmitStorageLive :: Yes ,
178190 ) ,
179191 _ => {
180192 let mut block = block;
@@ -467,7 +479,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
467479 & fake_borrow_temps,
468480 scrutinee_span,
469481 Some ( ( arm, match_scope) ) ,
470- false ,
482+ EmitStorageLive :: Yes ,
471483 ) ;
472484
473485 this. fixed_temps_scope = old_dedup_scope;
@@ -512,7 +524,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
512524 fake_borrow_temps : & [ ( Place < ' tcx > , Local , FakeBorrowKind ) ] ,
513525 scrutinee_span : Span ,
514526 arm_match_scope : Option < ( & Arm < ' tcx > , region:: Scope ) > ,
515- storages_alive : bool ,
527+ emit_storage_live : EmitStorageLive ,
516528 ) -> BasicBlock {
517529 if candidate. subcandidates . is_empty ( ) {
518530 // Avoid generating another `BasicBlock` when we only have one
@@ -524,7 +536,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
524536 scrutinee_span,
525537 arm_match_scope,
526538 true ,
527- storages_alive ,
539+ emit_storage_live ,
528540 )
529541 } else {
530542 // It's helpful to avoid scheduling drops multiple times to save
@@ -561,7 +573,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
561573 scrutinee_span,
562574 arm_match_scope,
563575 schedule_drops,
564- storages_alive ,
576+ emit_storage_live ,
565577 ) ;
566578 if arm. is_none ( ) {
567579 schedule_drops = false ;
@@ -731,7 +743,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
731743 & [ ] ,
732744 irrefutable_pat. span ,
733745 None ,
734- false ,
746+ EmitStorageLive :: Yes ,
735747 )
736748 . unit ( )
737749 }
@@ -807,6 +819,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
807819 }
808820 }
809821
822+ /// Emits a [`StatementKind::StorageLive`] for the given var, and also
823+ /// schedules a drop if requested (and possible).
810824 pub ( crate ) fn storage_live_binding (
811825 & mut self ,
812826 block : BasicBlock ,
@@ -2034,7 +2048,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
20342048 source_scope : Option < SourceScope > ,
20352049 scope_span : Span ,
20362050 declare_let_bindings : DeclareLetBindings ,
2037- storages_alive : bool ,
2051+ emit_storage_live : EmitStorageLive ,
20382052 ) -> BlockAnd < ( ) > {
20392053 let expr_span = self . thir [ expr_id] . span ;
20402054 let scrutinee = unpack ! ( block = self . lower_scrutinee( block, expr_id, expr_span) ) ;
@@ -2074,7 +2088,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
20742088 & [ ] ,
20752089 expr_span,
20762090 None ,
2077- storages_alive ,
2091+ emit_storage_live ,
20782092 ) ;
20792093
20802094 // If branch coverage is enabled, record this branch.
@@ -2099,7 +2113,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
20992113 scrutinee_span : Span ,
21002114 arm_match_scope : Option < ( & Arm < ' tcx > , region:: Scope ) > ,
21012115 schedule_drops : bool ,
2102- storages_alive : bool ,
2116+ emit_storage_live : EmitStorageLive ,
21032117 ) -> BasicBlock {
21042118 debug ! ( "bind_and_guard_matched_candidate(candidate={:?})" , candidate) ;
21052119
@@ -2314,7 +2328,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
23142328 post_guard_block,
23152329 true ,
23162330 by_value_bindings,
2317- storages_alive ,
2331+ emit_storage_live ,
23182332 ) ;
23192333
23202334 post_guard_block
@@ -2326,7 +2340,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
23262340 block,
23272341 schedule_drops,
23282342 bindings,
2329- storages_alive ,
2343+ emit_storage_live ,
23302344 ) ;
23312345 block
23322346 }
@@ -2417,7 +2431,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
24172431 block : BasicBlock ,
24182432 schedule_drops : bool ,
24192433 bindings : impl IntoIterator < Item = & ' b Binding < ' tcx > > ,
2420- storages_alive : bool ,
2434+ emit_storage_live : EmitStorageLive ,
24212435 ) where
24222436 ' tcx : ' b ,
24232437 {
@@ -2427,19 +2441,18 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
24272441 // Assign each of the bindings. This may trigger moves out of the candidate.
24282442 for binding in bindings {
24292443 let source_info = self . source_info ( binding. span ) ;
2430- let local = if storages_alive {
2444+ let local = match emit_storage_live {
24312445 // Here storages are already alive, probably because this is a binding
24322446 // from let-else.
24332447 // We just need to schedule drop for the value.
2434- self . var_local_id ( binding. var_id , OutsideGuard ) . into ( )
2435- } else {
2436- self . storage_live_binding (
2448+ EmitStorageLive :: No => self . var_local_id ( binding. var_id , OutsideGuard ) . into ( ) ,
2449+ EmitStorageLive :: Yes => self . storage_live_binding (
24372450 block,
24382451 binding. var_id ,
24392452 binding. span ,
24402453 OutsideGuard ,
24412454 schedule_drops,
2442- )
2455+ ) ,
24432456 } ;
24442457 if schedule_drops {
24452458 self . schedule_drop_for_binding ( binding. var_id , binding. span , OutsideGuard ) ;
0 commit comments