11#![ deny( rustc:: untranslatable_diagnostic) ]
22#![ deny( rustc:: diagnostic_outside_of_impl) ]
3- use rustc_infer:: infer:: InferCtxt ;
43use rustc_middle:: mir:: visit:: Visitor ;
54use rustc_middle:: mir:: {
65 Body , Local , Location , Place , PlaceRef , ProjectionElem , Rvalue , Statement , StatementKind ,
76 Terminator , TerminatorKind , UserTypeProjection ,
87} ;
9- use rustc_middle:: ty:: { self } ;
8+ use rustc_middle:: ty:: { TyCtxt , Variance } ;
109
1110use crate :: { borrow_set:: BorrowSet , facts:: AllFacts , location:: LocationTable , places_conflict} ;
1211
1312pub ( super ) fn generate_constraints < ' tcx > (
14- infcx : & InferCtxt < ' tcx > ,
15- all_facts : & mut Option < AllFacts > ,
13+ tcx : TyCtxt < ' tcx > ,
14+ all_facts : & mut AllFacts ,
1615 location_table : & LocationTable ,
1716 body : & Body < ' tcx > ,
1817 borrow_set : & BorrowSet < ' tcx > ,
1918) {
20- let mut cg = ConstraintGeneration { borrow_set, infcx, location_table, all_facts, body } ;
19+ let _prof_timer = tcx. prof . generic_activity ( "polonius_fact_generation" ) ;
20+ let mut cg = ConstraintGeneration { borrow_set, tcx, location_table, all_facts, body } ;
2121 for ( bb, data) in body. basic_blocks . iter_enumerated ( ) {
2222 cg. visit_basic_block_data ( bb, data) ;
2323 }
2424}
2525
2626/// 'cg = the duration of the constraint generation process itself.
2727struct ConstraintGeneration < ' cg , ' tcx > {
28- infcx : & ' cg InferCtxt < ' tcx > ,
29- all_facts : & ' cg mut Option < AllFacts > ,
28+ tcx : TyCtxt < ' tcx > ,
29+ all_facts : & ' cg mut AllFacts ,
3030 location_table : & ' cg LocationTable ,
3131 borrow_set : & ' cg BorrowSet < ' tcx > ,
3232 body : & ' cg Body < ' tcx > ,
3333}
3434
3535impl < ' cg , ' tcx > Visitor < ' tcx > for ConstraintGeneration < ' cg , ' tcx > {
3636 fn visit_statement ( & mut self , statement : & Statement < ' tcx > , location : Location ) {
37- if let Some ( all_facts) = self . all_facts {
38- let _prof_timer = self . infcx . tcx . prof . generic_activity ( "polonius_fact_generation" ) ;
39- all_facts. cfg_edge . push ( (
40- self . location_table . start_index ( location) ,
41- self . location_table . mid_index ( location) ,
42- ) ) ;
43-
44- all_facts. cfg_edge . push ( (
45- self . location_table . mid_index ( location) ,
46- self . location_table . start_index ( location. successor_within_block ( ) ) ,
47- ) ) ;
48-
49- // If there are borrows on this now dead local, we need to record them as `killed`.
50- if let StatementKind :: StorageDead ( local) = statement. kind {
51- record_killed_borrows_for_local (
52- all_facts,
53- self . borrow_set ,
54- self . location_table ,
55- local,
56- location,
57- ) ;
58- }
37+ self . all_facts . cfg_edge . push ( (
38+ self . location_table . start_index ( location) ,
39+ self . location_table . mid_index ( location) ,
40+ ) ) ;
41+
42+ self . all_facts . cfg_edge . push ( (
43+ self . location_table . mid_index ( location) ,
44+ self . location_table . start_index ( location. successor_within_block ( ) ) ,
45+ ) ) ;
46+
47+ // If there are borrows on this now dead local, we need to record them as `killed`.
48+ if let StatementKind :: StorageDead ( local) = statement. kind {
49+ self . record_killed_borrows_for_local ( local, location) ;
5950 }
6051
6152 self . super_statement ( statement, location) ;
@@ -70,21 +61,18 @@ impl<'cg, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'tcx> {
7061 }
7162
7263 fn visit_terminator ( & mut self , terminator : & Terminator < ' tcx > , location : Location ) {
73- if let Some ( all_facts) = self . all_facts {
74- let _prof_timer = self . infcx . tcx . prof . generic_activity ( "polonius_fact_generation" ) ;
75- all_facts. cfg_edge . push ( (
76- self . location_table . start_index ( location) ,
64+ self . all_facts . cfg_edge . push ( (
65+ self . location_table . start_index ( location) ,
66+ self . location_table . mid_index ( location) ,
67+ ) ) ;
68+
69+ let successor_blocks = terminator. successors ( ) ;
70+ self . all_facts . cfg_edge . reserve ( successor_blocks. size_hint ( ) . 0 ) ;
71+ for successor_block in successor_blocks {
72+ self . all_facts . cfg_edge . push ( (
7773 self . location_table . mid_index ( location) ,
74+ self . location_table . start_index ( successor_block. start_location ( ) ) ,
7875 ) ) ;
79-
80- let successor_blocks = terminator. successors ( ) ;
81- all_facts. cfg_edge . reserve ( successor_blocks. size_hint ( ) . 0 ) ;
82- for successor_block in successor_blocks {
83- all_facts. cfg_edge . push ( (
84- self . location_table . mid_index ( location) ,
85- self . location_table . start_index ( successor_block. start_location ( ) ) ,
86- ) ) ;
87- }
8876 }
8977
9078 // A `Call` terminator's return value can be a local which has borrows,
@@ -99,7 +87,7 @@ impl<'cg, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'tcx> {
9987 fn visit_ascribe_user_ty (
10088 & mut self ,
10189 _place : & Place < ' tcx > ,
102- _variance : ty :: Variance ,
90+ _variance : Variance ,
10391 _user_ty : & UserTypeProjection ,
10492 _location : Location ,
10593 ) {
@@ -110,75 +98,59 @@ impl<'cx, 'tcx> ConstraintGeneration<'cx, 'tcx> {
11098 /// When recording facts for Polonius, records the borrows on the specified place
11199 /// as `killed`. For example, when assigning to a local, or on a call's return destination.
112100 fn record_killed_borrows_for_place ( & mut self , place : Place < ' tcx > , location : Location ) {
113- if let Some ( all_facts) = self . all_facts {
114- let _prof_timer = self . infcx . tcx . prof . generic_activity ( "polonius_fact_generation" ) ;
115-
116- // Depending on the `Place` we're killing:
117- // - if it's a local, or a single deref of a local,
118- // we kill all the borrows on the local.
119- // - if it's a deeper projection, we have to filter which
120- // of the borrows are killed: the ones whose `borrowed_place`
121- // conflicts with the `place`.
122- match place. as_ref ( ) {
123- PlaceRef { local, projection : & [ ] }
124- | PlaceRef { local, projection : & [ ProjectionElem :: Deref ] } => {
125- debug ! (
126- "Recording `killed` facts for borrows of local={:?} at location={:?}" ,
127- local, location
128- ) ;
129-
130- record_killed_borrows_for_local (
131- all_facts,
132- self . borrow_set ,
133- self . location_table ,
134- local,
135- location,
136- ) ;
137- }
101+ // Depending on the `Place` we're killing:
102+ // - if it's a local, or a single deref of a local,
103+ // we kill all the borrows on the local.
104+ // - if it's a deeper projection, we have to filter which
105+ // of the borrows are killed: the ones whose `borrowed_place`
106+ // conflicts with the `place`.
107+ match place. as_ref ( ) {
108+ PlaceRef { local, projection : & [ ] }
109+ | PlaceRef { local, projection : & [ ProjectionElem :: Deref ] } => {
110+ debug ! (
111+ "Recording `killed` facts for borrows of local={:?} at location={:?}" ,
112+ local, location
113+ ) ;
114+
115+ self . record_killed_borrows_for_local ( local, location) ;
116+ }
138117
139- PlaceRef { local, projection : & [ .., _] } => {
140- // Kill conflicting borrows of the innermost local.
141- debug ! (
142- "Recording `killed` facts for borrows of \
118+ PlaceRef { local, projection : & [ .., _] } => {
119+ // Kill conflicting borrows of the innermost local.
120+ debug ! (
121+ "Recording `killed` facts for borrows of \
143122 innermost projected local={:?} at location={:?}",
144- local, location
145- ) ;
146-
147- if let Some ( borrow_indices) = self . borrow_set . local_map . get ( & local) {
148- for & borrow_index in borrow_indices {
149- let places_conflict = places_conflict:: places_conflict (
150- self . infcx . tcx ,
151- self . body ,
152- self . borrow_set [ borrow_index] . borrowed_place ,
153- place,
154- places_conflict:: PlaceConflictBias :: NoOverlap ,
155- ) ;
156-
157- if places_conflict {
158- let location_index = self . location_table . mid_index ( location) ;
159- all_facts. loan_killed_at . push ( ( borrow_index, location_index) ) ;
160- }
123+ local, location
124+ ) ;
125+
126+ if let Some ( borrow_indices) = self . borrow_set . local_map . get ( & local) {
127+ for & borrow_index in borrow_indices {
128+ let places_conflict = places_conflict:: places_conflict (
129+ self . tcx ,
130+ self . body ,
131+ self . borrow_set [ borrow_index] . borrowed_place ,
132+ place,
133+ places_conflict:: PlaceConflictBias :: NoOverlap ,
134+ ) ;
135+
136+ if places_conflict {
137+ let location_index = self . location_table . mid_index ( location) ;
138+ self . all_facts . loan_killed_at . push ( ( borrow_index, location_index) ) ;
161139 }
162140 }
163141 }
164142 }
165143 }
166144 }
167- }
168145
169- /// When recording facts for Polonius, records the borrows on the specified local as `killed`.
170- fn record_killed_borrows_for_local (
171- all_facts : & mut AllFacts ,
172- borrow_set : & BorrowSet < ' _ > ,
173- location_table : & LocationTable ,
174- local : Local ,
175- location : Location ,
176- ) {
177- if let Some ( borrow_indices) = borrow_set. local_map . get ( & local) {
178- all_facts. loan_killed_at . reserve ( borrow_indices. len ( ) ) ;
179- for & borrow_index in borrow_indices {
180- let location_index = location_table. mid_index ( location) ;
181- all_facts. loan_killed_at . push ( ( borrow_index, location_index) ) ;
146+ /// When recording facts for Polonius, records the borrows on the specified local as `killed`.
147+ fn record_killed_borrows_for_local ( & mut self , local : Local , location : Location ) {
148+ if let Some ( borrow_indices) = self . borrow_set . local_map . get ( & local) {
149+ let location_index = self . location_table . mid_index ( location) ;
150+ self . all_facts . loan_killed_at . reserve ( borrow_indices. len ( ) ) ;
151+ for & borrow_index in borrow_indices {
152+ self . all_facts . loan_killed_at . push ( ( borrow_index, location_index) ) ;
153+ }
182154 }
183155 }
184156}
0 commit comments