diff --git a/src/librustc_mir/borrow_check/borrow_set.rs b/src/librustc_mir/borrow_check/borrow_set.rs index 1fae97566d0a..c2d7d68923dd 100644 --- a/src/librustc_mir/borrow_check/borrow_set.rs +++ b/src/librustc_mir/borrow_check/borrow_set.rs @@ -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, } +impl<'tcx> Index 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> { diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index 8160a3201dac..340ff5e17876 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -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(); diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 04f4aaf1332e..23682bdee668 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -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>>, nonlexical_cause_info: Option, + + /// The set of borrows extracted from the MIR + borrow_set: Rc>, + + /// Dominators for MIR dominators: Dominators, } @@ -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 { + 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!( diff --git a/src/librustc_mir/dataflow/impls/borrows.rs b/src/librustc_mir/dataflow/impls/borrows.rs index b1fa7eeb3a55..55c38dc89f63 100644 --- a/src/librustc_mir/dataflow/impls/borrows.rs +++ b/src/librustc_mir/dataflow/impls/borrows.rs @@ -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 { - 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> { &self.borrow_set.borrows } pub fn scope_tree(&self) -> &Lrc { &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> {