@@ -6,8 +6,8 @@ use crate::borrow_check::nll::region_infer::values::LivenessValues;
66use rustc:: infer:: InferCtxt ;
77use rustc:: mir:: visit:: TyContext ;
88use rustc:: mir:: visit:: Visitor ;
9- use rustc:: mir:: { BasicBlock , BasicBlockData , Location , Body , Place , PlaceBase , Rvalue } ;
10- use rustc:: mir:: { SourceInfo , Statement , Terminator } ;
9+ use rustc:: mir:: { BasicBlock , BasicBlockData , Location , Body , Place , PlaceBase , Rvalue , TerminatorKind } ;
10+ use rustc:: mir:: { Local , SourceInfo , Statement , StatementKind , Terminator } ;
1111use rustc:: mir:: UserTypeProjection ;
1212use rustc:: ty:: fold:: TypeFoldable ;
1313use rustc:: ty:: { self , ClosureSubsts , GeneratorSubsts , RegionVid , Ty } ;
@@ -114,6 +114,17 @@ impl<'cg, 'cx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'cx, 'tcx> {
114114 self . location_table
115115 . start_index ( location. successor_within_block ( ) ) ,
116116 ) ) ;
117+
118+ // If there are borrows on this now dead local, we need to record them as `killed`.
119+ if let StatementKind :: StorageDead ( ref local) = statement. kind {
120+ record_killed_borrows_for_local (
121+ all_facts,
122+ self . borrow_set ,
123+ self . location_table ,
124+ local,
125+ location,
126+ ) ;
127+ }
117128 }
118129
119130 self . super_statement ( statement, location) ;
@@ -127,20 +138,7 @@ impl<'cg, 'cx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'cx, 'tcx> {
127138 ) {
128139 // When we see `X = ...`, then kill borrows of
129140 // `(*X).foo` and so forth.
130- if let Some ( all_facts) = self . all_facts {
131- if let Place {
132- base : PlaceBase :: Local ( temp) ,
133- projection : None ,
134- } = place {
135- if let Some ( borrow_indices) = self . borrow_set . local_map . get ( temp) {
136- all_facts. killed . reserve ( borrow_indices. len ( ) ) ;
137- for & borrow_index in borrow_indices {
138- let location_index = self . location_table . mid_index ( location) ;
139- all_facts. killed . push ( ( borrow_index, location_index) ) ;
140- }
141- }
142- }
143- }
141+ self . record_killed_borrows_for_place ( place, location) ;
144142
145143 self . super_assign ( place, rvalue, location) ;
146144 }
@@ -167,6 +165,14 @@ impl<'cg, 'cx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'cx, 'tcx> {
167165 }
168166 }
169167
168+ // A `Call` terminator's return value can be a local which has borrows,
169+ // so we need to record those as `killed` as well.
170+ if let TerminatorKind :: Call { ref destination, .. } = terminator. kind {
171+ if let Some ( ( place, _) ) = destination {
172+ self . record_killed_borrows_for_place ( place, location) ;
173+ }
174+ }
175+
170176 self . super_terminator ( terminator, location) ;
171177 }
172178
@@ -201,4 +207,40 @@ impl<'cx, 'cg, 'tcx> ConstraintGeneration<'cx, 'cg, 'tcx> {
201207 self . liveness_constraints . add_element ( vid, location) ;
202208 } ) ;
203209 }
210+
211+ /// When recording facts for Polonius, records the borrows on the specified place
212+ /// as `killed`. For example, when assigning to a local, or on a call's return destination.
213+ fn record_killed_borrows_for_place ( & mut self , place : & Place < ' tcx > , location : Location ) {
214+ if let Some ( all_facts) = self . all_facts {
215+ if let Place {
216+ base : PlaceBase :: Local ( local) ,
217+ projection : None ,
218+ } = place {
219+ record_killed_borrows_for_local (
220+ all_facts,
221+ self . borrow_set ,
222+ self . location_table ,
223+ local,
224+ location,
225+ ) ;
226+ }
227+ }
228+ }
229+ }
230+
231+ /// When recording facts for Polonius, records the borrows on the specified local as `killed`.
232+ fn record_killed_borrows_for_local (
233+ all_facts : & mut AllFacts ,
234+ borrow_set : & BorrowSet < ' _ > ,
235+ location_table : & LocationTable ,
236+ local : & Local ,
237+ location : Location ,
238+ ) {
239+ if let Some ( borrow_indices) = borrow_set. local_map . get ( local) {
240+ all_facts. killed . reserve ( borrow_indices. len ( ) ) ;
241+ for & borrow_index in borrow_indices {
242+ let location_index = location_table. mid_index ( location) ;
243+ all_facts. killed . push ( ( borrow_index, location_index) ) ;
244+ }
245+ }
204246}
0 commit comments