@@ -28,6 +28,7 @@ mod simplify;
2828mod  test; 
2929mod  util; 
3030
31+ use  std:: assert_matches:: assert_matches; 
3132use  std:: borrow:: Borrow ; 
3233use  std:: mem; 
3334
@@ -74,6 +75,17 @@ pub(crate) enum EmitStorageLive {
7475No , 
7576} 
7677
78+ /// Used by [`Builder::storage_live_binding`] and [`Builder::bind_matched_candidate_for_arm_body`] 
79+ /// to decide whether to schedule drops. 
80+ #[ derive( Clone ,  Copy ,  Debug ) ]  
81+ pub ( crate )  enum  ScheduleDrops  { 
82+     /// Yes, the relevant functions should also schedule drops as appropriate. 
83+ Yes , 
84+     /// No, don't schedule drops. The caller has taken responsibility for any 
85+ /// appropriate drops. 
86+ No , 
87+ } 
88+ 
7789impl < ' a ,  ' tcx >  Builder < ' a ,  ' tcx >  { 
7890    /// Lowers a condition in a way that ensures that variables bound in any let 
7991/// expressions are definitely initialized in the if body. 
@@ -535,7 +547,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
535547                fake_borrow_temps, 
536548                scrutinee_span, 
537549                arm_match_scope, 
538-                 true , 
550+                 ScheduleDrops :: Yes , 
539551                emit_storage_live, 
540552            ) 
541553        }  else  { 
@@ -554,7 +566,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
554566            // To handle this we instead unschedule it's drop after each time 
555567            // we lower the guard. 
556568            let  target_block = self . cfg . start_new_block ( ) ; 
557-             let  mut  schedule_drops = true ; 
569+             let  mut  schedule_drops = ScheduleDrops :: Yes ; 
558570            let  arm = arm_match_scope. unzip ( ) . 0 ; 
559571            // We keep a stack of all of the bindings and type ascriptions 
560572            // from the parent candidates that we visit, that also need to 
@@ -576,7 +588,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
576588                        emit_storage_live, 
577589                    ) ; 
578590                    if  arm. is_none ( )  { 
579-                         schedule_drops = false ; 
591+                         schedule_drops = ScheduleDrops :: No ; 
580592                    } 
581593                    self . cfg . goto ( binding_end,  outer_source_info,  target_block) ; 
582594                } , 
@@ -602,8 +614,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
602614        match  irrefutable_pat. kind  { 
603615            // Optimize the case of `let x = ...` to write directly into `x` 
604616            PatKind :: Binding  {  mode :  BindingMode ( ByRef :: No ,  _) ,  var,  subpattern :  None ,  .. }  => { 
605-                 let  place =
606-                     self . storage_live_binding ( block,  var,  irrefutable_pat. span ,  OutsideGuard ,  true ) ; 
617+                 let  place = self . storage_live_binding ( 
618+                     block, 
619+                     var, 
620+                     irrefutable_pat. span , 
621+                     OutsideGuard , 
622+                     ScheduleDrops :: Yes , 
623+                 ) ; 
607624                unpack ! ( block = self . expr_into_dest( place,  block,  initializer_id) ) ; 
608625
609626                // Inject a fake read, see comments on `FakeReadCause::ForLet`. 
@@ -636,8 +653,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
636653                    } , 
637654                ascription :  thir:: Ascription  {  ref  annotation,  variance :  _ } , 
638655            }  => { 
639-                 let  place =
640-                     self . storage_live_binding ( block,  var,  irrefutable_pat. span ,  OutsideGuard ,  true ) ; 
656+                 let  place = self . storage_live_binding ( 
657+                     block, 
658+                     var, 
659+                     irrefutable_pat. span , 
660+                     OutsideGuard , 
661+                     ScheduleDrops :: Yes , 
662+                 ) ; 
641663                unpack ! ( block = self . expr_into_dest( place,  block,  initializer_id) ) ; 
642664
643665                // Inject a fake read, see comments on `FakeReadCause::ForLet`. 
@@ -827,17 +849,21 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
827849        var :  LocalVarId , 
828850        span :  Span , 
829851        for_guard :  ForGuard , 
830-         schedule_drop :  bool , 
852+         schedule_drop :  ScheduleDrops , 
831853    )  -> Place < ' tcx >  { 
832854        let  local_id = self . var_local_id ( var,  for_guard) ; 
833855        let  source_info = self . source_info ( span) ; 
834856        self . cfg . push ( block,  Statement  {  source_info,  kind :  StatementKind :: StorageLive ( local_id)  } ) ; 
835857        // Although there is almost always scope for given variable in corner cases 
836858        // like #92893 we might get variable with no scope. 
837-         if  let  Some ( region_scope)  = self . region_scope_tree . var_scope ( var. 0 . local_id ) 
838-             && schedule_drop
839-         { 
840-             self . schedule_drop ( span,  region_scope,  local_id,  DropKind :: Storage ) ; 
859+         if  let  Some ( region_scope)  = self . region_scope_tree . var_scope ( var. 0 . local_id )  { 
860+             // Match exhaustively, so that it's easy to check how `ScheduleDrops` is used. 
861+             match  schedule_drop { 
862+                 ScheduleDrops :: Yes  => { 
863+                     self . schedule_drop ( span,  region_scope,  local_id,  DropKind :: Storage ) ; 
864+                 } 
865+                 ScheduleDrops :: No  => { } 
866+             } 
841867        } 
842868        Place :: from ( local_id) 
843869    } 
@@ -2112,7 +2138,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
21122138        fake_borrows :  & [ ( Place < ' tcx > ,  Local ,  FakeBorrowKind ) ] , 
21132139        scrutinee_span :  Span , 
21142140        arm_match_scope :  Option < ( & Arm < ' tcx > ,  region:: Scope ) > , 
2115-         schedule_drops :  bool , 
2141+         schedule_drops :  ScheduleDrops , 
21162142        emit_storage_live :  EmitStorageLive , 
21172143    )  -> BasicBlock  { 
21182144        debug ! ( "bind_and_guard_matched_candidate(candidate={:?})" ,  candidate) ; 
@@ -2323,10 +2349,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
23232349                let  cause = FakeReadCause :: ForGuardBinding ; 
23242350                self . cfg . push_fake_read ( post_guard_block,  guard_end,  cause,  Place :: from ( local_id) ) ; 
23252351            } 
2326-             assert ! ( schedule_drops,  "patterns with guards must schedule drops" ) ; 
2352+             assert_matches ! ( 
2353+                 schedule_drops, 
2354+                 ScheduleDrops :: Yes , 
2355+                 "patterns with guards must schedule drops" 
2356+             ) ; 
23272357            self . bind_matched_candidate_for_arm_body ( 
23282358                post_guard_block, 
2329-                 true , 
2359+                 ScheduleDrops :: Yes , 
23302360                by_value_bindings, 
23312361                emit_storage_live, 
23322362            ) ; 
@@ -2376,7 +2406,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
23762406    fn  bind_matched_candidate_for_guard < ' b > ( 
23772407        & mut  self , 
23782408        block :  BasicBlock , 
2379-         schedule_drops :  bool , 
2409+         schedule_drops :  ScheduleDrops , 
23802410        bindings :  impl  IntoIterator < Item  = & ' b  Binding < ' tcx > > , 
23812411    )  where 
23822412        ' tcx :  ' b , 
@@ -2429,7 +2459,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
24292459    fn  bind_matched_candidate_for_arm_body < ' b > ( 
24302460        & mut  self , 
24312461        block :  BasicBlock , 
2432-         schedule_drops :  bool , 
2462+         schedule_drops :  ScheduleDrops , 
24332463        bindings :  impl  IntoIterator < Item  = & ' b  Binding < ' tcx > > , 
24342464        emit_storage_live :  EmitStorageLive , 
24352465    )  where 
@@ -2454,8 +2484,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
24542484                    schedule_drops, 
24552485                ) , 
24562486            } ; 
2457-             if  schedule_drops { 
2458-                 self . schedule_drop_for_binding ( binding. var_id ,  binding. span ,  OutsideGuard ) ; 
2487+             match  schedule_drops { 
2488+                 ScheduleDrops :: Yes  => { 
2489+                     self . schedule_drop_for_binding ( binding. var_id ,  binding. span ,  OutsideGuard ) ; 
2490+                 } 
2491+                 ScheduleDrops :: No  => { } 
24592492            } 
24602493            let  rvalue = match  binding. binding_mode . 0  { 
24612494                ByRef :: No  => Rvalue :: Use ( self . consume_by_copy_or_move ( binding. source ) ) , 
0 commit comments