stop using borrows for anything but iterating over live data
This commit is contained in:
parent
d4005a2bc9
commit
df233f0f2c
4 changed files with 56 additions and 57 deletions
|
|
@ -18,6 +18,7 @@ use rustc::util::nodemap::{FxHashMap, FxHashSet};
|
|||
use rustc_data_structures::indexed_vec::IndexVec;
|
||||
use std::fmt;
|
||||
use std::hash::Hash;
|
||||
use std::ops::Index;
|
||||
use syntax_pos::Span;
|
||||
|
||||
crate struct BorrowSet<'tcx> {
|
||||
|
|
@ -49,6 +50,14 @@ crate struct BorrowSet<'tcx> {
|
|||
crate region_span_map: FxHashMap<RegionKind, Span>,
|
||||
}
|
||||
|
||||
impl<'tcx> Index<BorrowIndex> for BorrowSet<'tcx> {
|
||||
type Output = BorrowData<'tcx>;
|
||||
|
||||
fn index(&self, index: BorrowIndex) -> &BorrowData<'tcx> {
|
||||
&self.borrows[index]
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
crate struct BorrowData<'tcx> {
|
||||
/// Location where the borrow reservation starts.
|
||||
|
|
@ -124,6 +133,13 @@ impl<'tcx> BorrowSet<'tcx> {
|
|||
region_span_map: visitor.region_span_map,
|
||||
}
|
||||
}
|
||||
|
||||
crate fn activations_at_location(&self, location: Location) -> &[BorrowIndex] {
|
||||
self.activation_map
|
||||
.get(&location)
|
||||
.map(|activations| &activations[..])
|
||||
.unwrap_or(&[])
|
||||
}
|
||||
}
|
||||
|
||||
struct GatherBorrows<'a, 'gcx: 'tcx, 'tcx: 'a> {
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ use super::{Context, MirBorrowckCtxt};
|
|||
use super::{InitializationRequiringAction, PrefixSet};
|
||||
use super::borrow_set::BorrowData;
|
||||
|
||||
use dataflow::{Borrows, FlowAtLocation, MovingOutStatements};
|
||||
use dataflow::{FlowAtLocation, MovingOutStatements};
|
||||
use dataflow::move_paths::MovePathIndex;
|
||||
use util::borrowck_errors::{BorrowckErrors, Origin};
|
||||
|
||||
|
|
@ -391,10 +391,9 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
|||
context: Context,
|
||||
borrow: &BorrowData<'tcx>,
|
||||
drop_span: Span,
|
||||
borrows: &Borrows<'cx, 'gcx, 'tcx>
|
||||
) {
|
||||
let end_span = borrows.opt_region_end_span(&borrow.region);
|
||||
let scope_tree = borrows.scope_tree();
|
||||
let end_span = self.opt_region_end_span(&borrow.region);
|
||||
let scope_tree = self.tcx.region_scope_tree(self.mir_def_id);
|
||||
let root_place = self.prefixes(&borrow.borrowed_place, PrefixSet::All)
|
||||
.last()
|
||||
.unwrap();
|
||||
|
|
|
|||
|
|
@ -29,7 +29,6 @@ use rustc_data_structures::indexed_vec::Idx;
|
|||
|
||||
use std::rc::Rc;
|
||||
|
||||
use syntax::ast;
|
||||
use syntax_pos::Span;
|
||||
|
||||
use dataflow::{do_dataflow, DebugFormatted};
|
||||
|
|
@ -237,7 +236,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
|
|||
let mut mbcx = MirBorrowckCtxt {
|
||||
tcx: tcx,
|
||||
mir: mir,
|
||||
node_id: id,
|
||||
mir_def_id: def_id,
|
||||
move_data: &mdpe.move_data,
|
||||
param_env: param_env,
|
||||
movable_generator,
|
||||
|
|
@ -250,6 +249,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
|
|||
moved_error_reported: FxHashSet(),
|
||||
nonlexical_regioncx: opt_regioncx,
|
||||
nonlexical_cause_info: None,
|
||||
borrow_set,
|
||||
dominators,
|
||||
};
|
||||
|
||||
|
|
@ -270,7 +270,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
|
|||
pub struct MirBorrowckCtxt<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
|
||||
tcx: TyCtxt<'cx, 'gcx, 'tcx>,
|
||||
mir: &'cx Mir<'tcx>,
|
||||
node_id: ast::NodeId,
|
||||
mir_def_id: DefId,
|
||||
move_data: &'cx MoveData<'tcx>,
|
||||
param_env: ParamEnv<'gcx>,
|
||||
movable_generator: bool,
|
||||
|
|
@ -303,6 +303,11 @@ pub struct MirBorrowckCtxt<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
|
|||
/// find out which CFG points are contained in each borrow region.
|
||||
nonlexical_regioncx: Option<Rc<RegionInferenceContext<'tcx>>>,
|
||||
nonlexical_cause_info: Option<RegionCausalInfo>,
|
||||
|
||||
/// The set of borrows extracted from the MIR
|
||||
borrow_set: Rc<BorrowSet<'tcx>>,
|
||||
|
||||
/// Dominators for MIR
|
||||
dominators: Dominators<BasicBlock>,
|
||||
}
|
||||
|
||||
|
|
@ -544,11 +549,10 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx
|
|||
|
||||
if self.movable_generator {
|
||||
// Look for any active borrows to locals
|
||||
let domain = flow_state.borrows.operator();
|
||||
let data = domain.borrows();
|
||||
let borrow_set = self.borrow_set.clone();
|
||||
flow_state.borrows.with_iter_outgoing(|borrows| {
|
||||
for i in borrows {
|
||||
let borrow = &data[i];
|
||||
let borrow = &borrow_set[i];
|
||||
self.check_for_local_borrow(borrow, span);
|
||||
}
|
||||
});
|
||||
|
|
@ -560,13 +564,12 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx
|
|||
// Often, the storage will already have been killed by an explicit
|
||||
// StorageDead, but we don't always emit those (notably on unwind paths),
|
||||
// so this "extra check" serves as a kind of backup.
|
||||
let domain = flow_state.borrows.operator();
|
||||
let data = domain.borrows();
|
||||
let borrow_set = self.borrow_set.clone();
|
||||
flow_state.borrows.with_iter_outgoing(|borrows| {
|
||||
for i in borrows {
|
||||
let borrow = &data[i];
|
||||
let borrow = &borrow_set[i];
|
||||
let context = ContextKind::StorageDead.new(loc);
|
||||
self.check_for_invalidation_at_exit(context, borrow, span, flow_state);
|
||||
self.check_for_invalidation_at_exit(context, borrow, span);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -894,10 +897,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
|||
this.report_use_while_mutably_borrowed(context, place_span, borrow)
|
||||
}
|
||||
ReadKind::Borrow(bk) => {
|
||||
let end_issued_loan_span = flow_state
|
||||
.borrows
|
||||
.operator()
|
||||
.opt_region_end_span(&borrow.region);
|
||||
let end_issued_loan_span = this.opt_region_end_span(&borrow.region);
|
||||
error_reported = true;
|
||||
this.report_conflicting_borrow(
|
||||
context,
|
||||
|
|
@ -936,10 +936,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
|||
|
||||
match kind {
|
||||
WriteKind::MutableBorrow(bk) => {
|
||||
let end_issued_loan_span = flow_state
|
||||
.borrows
|
||||
.operator()
|
||||
.opt_region_end_span(&borrow.region);
|
||||
let end_issued_loan_span = this.opt_region_end_span(&borrow.region);
|
||||
|
||||
error_reported = true;
|
||||
this.report_conflicting_borrow(
|
||||
|
|
@ -956,7 +953,6 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
|||
context,
|
||||
borrow,
|
||||
place_span.1,
|
||||
flow_state.borrows.operator(),
|
||||
);
|
||||
}
|
||||
WriteKind::Mutate => {
|
||||
|
|
@ -1158,7 +1154,6 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
|||
context: Context,
|
||||
borrow: &BorrowData<'tcx>,
|
||||
span: Span,
|
||||
flow_state: &Flows<'cx, 'gcx, 'tcx>,
|
||||
) {
|
||||
debug!("check_for_invalidation_at_exit({:?})", borrow);
|
||||
let place = &borrow.borrowed_place;
|
||||
|
|
@ -1211,7 +1206,6 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
|||
context,
|
||||
borrow,
|
||||
span,
|
||||
flow_state.borrows.operator(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -1266,9 +1260,9 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
|||
// Two-phase borrow support: For each activation that is newly
|
||||
// generated at this statement, check if it interferes with
|
||||
// another borrow.
|
||||
let borrows = flow_state.borrows.operator();
|
||||
for &borrow_index in borrows.activations_at_location(location) {
|
||||
let borrow = &borrows.borrows()[borrow_index];
|
||||
let borrow_set = self.borrow_set.clone();
|
||||
for &borrow_index in borrow_set.activations_at_location(location) {
|
||||
let borrow = &borrow_set[borrow_index];
|
||||
|
||||
// only mutable borrows should be 2-phase
|
||||
assert!(match borrow.kind {
|
||||
|
|
@ -1838,6 +1832,22 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
|||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the span for the "end point" given region. This will
|
||||
/// return `None` if NLL is enabled, since that concept has no
|
||||
/// meaning there. Otherwise, return region span if it exists and
|
||||
/// span for end of the function if it doesn't exist.
|
||||
pub(crate) fn opt_region_end_span(&self, region: &ty::Region<'tcx>) -> Option<Span> {
|
||||
match self.nonlexical_regioncx {
|
||||
Some(_) => None,
|
||||
None => {
|
||||
match self.borrow_set.region_span_map.get(region) {
|
||||
Some(span) => Some(self.tcx.sess.codemap().end_point(*span)),
|
||||
None => Some(self.tcx.sess.codemap().end_point(self.mir.span))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||
|
|
@ -2238,13 +2248,12 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
|||
// FIXME: analogous code in check_loans first maps `place` to
|
||||
// its base_path.
|
||||
|
||||
let data = flow_state.borrows.operator().borrows();
|
||||
|
||||
// check for loan restricting path P being used. Accounts for
|
||||
// borrows of P, P.a.b, etc.
|
||||
let mut iter_incoming = flow_state.borrows.iter_incoming();
|
||||
let borrow_set = self.borrow_set.clone();
|
||||
while let Some(i) = iter_incoming.next() {
|
||||
let borrowed = &data[i];
|
||||
let borrowed = &borrow_set[i];
|
||||
|
||||
if self.places_conflict(&borrowed.borrowed_place, place, access) {
|
||||
debug!(
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ use rustc::hir;
|
|||
use rustc::hir::def_id::DefId;
|
||||
use rustc::middle::region;
|
||||
use rustc::mir::{self, Location, Place, Mir};
|
||||
use rustc::ty::{Region, TyCtxt};
|
||||
use rustc::ty::TyCtxt;
|
||||
use rustc::ty::RegionKind;
|
||||
use rustc::ty::RegionKind::ReScope;
|
||||
|
||||
|
|
@ -30,8 +30,6 @@ pub use dataflow::indexes::BorrowIndex;
|
|||
use borrow_check::nll::region_infer::RegionInferenceContext;
|
||||
use borrow_check::nll::ToRegionVid;
|
||||
|
||||
use syntax_pos::Span;
|
||||
|
||||
use std::rc::Rc;
|
||||
|
||||
/// `Borrows` stores the data used in the analyses that track the flow
|
||||
|
|
@ -77,22 +75,6 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns the span for the "end point" given region. This will
|
||||
/// return `None` if NLL is enabled, since that concept has no
|
||||
/// meaning there. Otherwise, return region span if it exists and
|
||||
/// span for end of the function if it doesn't exist.
|
||||
pub(crate) fn opt_region_end_span(&self, region: &Region) -> Option<Span> {
|
||||
match self.nonlexical_regioncx {
|
||||
Some(_) => None,
|
||||
None => {
|
||||
match self.borrow_set.region_span_map.get(region) {
|
||||
Some(span) => Some(self.tcx.sess.codemap().end_point(*span)),
|
||||
None => Some(self.tcx.sess.codemap().end_point(self.mir.span))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
crate fn borrows(&self) -> &IndexVec<BorrowIndex, BorrowData<'tcx>> { &self.borrow_set.borrows }
|
||||
|
||||
pub fn scope_tree(&self) -> &Lrc<region::ScopeTree> { &self.scope_tree }
|
||||
|
|
@ -136,13 +118,6 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> {
|
|||
sets.kill_all(borrow_indexes);
|
||||
}
|
||||
}
|
||||
|
||||
crate fn activations_at_location(&self, location: Location) -> &[BorrowIndex] {
|
||||
self.borrow_set.activation_map
|
||||
.get(&location)
|
||||
.map(|activations| &activations[..])
|
||||
.unwrap_or(&[])
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'gcx, 'tcx> BitDenotation for Borrows<'a, 'gcx, 'tcx> {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue