@@ -45,12 +45,9 @@ pub(super) fn trace<'tcx>(
45
45
boring_locals : Vec < Local > ,
46
46
) {
47
47
let local_use_map = & LocalUseMap :: build ( & relevant_live_locals, location_map, typeck. body ) ;
48
- let flow_inits = MaybeInitializedPlaces :: new ( typeck. tcx ( ) , typeck. body , move_data)
49
- . iterate_to_fixpoint ( typeck. tcx ( ) , typeck. body , Some ( "borrowck" ) )
50
- . into_results_cursor ( typeck. body ) ;
51
48
let cx = LivenessContext {
52
49
typeck,
53
- flow_inits,
50
+ flow_inits : None ,
54
51
location_map,
55
52
local_use_map,
56
53
move_data,
@@ -83,8 +80,8 @@ struct LivenessContext<'a, 'typeck, 'tcx> {
83
80
drop_data : FxIndexMap < Ty < ' tcx > , DropData < ' tcx > > ,
84
81
85
82
/// Results of dataflow tracking which variables (and paths) have been
86
- /// initialized.
87
- flow_inits : ResultsCursor < ' a , ' tcx , MaybeInitializedPlaces < ' a , ' tcx > > ,
83
+ /// initialized. Computed lazily when needed by drop-liveness.
84
+ flow_inits : Option < ResultsCursor < ' a , ' tcx , MaybeInitializedPlaces < ' a , ' tcx > > > ,
88
85
89
86
/// Index indicating where each variable is assigned, used, or
90
87
/// dropped.
@@ -461,6 +458,28 @@ impl<'a, 'typeck, 'tcx> LivenessResults<'a, 'typeck, 'tcx> {
461
458
}
462
459
}
463
460
461
+ impl < ' a , ' typeck , ' tcx > LivenessContext < ' a , ' typeck , ' tcx > {
462
+ /// Computes the `MaybeInitializedPlaces` dataflow analysis if it hasn't been done already.
463
+ ///
464
+ /// In practice, the results of this dataflow analysis are rarely needed but can be expensive to
465
+ /// compute on big functions, so we compute them lazily as a fast path when:
466
+ /// - there are relevant live locals
467
+ /// - there are drop points for these relevant live locals.
468
+ ///
469
+ /// This happens as part of the drop-liveness computation: it's the only place checking for
470
+ /// maybe-initializedness of `MovePathIndex`es.
471
+ fn flow_inits ( & mut self ) -> & mut ResultsCursor < ' a , ' tcx , MaybeInitializedPlaces < ' a , ' tcx > > {
472
+ self . flow_inits . get_or_insert_with ( || {
473
+ let tcx = self . typeck . tcx ( ) ;
474
+ let body = self . typeck . body ;
475
+ let flow_inits = MaybeInitializedPlaces :: new ( tcx, body, self . move_data )
476
+ . iterate_to_fixpoint ( tcx, body, Some ( "borrowck" ) )
477
+ . into_results_cursor ( body) ;
478
+ flow_inits
479
+ } )
480
+ }
481
+ }
482
+
464
483
impl < ' tcx > LivenessContext < ' _ , ' _ , ' tcx > {
465
484
fn body ( & self ) -> & Body < ' tcx > {
466
485
self . typeck . body
@@ -469,13 +488,14 @@ impl<'tcx> LivenessContext<'_, '_, 'tcx> {
469
488
/// Returns `true` if the local variable (or some part of it) is initialized at the current
470
489
/// cursor position. Callers should call one of the `seek` methods immediately before to point
471
490
/// the cursor to the desired location.
472
- fn initialized_at_curr_loc ( & self , mpi : MovePathIndex ) -> bool {
473
- let state = self . flow_inits . get ( ) ;
491
+ fn initialized_at_curr_loc ( & mut self , mpi : MovePathIndex ) -> bool {
492
+ let flow_inits = self . flow_inits ( ) ;
493
+ let state = flow_inits. get ( ) ;
474
494
if state. contains ( mpi) {
475
495
return true ;
476
496
}
477
497
478
- let move_paths = & self . flow_inits . analysis ( ) . move_data ( ) . move_paths ;
498
+ let move_paths = & flow_inits. analysis ( ) . move_data ( ) . move_paths ;
479
499
move_paths[ mpi] . find_descendant ( move_paths, |mpi| state. contains ( mpi) ) . is_some ( )
480
500
}
481
501
@@ -484,7 +504,8 @@ impl<'tcx> LivenessContext<'_, '_, 'tcx> {
484
504
/// DROP of some local variable will have an effect -- note that
485
505
/// drops, as they may unwind, are always terminators.
486
506
fn initialized_at_terminator ( & mut self , block : BasicBlock , mpi : MovePathIndex ) -> bool {
487
- self . flow_inits . seek_before_primary_effect ( self . body ( ) . terminator_loc ( block) ) ;
507
+ let terminator_location = self . body ( ) . terminator_loc ( block) ;
508
+ self . flow_inits ( ) . seek_before_primary_effect ( terminator_location) ;
488
509
self . initialized_at_curr_loc ( mpi)
489
510
}
490
511
@@ -494,7 +515,8 @@ impl<'tcx> LivenessContext<'_, '_, 'tcx> {
494
515
/// **Warning:** Does not account for the result of `Call`
495
516
/// instructions.
496
517
fn initialized_at_exit ( & mut self , block : BasicBlock , mpi : MovePathIndex ) -> bool {
497
- self . flow_inits . seek_after_primary_effect ( self . body ( ) . terminator_loc ( block) ) ;
518
+ let terminator_location = self . body ( ) . terminator_loc ( block) ;
519
+ self . flow_inits ( ) . seek_after_primary_effect ( terminator_location) ;
498
520
self . initialized_at_curr_loc ( mpi)
499
521
}
500
522
0 commit comments