@@ -37,18 +37,17 @@ use crate::type_check::{NormalizeLocation, TypeChecker};
37
37
/// DROP-LIVE set are to the liveness sets for regions found in the
38
38
/// `dropck_outlives` result of the variable's type (in particular,
39
39
/// this respects `#[may_dangle]` annotations).
40
- pub ( super ) fn trace < ' a , ' tcx > (
40
+ pub ( super ) fn trace < ' tcx > (
41
41
typeck : & mut TypeChecker < ' _ , ' tcx > ,
42
42
location_map : & DenseLocationMap ,
43
- flow_inits : ResultsCursor < ' a , ' tcx , MaybeInitializedPlaces < ' a , ' tcx > > ,
44
43
move_data : & MoveData < ' tcx > ,
45
44
relevant_live_locals : Vec < Local > ,
46
45
boring_locals : Vec < Local > ,
47
46
) {
48
47
let local_use_map = & LocalUseMap :: build ( & relevant_live_locals, location_map, typeck. body ) ;
49
48
let cx = LivenessContext {
50
49
typeck,
51
- flow_inits,
50
+ flow_inits : None ,
52
51
location_map,
53
52
local_use_map,
54
53
move_data,
@@ -65,7 +64,7 @@ pub(super) fn trace<'a, 'tcx>(
65
64
}
66
65
67
66
/// Contextual state for the type-liveness coroutine.
68
- struct LivenessContext < ' a , ' typeck , ' b , ' tcx > {
67
+ struct LivenessContext < ' a , ' typeck , ' tcx > {
69
68
/// Current type-checker, giving us our inference context etc.
70
69
///
71
70
/// This also stores the body we're currently analyzing.
@@ -82,7 +81,7 @@ struct LivenessContext<'a, 'typeck, 'b, 'tcx> {
82
81
83
82
/// Results of dataflow tracking which variables (and paths) have been
84
83
/// initialized.
85
- flow_inits : ResultsCursor < ' b , ' tcx , MaybeInitializedPlaces < ' b , ' tcx > > ,
84
+ flow_inits : Option < ResultsCursor < ' a , ' tcx , MaybeInitializedPlaces < ' a , ' tcx > > > ,
86
85
87
86
/// Index indicating where each variable is assigned, used, or
88
87
/// dropped.
@@ -94,8 +93,8 @@ struct DropData<'tcx> {
94
93
region_constraint_data : Option < & ' tcx QueryRegionConstraints < ' tcx > > ,
95
94
}
96
95
97
- struct LivenessResults < ' a , ' typeck , ' b , ' tcx > {
98
- cx : LivenessContext < ' a , ' typeck , ' b , ' tcx > ,
96
+ struct LivenessResults < ' a , ' typeck , ' tcx > {
97
+ cx : LivenessContext < ' a , ' typeck , ' tcx > ,
99
98
100
99
/// Set of points that define the current local.
101
100
defs : DenseBitSet < PointIndex > ,
@@ -116,8 +115,8 @@ struct LivenessResults<'a, 'typeck, 'b, 'tcx> {
116
115
stack : Vec < PointIndex > ,
117
116
}
118
117
119
- impl < ' a , ' typeck , ' b , ' tcx > LivenessResults < ' a , ' typeck , ' b , ' tcx > {
120
- fn new ( cx : LivenessContext < ' a , ' typeck , ' b , ' tcx > ) -> Self {
118
+ impl < ' a , ' typeck , ' tcx > LivenessResults < ' a , ' typeck , ' tcx > {
119
+ fn new ( cx : LivenessContext < ' a , ' typeck , ' tcx > ) -> Self {
121
120
let num_points = cx. location_map . num_points ( ) ;
122
121
LivenessResults {
123
122
cx,
@@ -459,20 +458,39 @@ impl<'a, 'typeck, 'b, 'tcx> LivenessResults<'a, 'typeck, 'b, 'tcx> {
459
458
}
460
459
}
461
460
462
- impl < ' tcx > LivenessContext < ' _ , ' _ , ' _ , ' tcx > {
461
+ impl < ' a , ' typeck , ' tcx > LivenessContext < ' a , ' typeck , ' tcx > {
462
+ fn ensure ( & mut self ) -> & mut ResultsCursor < ' a , ' tcx , MaybeInitializedPlaces < ' a , ' tcx > > {
463
+ // Lazily compute maybe-init dataflow analysis if it's needed: if there are relevant
464
+ // live locals with drop points.
465
+ if self . flow_inits . is_none ( ) {
466
+ use rustc_mir_dataflow:: Analysis ;
467
+ let tcx = self . typeck . tcx ( ) ;
468
+ let body = self . typeck . body ;
469
+ let flow_inits = MaybeInitializedPlaces :: new ( tcx, body, self . move_data )
470
+ . iterate_to_fixpoint ( tcx, body, Some ( "borrowck" ) )
471
+ . into_results_cursor ( body) ;
472
+ self . flow_inits = Some ( flow_inits) ;
473
+ }
474
+ self . flow_inits . as_mut ( ) . expect ( "MaybeInitializedPlaces unavailable for drop-liveness" )
475
+ }
476
+ }
477
+
478
+ impl < ' tcx > LivenessContext < ' _ , ' _ , ' tcx > {
463
479
fn body ( & self ) -> & Body < ' tcx > {
464
480
self . typeck . body
465
481
}
482
+
466
483
/// Returns `true` if the local variable (or some part of it) is initialized at the current
467
484
/// cursor position. Callers should call one of the `seek` methods immediately before to point
468
485
/// the cursor to the desired location.
469
- fn initialized_at_curr_loc ( & self , mpi : MovePathIndex ) -> bool {
470
- let state = self . flow_inits . get ( ) ;
486
+ fn initialized_at_curr_loc ( & mut self , mpi : MovePathIndex ) -> bool {
487
+ let flow_inits = self . ensure ( ) ;
488
+ let state = flow_inits. get ( ) ;
471
489
if state. contains ( mpi) {
472
490
return true ;
473
491
}
474
492
475
- let move_paths = & self . flow_inits . analysis ( ) . move_data ( ) . move_paths ;
493
+ let move_paths = & flow_inits. analysis ( ) . move_data ( ) . move_paths ;
476
494
move_paths[ mpi] . find_descendant ( move_paths, |mpi| state. contains ( mpi) ) . is_some ( )
477
495
}
478
496
@@ -481,7 +499,8 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> {
481
499
/// DROP of some local variable will have an effect -- note that
482
500
/// drops, as they may unwind, are always terminators.
483
501
fn initialized_at_terminator ( & mut self , block : BasicBlock , mpi : MovePathIndex ) -> bool {
484
- self . flow_inits . seek_before_primary_effect ( self . body ( ) . terminator_loc ( block) ) ;
502
+ let terminator = self . body ( ) . terminator_loc ( block) ;
503
+ self . ensure ( ) . seek_before_primary_effect ( terminator) ;
485
504
self . initialized_at_curr_loc ( mpi)
486
505
}
487
506
@@ -491,7 +510,8 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> {
491
510
/// **Warning:** Does not account for the result of `Call`
492
511
/// instructions.
493
512
fn initialized_at_exit ( & mut self , block : BasicBlock , mpi : MovePathIndex ) -> bool {
494
- self . flow_inits . seek_after_primary_effect ( self . body ( ) . terminator_loc ( block) ) ;
513
+ let terminator = self . body ( ) . terminator_loc ( block) ;
514
+ self . ensure ( ) . seek_after_primary_effect ( terminator) ;
495
515
self . initialized_at_curr_loc ( mpi)
496
516
}
497
517
0 commit comments