@@ -45,12 +45,9 @@ pub(super) fn trace<'tcx>(
4545 boring_locals : Vec < Local > ,
4646) {
4747 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 ) ;
5148 let cx = LivenessContext {
5249 typeck,
53- flow_inits,
50+ flow_inits : None ,
5451 location_map,
5552 local_use_map,
5653 move_data,
@@ -83,8 +80,8 @@ struct LivenessContext<'a, 'typeck, 'tcx> {
8380 drop_data : FxIndexMap < Ty < ' tcx > , DropData < ' tcx > > ,
8481
8582 /// 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 > > > ,
8885
8986 /// Index indicating where each variable is assigned, used, or
9087 /// dropped.
@@ -461,6 +458,28 @@ impl<'a, 'typeck, 'tcx> LivenessResults<'a, 'typeck, 'tcx> {
461458 }
462459}
463460
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+
464483impl < ' tcx > LivenessContext < ' _ , ' _ , ' tcx > {
465484 fn body ( & self ) -> & Body < ' tcx > {
466485 self . typeck . body
@@ -469,13 +488,14 @@ impl<'tcx> LivenessContext<'_, '_, 'tcx> {
469488 /// Returns `true` if the local variable (or some part of it) is initialized at the current
470489 /// cursor position. Callers should call one of the `seek` methods immediately before to point
471490 /// 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 ( ) ;
474494 if state. contains ( mpi) {
475495 return true ;
476496 }
477497
478- let move_paths = & self . flow_inits . analysis ( ) . move_data ( ) . move_paths ;
498+ let move_paths = & flow_inits. analysis ( ) . move_data ( ) . move_paths ;
479499 move_paths[ mpi] . find_descendant ( move_paths, |mpi| state. contains ( mpi) ) . is_some ( )
480500 }
481501
@@ -484,7 +504,8 @@ impl<'tcx> LivenessContext<'_, '_, 'tcx> {
484504 /// DROP of some local variable will have an effect -- note that
485505 /// drops, as they may unwind, are always terminators.
486506 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) ;
488509 self . initialized_at_curr_loc ( mpi)
489510 }
490511
@@ -494,7 +515,8 @@ impl<'tcx> LivenessContext<'_, '_, 'tcx> {
494515 /// **Warning:** Does not account for the result of `Call`
495516 /// instructions.
496517 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) ;
498520 self . initialized_at_curr_loc ( mpi)
499521 }
500522
0 commit comments