@@ -3,12 +3,15 @@ use crate::borrow_check::location::LocationTable;
33use crate :: borrow_check:: nll:: ToRegionVid ;
44use crate :: borrow_check:: nll:: facts:: AllFacts ;
55use crate :: borrow_check:: nll:: region_infer:: values:: LivenessValues ;
6+ use crate :: borrow_check:: places_conflict;
67use rustc:: infer:: InferCtxt ;
78use rustc:: mir:: visit:: TyContext ;
89use rustc:: mir:: visit:: Visitor ;
9- use rustc:: mir:: { BasicBlock , BasicBlockData , Location , Body , Place , PlaceBase , Rvalue , TerminatorKind } ;
10- use rustc:: mir:: { Local , SourceInfo , Statement , StatementKind , Terminator } ;
11- use rustc:: mir:: UserTypeProjection ;
10+ use rustc:: mir:: {
11+ BasicBlock , BasicBlockData , Body , Local , Location , Place , PlaceBase , Projection ,
12+ ProjectionElem , Rvalue , SourceInfo , Statement , StatementKind , Terminator , TerminatorKind ,
13+ UserTypeProjection ,
14+ } ;
1215use rustc:: ty:: fold:: TypeFoldable ;
1316use rustc:: ty:: { self , ClosureSubsts , GeneratorSubsts , RegionVid , Ty } ;
1417use rustc:: ty:: subst:: SubstsRef ;
@@ -27,6 +30,7 @@ pub(super) fn generate_constraints<'cx, 'tcx>(
2730 liveness_constraints,
2831 location_table,
2932 all_facts,
33+ body,
3034 } ;
3135
3236 for ( bb, data) in body. basic_blocks ( ) . iter_enumerated ( ) {
@@ -41,6 +45,7 @@ struct ConstraintGeneration<'cg, 'cx, 'tcx> {
4145 location_table : & ' cg LocationTable ,
4246 liveness_constraints : & ' cg mut LivenessValues < RegionVid > ,
4347 borrow_set : & ' cg BorrowSet < ' tcx > ,
48+ body : & ' cg Body < ' tcx > ,
4449}
4550
4651impl < ' cg , ' cx , ' tcx > Visitor < ' tcx > for ConstraintGeneration < ' cg , ' cx , ' tcx > {
@@ -212,17 +217,73 @@ impl<'cx, 'cg, 'tcx> ConstraintGeneration<'cx, 'cg, 'tcx> {
212217 /// as `killed`. For example, when assigning to a local, or on a call's return destination.
213218 fn record_killed_borrows_for_place ( & mut self , place : & Place < ' tcx > , location : Location ) {
214219 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- ) ;
220+ // Depending on the `Place` we're killing:
221+ // - if it's a local, or a single deref of a local,
222+ // we kill all the borrows on the local.
223+ // - if it's a deeper projection, we have to filter which
224+ // of the borrows are killed: the ones whose `borrowed_place`
225+ // conflicts with the `place`.
226+ match place {
227+ Place {
228+ base : PlaceBase :: Local ( local) ,
229+ projection : None ,
230+ } |
231+ Place {
232+ base : PlaceBase :: Local ( local) ,
233+ projection : Some ( box Projection {
234+ base : None ,
235+ elem : ProjectionElem :: Deref ,
236+ } ) ,
237+ } => {
238+ debug ! (
239+ "Recording `killed` facts for borrows of local={:?} at location={:?}" ,
240+ local, location
241+ ) ;
242+
243+ record_killed_borrows_for_local (
244+ all_facts,
245+ self . borrow_set ,
246+ self . location_table ,
247+ local,
248+ location,
249+ ) ;
250+ }
251+
252+ Place {
253+ base : PlaceBase :: Static ( _) ,
254+ ..
255+ } => {
256+ // Ignore kills of static or static mut variables.
257+ }
258+
259+ Place {
260+ base : PlaceBase :: Local ( local) ,
261+ projection : Some ( _) ,
262+ } => {
263+ // Kill conflicting borrows of the innermost local.
264+ debug ! (
265+ "Recording `killed` facts for borrows of \
266+ innermost projected local={:?} at location={:?}",
267+ local, location
268+ ) ;
269+
270+ if let Some ( borrow_indices) = self . borrow_set . local_map . get ( local) {
271+ for & borrow_index in borrow_indices {
272+ let places_conflict = places_conflict:: places_conflict (
273+ self . infcx . tcx ,
274+ self . body ,
275+ & self . borrow_set . borrows [ borrow_index] . borrowed_place ,
276+ place,
277+ places_conflict:: PlaceConflictBias :: NoOverlap ,
278+ ) ;
279+
280+ if places_conflict {
281+ let location_index = self . location_table . mid_index ( location) ;
282+ all_facts. killed . push ( ( borrow_index, location_index) ) ;
283+ }
284+ }
285+ }
286+ }
226287 }
227288 }
228289 }
0 commit comments