Skip to content

Commit 2f3e36f

Browse files
committed
Polonius: generate killed facts for assignments to projections
1 parent 823ab42 commit 2f3e36f

File tree

1 file changed

+75
-14
lines changed

1 file changed

+75
-14
lines changed

src/librustc_mir/borrow_check/nll/constraint_generation.rs

Lines changed: 75 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,15 @@ use crate::borrow_check::location::LocationTable;
33
use crate::borrow_check::nll::ToRegionVid;
44
use crate::borrow_check::nll::facts::AllFacts;
55
use crate::borrow_check::nll::region_infer::values::LivenessValues;
6+
use crate::borrow_check::places_conflict;
67
use rustc::infer::InferCtxt;
78
use rustc::mir::visit::TyContext;
89
use 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+
};
1215
use rustc::ty::fold::TypeFoldable;
1316
use rustc::ty::{self, ClosureSubsts, GeneratorSubsts, RegionVid, Ty};
1417
use 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

4651
impl<'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

Comments
 (0)