@@ -459,6 +459,7 @@ impl Inliner<'tcx> {
459
459
tcx : self . tcx ,
460
460
callsite_span : callsite. source_info . span ,
461
461
body_span : callee_body. span ,
462
+ always_live_locals : BitSet :: new_filled ( callee_body. local_decls . len ( ) ) ,
462
463
} ;
463
464
464
465
// Map all `Local`s, `SourceScope`s and `BasicBlock`s to new ones
@@ -490,6 +491,34 @@ impl Inliner<'tcx> {
490
491
}
491
492
}
492
493
494
+ // If there are any locals without storage markers, give them storage only for the
495
+ // duration of the call.
496
+ for local in callee_body. vars_and_temps_iter ( ) {
497
+ if integrator. always_live_locals . contains ( local) {
498
+ let new_local = integrator. map_local ( local) ;
499
+ caller_body[ callsite. block ] . statements . push ( Statement {
500
+ source_info : callsite. source_info ,
501
+ kind : StatementKind :: StorageLive ( new_local) ,
502
+ } ) ;
503
+ }
504
+ }
505
+ if let Some ( block) = callsite. target {
506
+ // To avoid repeated O(n) insert, push any new statements to the end and rotate
507
+ // the slice once.
508
+ let mut n = 0 ;
509
+ for local in callee_body. vars_and_temps_iter ( ) . rev ( ) {
510
+ if integrator. always_live_locals . contains ( local) {
511
+ let new_local = integrator. map_local ( local) ;
512
+ caller_body[ block] . statements . push ( Statement {
513
+ source_info : callsite. source_info ,
514
+ kind : StatementKind :: StorageDead ( new_local) ,
515
+ } ) ;
516
+ n += 1 ;
517
+ }
518
+ }
519
+ caller_body[ block] . statements . rotate_right ( n) ;
520
+ }
521
+
493
522
// Insert all of the (mapped) parts of the callee body into the caller.
494
523
caller_body. local_decls . extend (
495
524
// FIXME(eddyb) make `Range<Local>` iterable so that we can use
@@ -670,6 +699,7 @@ struct Integrator<'a, 'tcx> {
670
699
tcx : TyCtxt < ' tcx > ,
671
700
callsite_span : Span ,
672
701
body_span : Span ,
702
+ always_live_locals : BitSet < Local > ,
673
703
}
674
704
675
705
impl < ' a , ' tcx > Integrator < ' a , ' tcx > {
@@ -759,6 +789,15 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Integrator<'a, 'tcx> {
759
789
}
760
790
}
761
791
792
+ fn visit_statement ( & mut self , statement : & mut Statement < ' tcx > , location : Location ) {
793
+ if let StatementKind :: StorageLive ( local) | StatementKind :: StorageDead ( local) =
794
+ statement. kind
795
+ {
796
+ self . always_live_locals . remove ( local) ;
797
+ }
798
+ self . super_statement ( statement, location) ;
799
+ }
800
+
762
801
fn visit_terminator ( & mut self , terminator : & mut Terminator < ' tcx > , loc : Location ) {
763
802
// Don't try to modify the implicit `_0` access on return (`return` terminators are
764
803
// replaced down below anyways).
0 commit comments