@@ -62,6 +62,18 @@ pub(crate) enum DeclareLetBindings {
62
62
LetNotPermitted ,
63
63
}
64
64
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
+
65
77
impl < ' a , ' tcx > Builder < ' a , ' tcx > {
66
78
/// Lowers a condition in a way that ensures that variables bound in any let
67
79
/// expressions are definitely initialized in the if body.
@@ -174,7 +186,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
174
186
Some ( args. variable_source_info . scope ) ,
175
187
args. variable_source_info . span ,
176
188
args. declare_let_bindings ,
177
- false ,
189
+ EmitStorageLive :: Yes ,
178
190
) ,
179
191
_ => {
180
192
let mut block = block;
@@ -467,7 +479,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
467
479
& fake_borrow_temps,
468
480
scrutinee_span,
469
481
Some ( ( arm, match_scope) ) ,
470
- false ,
482
+ EmitStorageLive :: Yes ,
471
483
) ;
472
484
473
485
this. fixed_temps_scope = old_dedup_scope;
@@ -512,7 +524,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
512
524
fake_borrow_temps : & [ ( Place < ' tcx > , Local , FakeBorrowKind ) ] ,
513
525
scrutinee_span : Span ,
514
526
arm_match_scope : Option < ( & Arm < ' tcx > , region:: Scope ) > ,
515
- storages_alive : bool ,
527
+ emit_storage_live : EmitStorageLive ,
516
528
) -> BasicBlock {
517
529
if candidate. subcandidates . is_empty ( ) {
518
530
// Avoid generating another `BasicBlock` when we only have one
@@ -524,7 +536,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
524
536
scrutinee_span,
525
537
arm_match_scope,
526
538
true ,
527
- storages_alive ,
539
+ emit_storage_live ,
528
540
)
529
541
} else {
530
542
// It's helpful to avoid scheduling drops multiple times to save
@@ -561,7 +573,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
561
573
scrutinee_span,
562
574
arm_match_scope,
563
575
schedule_drops,
564
- storages_alive ,
576
+ emit_storage_live ,
565
577
) ;
566
578
if arm. is_none ( ) {
567
579
schedule_drops = false ;
@@ -731,7 +743,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
731
743
& [ ] ,
732
744
irrefutable_pat. span ,
733
745
None ,
734
- false ,
746
+ EmitStorageLive :: Yes ,
735
747
)
736
748
. unit ( )
737
749
}
@@ -807,6 +819,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
807
819
}
808
820
}
809
821
822
+ /// Emits a [`StatementKind::StorageLive`] for the given var, and also
823
+ /// schedules a drop if requested (and possible).
810
824
pub ( crate ) fn storage_live_binding (
811
825
& mut self ,
812
826
block : BasicBlock ,
@@ -2034,7 +2048,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
2034
2048
source_scope : Option < SourceScope > ,
2035
2049
scope_span : Span ,
2036
2050
declare_let_bindings : DeclareLetBindings ,
2037
- storages_alive : bool ,
2051
+ emit_storage_live : EmitStorageLive ,
2038
2052
) -> BlockAnd < ( ) > {
2039
2053
let expr_span = self . thir [ expr_id] . span ;
2040
2054
let scrutinee = unpack ! ( block = self . lower_scrutinee( block, expr_id, expr_span) ) ;
@@ -2074,7 +2088,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
2074
2088
& [ ] ,
2075
2089
expr_span,
2076
2090
None ,
2077
- storages_alive ,
2091
+ emit_storage_live ,
2078
2092
) ;
2079
2093
2080
2094
// If branch coverage is enabled, record this branch.
@@ -2099,7 +2113,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
2099
2113
scrutinee_span : Span ,
2100
2114
arm_match_scope : Option < ( & Arm < ' tcx > , region:: Scope ) > ,
2101
2115
schedule_drops : bool ,
2102
- storages_alive : bool ,
2116
+ emit_storage_live : EmitStorageLive ,
2103
2117
) -> BasicBlock {
2104
2118
debug ! ( "bind_and_guard_matched_candidate(candidate={:?})" , candidate) ;
2105
2119
@@ -2314,7 +2328,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
2314
2328
post_guard_block,
2315
2329
true ,
2316
2330
by_value_bindings,
2317
- storages_alive ,
2331
+ emit_storage_live ,
2318
2332
) ;
2319
2333
2320
2334
post_guard_block
@@ -2326,7 +2340,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
2326
2340
block,
2327
2341
schedule_drops,
2328
2342
bindings,
2329
- storages_alive ,
2343
+ emit_storage_live ,
2330
2344
) ;
2331
2345
block
2332
2346
}
@@ -2417,7 +2431,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
2417
2431
block : BasicBlock ,
2418
2432
schedule_drops : bool ,
2419
2433
bindings : impl IntoIterator < Item = & ' b Binding < ' tcx > > ,
2420
- storages_alive : bool ,
2434
+ emit_storage_live : EmitStorageLive ,
2421
2435
) where
2422
2436
' tcx : ' b ,
2423
2437
{
@@ -2427,19 +2441,18 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
2427
2441
// Assign each of the bindings. This may trigger moves out of the candidate.
2428
2442
for binding in bindings {
2429
2443
let source_info = self . source_info ( binding. span ) ;
2430
- let local = if storages_alive {
2444
+ let local = match emit_storage_live {
2431
2445
// Here storages are already alive, probably because this is a binding
2432
2446
// from let-else.
2433
2447
// 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 (
2437
2450
block,
2438
2451
binding. var_id ,
2439
2452
binding. span ,
2440
2453
OutsideGuard ,
2441
2454
schedule_drops,
2442
- )
2455
+ ) ,
2443
2456
} ;
2444
2457
if schedule_drops {
2445
2458
self . schedule_drop_for_binding ( binding. var_id , binding. span , OutsideGuard ) ;
0 commit comments