11use crate :: borrow_check:: location:: LocationTable ;
22use crate :: borrow_check:: nll:: region_infer:: values:: { self , PointIndex , RegionValueElements } ;
33use crate :: borrow_check:: nll:: type_check:: liveness:: local_use_map:: LocalUseMap ;
4+ use crate :: borrow_check:: nll:: type_check:: liveness:: polonius;
45use crate :: borrow_check:: nll:: type_check:: NormalizeLocation ;
56use crate :: borrow_check:: nll:: type_check:: TypeChecker ;
67use crate :: dataflow:: indexes:: MovePathIndex ;
78use crate :: dataflow:: move_paths:: MoveData ;
89use crate :: dataflow:: { FlowAtLocation , FlowsAtLocation , MaybeInitializedPlaces } ;
910use rustc:: infer:: canonical:: QueryRegionConstraints ;
10- use rustc:: mir:: { BasicBlock , ConstraintCategory , Local , Location , Body } ;
11+ use rustc:: mir:: { BasicBlock , Body , ConstraintCategory , Local , Location } ;
1112use rustc:: traits:: query:: dropck_outlives:: DropckOutlivesResult ;
1213use rustc:: traits:: query:: type_op:: outlives:: DropckOutlives ;
1314use rustc:: traits:: query:: type_op:: TypeOp ;
@@ -130,6 +131,12 @@ impl LivenessResults<'me, 'typeck, 'flow, 'tcx> {
130131 for local in live_locals {
131132 self . reset_local_state ( ) ;
132133 self . add_defs_for ( local) ;
134+
135+ // FIXME: this is temporary until we can generate our own initialization
136+ if self . cx . typeck . borrowck_context . all_facts . is_some ( ) {
137+ self . add_polonius_var_initialized_on_exit_for ( local)
138+ }
139+
133140 self . compute_use_live_points_for ( local) ;
134141 self . compute_drop_live_points_for ( local) ;
135142
@@ -150,6 +157,63 @@ impl LivenessResults<'me, 'typeck, 'flow, 'tcx> {
150157 }
151158 }
152159
160+ // WARNING: panics if self.cx.typeck.borrowck_context.all_facts != None
161+ //
162+ // FIXME: this analysis (the initialization tracking) should be
163+ // done in Polonius, but isn't yet.
164+ fn add_polonius_var_initialized_on_exit_for ( & mut self , local : Local ) {
165+ let move_path = self . cx . move_data . rev_lookup . find_local ( local) ;
166+ let facts = self . cx . typeck . borrowck_context . all_facts . as_mut ( ) . unwrap ( ) ;
167+ for block in self . cx . body . basic_blocks ( ) . indices ( ) {
168+ debug ! ( "polonius: generating initialization facts for {:?} in {:?}" , local, block) ;
169+
170+ // iterate through the block, applying the effects of each statement
171+ // up to and including location, and populate `var_initialized_on_exit`
172+ self . cx . flow_inits . reset_to_entry_of ( block) ;
173+ let start_location = Location { block, statement_index : 0 } ;
174+ self . cx . flow_inits . apply_local_effect ( start_location) ;
175+
176+ for statement_index in 0 ..self . cx . body [ block] . statements . len ( ) {
177+ let current_location = Location { block, statement_index } ;
178+
179+ self . cx . flow_inits . reconstruct_statement_effect ( current_location) ;
180+
181+ // statement has not yet taken effect:
182+ if self . cx . flow_inits . has_any_child_of ( move_path) . is_some ( ) {
183+ facts
184+ . var_initialized_on_exit
185+ . push ( ( local, self . cx . location_table . start_index ( current_location) ) ) ;
186+ }
187+
188+ // statement has now taken effect
189+ self . cx . flow_inits . apply_local_effect ( current_location) ;
190+
191+ if self . cx . flow_inits . has_any_child_of ( move_path) . is_some ( ) {
192+ facts
193+ . var_initialized_on_exit
194+ . push ( ( local, self . cx . location_table . mid_index ( current_location) ) ) ;
195+ }
196+ }
197+
198+ let terminator_location = self . cx . body . terminator_loc ( block) ;
199+
200+ if self . cx . flow_inits . has_any_child_of ( move_path) . is_some ( ) {
201+ facts
202+ . var_initialized_on_exit
203+ . push ( ( local, self . cx . location_table . start_index ( terminator_location) ) ) ;
204+ }
205+
206+ // apply the effects of the terminator and push it if needed
207+ self . cx . flow_inits . reset_to_exit_of ( block) ;
208+
209+ if self . cx . flow_inits . has_any_child_of ( move_path) . is_some ( ) {
210+ facts
211+ . var_initialized_on_exit
212+ . push ( ( local, self . cx . location_table . mid_index ( terminator_location) ) ) ;
213+ }
214+ }
215+ }
216+
153217 /// Clear the value of fields that are "per local variable".
154218 fn reset_local_state ( & mut self ) {
155219 self . defs . clear ( ) ;
@@ -211,6 +275,11 @@ impl LivenessResults<'me, 'typeck, 'flow, 'tcx> {
211275 debug_assert_eq ! ( self . cx. body. terminator_loc( location. block) , location, ) ;
212276
213277 if self . cx . initialized_at_terminator ( location. block , mpi) {
278+ // FIXME: this analysis (the initialization tracking) should be
279+ // done in Polonius, but isn't yet.
280+ if let Some ( facts) = self . cx . typeck . borrowck_context . all_facts {
281+ facts. var_drop_used . push ( ( local, self . cx . location_table . mid_index ( location) ) ) ;
282+ }
214283 if self . drop_live_at . insert ( drop_point) {
215284 self . drop_locations . push ( location) ;
216285 self . stack . push ( drop_point) ;
@@ -487,6 +556,8 @@ impl LivenessContext<'_, '_, '_, 'tcx> {
487556 live_at,
488557 self . location_table ,
489558 ) ;
559+
560+ polonius:: add_var_drops_regions ( & mut self . typeck , dropped_local, & kind) ;
490561 }
491562 }
492563
@@ -505,14 +576,15 @@ impl LivenessContext<'_, '_, '_, 'tcx> {
505576
506577 let tcx = typeck. tcx ( ) ;
507578 tcx. for_each_free_region ( & value, |live_region| {
508- let live_region_vid = typeck . borrowck_context
509- . universal_regions
510- . to_region_vid ( live_region ) ;
511- typeck . borrowck_context
579+ let live_region_vid =
580+ typeck . borrowck_context . universal_regions . to_region_vid ( live_region ) ;
581+ typeck
582+ . borrowck_context
512583 . constraints
513584 . liveness_constraints
514585 . add_elements ( live_region_vid, live_at) ;
515586
587+ // FIXME: remove this when we can generate our own region-live-at reliably
516588 if let Some ( facts) = typeck. borrowck_context . all_facts {
517589 for point in live_at. iter ( ) {
518590 let loc = elements. to_location ( point) ;
0 commit comments