11#![ deny( rustc:: untranslatable_diagnostic) ]
22#![ deny( rustc:: diagnostic_outside_of_impl) ]
3- use rustc_infer:: infer:: InferCtxt ;
4- use rustc_middle:: mir:: visit:: TyContext ;
5- use rustc_middle:: mir:: visit:: Visitor ;
6- use rustc_middle:: mir:: {
7- Body , Local , Location , Place , PlaceRef , ProjectionElem , Rvalue , SourceInfo , Statement ,
8- StatementKind , Terminator , TerminatorKind , UserTypeProjection ,
9- } ;
3+ use rustc_middle:: mir:: visit:: { TyContext , Visitor } ;
4+ use rustc_middle:: mir:: { Body , Location , SourceInfo } ;
105use rustc_middle:: ty:: visit:: TypeVisitable ;
11- use rustc_middle:: ty:: GenericArgsRef ;
12- use rustc_middle:: ty:: { self , Ty , TyCtxt } ;
6+ use rustc_middle:: ty:: { GenericArgsRef , Region , Ty , TyCtxt } ;
137
14- use crate :: {
15- borrow_set:: BorrowSet , facts:: AllFacts , location:: LocationTable , places_conflict,
16- region_infer:: values:: LivenessValues ,
17- } ;
8+ use crate :: region_infer:: values:: LivenessValues ;
189
1910pub ( super ) fn generate_constraints < ' tcx > (
20- infcx : & InferCtxt < ' tcx > ,
11+ tcx : TyCtxt < ' tcx > ,
2112 liveness_constraints : & mut LivenessValues ,
22- all_facts : & mut Option < AllFacts > ,
23- location_table : & LocationTable ,
2413 body : & Body < ' tcx > ,
25- borrow_set : & BorrowSet < ' tcx > ,
2614) {
27- let mut cg = ConstraintGeneration {
28- borrow_set,
29- infcx,
30- liveness_constraints,
31- location_table,
32- all_facts,
33- body,
34- } ;
35-
15+ let mut cg = ConstraintGeneration { tcx, liveness_constraints } ;
3616 for ( bb, data) in body. basic_blocks . iter_enumerated ( ) {
3717 cg. visit_basic_block_data ( bb, data) ;
3818 }
3919}
4020
4121/// 'cg = the duration of the constraint generation process itself.
4222struct ConstraintGeneration < ' cg , ' tcx > {
43- infcx : & ' cg InferCtxt < ' tcx > ,
44- all_facts : & ' cg mut Option < AllFacts > ,
45- location_table : & ' cg LocationTable ,
23+ tcx : TyCtxt < ' tcx > ,
4624 liveness_constraints : & ' cg mut LivenessValues ,
47- borrow_set : & ' cg BorrowSet < ' tcx > ,
48- body : & ' cg Body < ' tcx > ,
4925}
5026
5127impl < ' cg , ' tcx > Visitor < ' tcx > for ConstraintGeneration < ' cg , ' tcx > {
5228 /// We sometimes have `args` within an rvalue, or within a
5329 /// call. Make them live at the location where they appear.
5430 fn visit_args ( & mut self , args : & GenericArgsRef < ' tcx > , location : Location ) {
55- self . add_regular_live_constraint ( * args, location) ;
31+ self . record_regions_live_at ( * args, location) ;
5632 self . super_args ( args) ;
5733 }
5834
59- /// We sometimes have `region` within an rvalue, or within a
35+ /// We sometimes have `region`s within an rvalue, or within a
6036 /// call. Make them live at the location where they appear.
61- fn visit_region ( & mut self , region : ty :: Region < ' tcx > , location : Location ) {
62- self . add_regular_live_constraint ( region, location) ;
37+ fn visit_region ( & mut self , region : Region < ' tcx > , location : Location ) {
38+ self . record_regions_live_at ( region, location) ;
6339 self . super_region ( region) ;
6440 }
6541
66- /// We sometimes have `ty` within an rvalue, or within a
42+ /// We sometimes have `ty`s within an rvalue, or within a
6743 /// call. Make them live at the location where they appear.
6844 fn visit_ty ( & mut self , ty : Ty < ' tcx > , ty_context : TyContext ) {
6945 match ty_context {
@@ -74,175 +50,25 @@ impl<'cg, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'tcx> {
7450 span_bug ! ( span, "should not be visiting outside of the CFG: {:?}" , ty_context) ;
7551 }
7652 TyContext :: Location ( location) => {
77- self . add_regular_live_constraint ( ty, location) ;
53+ self . record_regions_live_at ( ty, location) ;
7854 }
7955 }
8056
8157 self . super_ty ( ty) ;
8258 }
83-
84- fn visit_statement ( & mut self , statement : & Statement < ' tcx > , location : Location ) {
85- if let Some ( all_facts) = self . all_facts {
86- let _prof_timer = self . infcx . tcx . prof . generic_activity ( "polonius_fact_generation" ) ;
87- all_facts. cfg_edge . push ( (
88- self . location_table . start_index ( location) ,
89- self . location_table . mid_index ( location) ,
90- ) ) ;
91-
92- all_facts. cfg_edge . push ( (
93- self . location_table . mid_index ( location) ,
94- self . location_table . start_index ( location. successor_within_block ( ) ) ,
95- ) ) ;
96-
97- // If there are borrows on this now dead local, we need to record them as `killed`.
98- if let StatementKind :: StorageDead ( local) = statement. kind {
99- record_killed_borrows_for_local (
100- all_facts,
101- self . borrow_set ,
102- self . location_table ,
103- local,
104- location,
105- ) ;
106- }
107- }
108-
109- self . super_statement ( statement, location) ;
110- }
111-
112- fn visit_assign ( & mut self , place : & Place < ' tcx > , rvalue : & Rvalue < ' tcx > , location : Location ) {
113- // When we see `X = ...`, then kill borrows of
114- // `(*X).foo` and so forth.
115- self . record_killed_borrows_for_place ( * place, location) ;
116-
117- self . super_assign ( place, rvalue, location) ;
118- }
119-
120- fn visit_terminator ( & mut self , terminator : & Terminator < ' tcx > , location : Location ) {
121- if let Some ( all_facts) = self . all_facts {
122- let _prof_timer = self . infcx . tcx . prof . generic_activity ( "polonius_fact_generation" ) ;
123- all_facts. cfg_edge . push ( (
124- self . location_table . start_index ( location) ,
125- self . location_table . mid_index ( location) ,
126- ) ) ;
127-
128- let successor_blocks = terminator. successors ( ) ;
129- all_facts. cfg_edge . reserve ( successor_blocks. size_hint ( ) . 0 ) ;
130- for successor_block in successor_blocks {
131- all_facts. cfg_edge . push ( (
132- self . location_table . mid_index ( location) ,
133- self . location_table . start_index ( successor_block. start_location ( ) ) ,
134- ) ) ;
135- }
136- }
137-
138- // A `Call` terminator's return value can be a local which has borrows,
139- // so we need to record those as `killed` as well.
140- if let TerminatorKind :: Call { destination, .. } = terminator. kind {
141- self . record_killed_borrows_for_place ( destination, location) ;
142- }
143-
144- self . super_terminator ( terminator, location) ;
145- }
146-
147- fn visit_ascribe_user_ty (
148- & mut self ,
149- _place : & Place < ' tcx > ,
150- _variance : ty:: Variance ,
151- _user_ty : & UserTypeProjection ,
152- _location : Location ,
153- ) {
154- }
15559}
15660
15761impl < ' cx , ' tcx > ConstraintGeneration < ' cx , ' tcx > {
158- /// Some variable with type `live_ty` is "regular live" at
159- /// `location` -- i.e., it may be used later. This means that all
160- /// regions appearing in the type `live_ty` must be live at
161- /// `location`.
162- fn add_regular_live_constraint < T > ( & mut self , live_ty : T , location : Location )
62+ /// Some variable is "regular live" at `location` -- i.e., it may be used later. This means that
63+ /// all regions appearing in the type of `value` must be live at `location`.
64+ fn record_regions_live_at < T > ( & mut self , value : T , location : Location )
16365 where
16466 T : TypeVisitable < TyCtxt < ' tcx > > ,
16567 {
166- debug ! ( "add_regular_live_constraint(live_ty={:?}, location={:?})" , live_ty, location) ;
167-
168- self . infcx . tcx . for_each_free_region ( & live_ty, |live_region| {
169- let vid = live_region. as_var ( ) ;
170- self . liveness_constraints . add_location ( vid, location) ;
68+ debug ! ( "add_regular_live_constraint(value={:?}, location={:?})" , value, location) ;
69+ self . tcx . for_each_free_region ( & value, |live_region| {
70+ let live_region_vid = live_region. as_var ( ) ;
71+ self . liveness_constraints . add_location ( live_region_vid, location) ;
17172 } ) ;
17273 }
173-
174- /// When recording facts for Polonius, records the borrows on the specified place
175- /// as `killed`. For example, when assigning to a local, or on a call's return destination.
176- fn record_killed_borrows_for_place ( & mut self , place : Place < ' tcx > , location : Location ) {
177- if let Some ( all_facts) = self . all_facts {
178- let _prof_timer = self . infcx . tcx . prof . generic_activity ( "polonius_fact_generation" ) ;
179-
180- // Depending on the `Place` we're killing:
181- // - if it's a local, or a single deref of a local,
182- // we kill all the borrows on the local.
183- // - if it's a deeper projection, we have to filter which
184- // of the borrows are killed: the ones whose `borrowed_place`
185- // conflicts with the `place`.
186- match place. as_ref ( ) {
187- PlaceRef { local, projection : & [ ] }
188- | PlaceRef { local, projection : & [ ProjectionElem :: Deref ] } => {
189- debug ! (
190- "Recording `killed` facts for borrows of local={:?} at location={:?}" ,
191- local, location
192- ) ;
193-
194- record_killed_borrows_for_local (
195- all_facts,
196- self . borrow_set ,
197- self . location_table ,
198- local,
199- location,
200- ) ;
201- }
202-
203- PlaceRef { local, projection : & [ .., _] } => {
204- // Kill conflicting borrows of the innermost local.
205- debug ! (
206- "Recording `killed` facts for borrows of \
207- innermost projected local={:?} at location={:?}",
208- local, location
209- ) ;
210-
211- if let Some ( borrow_indices) = self . borrow_set . local_map . get ( & local) {
212- for & borrow_index in borrow_indices {
213- let places_conflict = places_conflict:: places_conflict (
214- self . infcx . tcx ,
215- self . body ,
216- self . borrow_set [ borrow_index] . borrowed_place ,
217- place,
218- places_conflict:: PlaceConflictBias :: NoOverlap ,
219- ) ;
220-
221- if places_conflict {
222- let location_index = self . location_table . mid_index ( location) ;
223- all_facts. loan_killed_at . push ( ( borrow_index, location_index) ) ;
224- }
225- }
226- }
227- }
228- }
229- }
230- }
231- }
232-
233- /// When recording facts for Polonius, records the borrows on the specified local as `killed`.
234- fn record_killed_borrows_for_local (
235- all_facts : & mut AllFacts ,
236- borrow_set : & BorrowSet < ' _ > ,
237- location_table : & LocationTable ,
238- local : Local ,
239- location : Location ,
240- ) {
241- if let Some ( borrow_indices) = borrow_set. local_map . get ( & local) {
242- all_facts. loan_killed_at . reserve ( borrow_indices. len ( ) ) ;
243- for & borrow_index in borrow_indices {
244- let location_index = location_table. mid_index ( location) ;
245- all_facts. loan_killed_at . push ( ( borrow_index, location_index) ) ;
246- }
247- }
24874}
0 commit comments