mirror of
https://github.com/rust-lang/rust.git
synced 2025-06-21 12:07:31 +00:00
Polonius: generate killed
facts for assignments to projections
This commit is contained in:
parent
823ab42e66
commit
2f3e36f51a
@ -3,12 +3,15 @@ use crate::borrow_check::location::LocationTable;
|
|||||||
use crate::borrow_check::nll::ToRegionVid;
|
use crate::borrow_check::nll::ToRegionVid;
|
||||||
use crate::borrow_check::nll::facts::AllFacts;
|
use crate::borrow_check::nll::facts::AllFacts;
|
||||||
use crate::borrow_check::nll::region_infer::values::LivenessValues;
|
use crate::borrow_check::nll::region_infer::values::LivenessValues;
|
||||||
|
use crate::borrow_check::places_conflict;
|
||||||
use rustc::infer::InferCtxt;
|
use rustc::infer::InferCtxt;
|
||||||
use rustc::mir::visit::TyContext;
|
use rustc::mir::visit::TyContext;
|
||||||
use rustc::mir::visit::Visitor;
|
use rustc::mir::visit::Visitor;
|
||||||
use rustc::mir::{BasicBlock, BasicBlockData, Location, Body, Place, PlaceBase, Rvalue, TerminatorKind};
|
use rustc::mir::{
|
||||||
use rustc::mir::{Local, SourceInfo, Statement, StatementKind, Terminator};
|
BasicBlock, BasicBlockData, Body, Local, Location, Place, PlaceBase, Projection,
|
||||||
use rustc::mir::UserTypeProjection;
|
ProjectionElem, Rvalue, SourceInfo, Statement, StatementKind, Terminator, TerminatorKind,
|
||||||
|
UserTypeProjection,
|
||||||
|
};
|
||||||
use rustc::ty::fold::TypeFoldable;
|
use rustc::ty::fold::TypeFoldable;
|
||||||
use rustc::ty::{self, ClosureSubsts, GeneratorSubsts, RegionVid, Ty};
|
use rustc::ty::{self, ClosureSubsts, GeneratorSubsts, RegionVid, Ty};
|
||||||
use rustc::ty::subst::SubstsRef;
|
use rustc::ty::subst::SubstsRef;
|
||||||
@ -27,6 +30,7 @@ pub(super) fn generate_constraints<'cx, 'tcx>(
|
|||||||
liveness_constraints,
|
liveness_constraints,
|
||||||
location_table,
|
location_table,
|
||||||
all_facts,
|
all_facts,
|
||||||
|
body,
|
||||||
};
|
};
|
||||||
|
|
||||||
for (bb, data) in body.basic_blocks().iter_enumerated() {
|
for (bb, data) in body.basic_blocks().iter_enumerated() {
|
||||||
@ -41,6 +45,7 @@ struct ConstraintGeneration<'cg, 'cx, 'tcx> {
|
|||||||
location_table: &'cg LocationTable,
|
location_table: &'cg LocationTable,
|
||||||
liveness_constraints: &'cg mut LivenessValues<RegionVid>,
|
liveness_constraints: &'cg mut LivenessValues<RegionVid>,
|
||||||
borrow_set: &'cg BorrowSet<'tcx>,
|
borrow_set: &'cg BorrowSet<'tcx>,
|
||||||
|
body: &'cg Body<'tcx>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'cg, 'cx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'cx, 'tcx> {
|
impl<'cg, 'cx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'cx, 'tcx> {
|
||||||
@ -212,17 +217,73 @@ impl<'cx, 'cg, 'tcx> ConstraintGeneration<'cx, 'cg, 'tcx> {
|
|||||||
/// as `killed`. For example, when assigning to a local, or on a call's return destination.
|
/// as `killed`. For example, when assigning to a local, or on a call's return destination.
|
||||||
fn record_killed_borrows_for_place(&mut self, place: &Place<'tcx>, location: Location) {
|
fn record_killed_borrows_for_place(&mut self, place: &Place<'tcx>, location: Location) {
|
||||||
if let Some(all_facts) = self.all_facts {
|
if let Some(all_facts) = self.all_facts {
|
||||||
if let Place {
|
// Depending on the `Place` we're killing:
|
||||||
base: PlaceBase::Local(local),
|
// - if it's a local, or a single deref of a local,
|
||||||
projection: None,
|
// we kill all the borrows on the local.
|
||||||
} = place {
|
// - if it's a deeper projection, we have to filter which
|
||||||
record_killed_borrows_for_local(
|
// of the borrows are killed: the ones whose `borrowed_place`
|
||||||
all_facts,
|
// conflicts with the `place`.
|
||||||
self.borrow_set,
|
match place {
|
||||||
self.location_table,
|
Place {
|
||||||
local,
|
base: PlaceBase::Local(local),
|
||||||
location,
|
projection: None,
|
||||||
);
|
} |
|
||||||
|
Place {
|
||||||
|
base: PlaceBase::Local(local),
|
||||||
|
projection: Some(box Projection {
|
||||||
|
base: None,
|
||||||
|
elem: ProjectionElem::Deref,
|
||||||
|
}),
|
||||||
|
} => {
|
||||||
|
debug!(
|
||||||
|
"Recording `killed` facts for borrows of local={:?} at location={:?}",
|
||||||
|
local, location
|
||||||
|
);
|
||||||
|
|
||||||
|
record_killed_borrows_for_local(
|
||||||
|
all_facts,
|
||||||
|
self.borrow_set,
|
||||||
|
self.location_table,
|
||||||
|
local,
|
||||||
|
location,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Place {
|
||||||
|
base: PlaceBase::Static(_),
|
||||||
|
..
|
||||||
|
} => {
|
||||||
|
// Ignore kills of static or static mut variables.
|
||||||
|
}
|
||||||
|
|
||||||
|
Place {
|
||||||
|
base: PlaceBase::Local(local),
|
||||||
|
projection: Some(_),
|
||||||
|
} => {
|
||||||
|
// Kill conflicting borrows of the innermost local.
|
||||||
|
debug!(
|
||||||
|
"Recording `killed` facts for borrows of \
|
||||||
|
innermost projected local={:?} at location={:?}",
|
||||||
|
local, location
|
||||||
|
);
|
||||||
|
|
||||||
|
if let Some(borrow_indices) = self.borrow_set.local_map.get(local) {
|
||||||
|
for &borrow_index in borrow_indices {
|
||||||
|
let places_conflict = places_conflict::places_conflict(
|
||||||
|
self.infcx.tcx,
|
||||||
|
self.body,
|
||||||
|
&self.borrow_set.borrows[borrow_index].borrowed_place,
|
||||||
|
place,
|
||||||
|
places_conflict::PlaceConflictBias::NoOverlap,
|
||||||
|
);
|
||||||
|
|
||||||
|
if places_conflict {
|
||||||
|
let location_index = self.location_table.mid_index(location);
|
||||||
|
all_facts.killed.push((borrow_index, location_index));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user