From ab98c595eaa07249e2ebbf37c9123b33fc6a892f Mon Sep 17 00:00:00 2001 From: Paul Daniel Faria Date: Thu, 24 Oct 2019 00:38:01 -0400 Subject: [PATCH] Fix a large number of Body -> (ReadOnly)BodyCache type errors, add predecessor_locations fn to ReadOnlyBodyCache --- src/librustc/mir/cache.rs | 62 ++++++++++----- src/librustc_mir/borrow_check/borrow_set.rs | 16 ++-- .../borrow_check/conflict_errors.rs | 56 +++++++------- .../borrow_check/error_reporting.rs | 32 ++++---- src/librustc_mir/borrow_check/mod.rs | 75 ++++++++++--------- src/librustc_mir/borrow_check/move_errors.rs | 20 ++--- .../borrow_check/mutability_errors.rs | 24 +++--- .../borrow_check/nll/explain_borrow/mod.rs | 20 ++--- .../borrow_check/nll/invalidation.rs | 10 +-- src/librustc_mir/borrow_check/nll/mod.rs | 31 ++++---- .../borrow_check/nll/region_infer/values.rs | 8 +- src/librustc_mir/borrow_check/nll/renumber.rs | 10 +-- .../borrow_check/nll/type_check/mod.rs | 20 ++--- src/librustc_mir/borrow_check/prefixes.rs | 2 +- src/librustc_mir/borrow_check/used_muts.rs | 2 +- 15 files changed, 206 insertions(+), 182 deletions(-) diff --git a/src/librustc/mir/cache.rs b/src/librustc/mir/cache.rs index 63d8eba971b..c0c5f77fe6e 100644 --- a/src/librustc/mir/cache.rs +++ b/src/librustc/mir/cache.rs @@ -33,6 +33,41 @@ pub struct Cache { // } //} +macro_rules! get_predecessors { + (mut $self:ident, $block:expr, $body:expr) => { + $self.predecessors_for($block, $body) + }; + ($self:ident, $block:expr, $body:expr) => { + $self.unwrap_predecessors_for($block) + }; +} + +macro_rules! impl_predecessor_locations { + ( ( $($pub:ident)? ) $name:ident $($mutability:ident)?) => { + $($pub)? fn $name<'a>(&'a $($mutability)? self, loc: Location, body: &'a Body<'a>) -> impl Iterator + 'a { + let if_zero_locations = if loc.statement_index == 0 { + let predecessor_blocks = get_predecessors!($($mutability)? self, loc.block, body); + let num_predecessor_blocks = predecessor_blocks.len(); + Some( + (0..num_predecessor_blocks) + .map(move |i| predecessor_blocks[i]) + .map(move |bb| body.terminator_loc(bb)), + ) + } else { + None + }; + + let if_not_zero_locations = if loc.statement_index == 0 { + None + } else { + Some(Location { block: loc.block, statement_index: loc.statement_index - 1 }) + }; + + if_zero_locations.into_iter().flatten().chain(if_not_zero_locations) + } + }; +} + impl Cache { pub fn new() -> Self { Self { @@ -80,27 +115,9 @@ impl Cache { } #[inline] - pub fn predecessor_locations<'a>(&'a mut self, loc: Location, body: &'a Body<'a>) -> impl Iterator + 'a { - let if_zero_locations = if loc.statement_index == 0 { - let predecessor_blocks = self.predecessors_for(loc.block, body); - let num_predecessor_blocks = predecessor_blocks.len(); - Some( - (0..num_predecessor_blocks) - .map(move |i| predecessor_blocks[i]) - .map(move |bb| body.terminator_loc(bb)), - ) - } else { - None - }; + impl_predecessor_locations!((pub) predecessor_locations mut); - let if_not_zero_locations = if loc.statement_index == 0 { - None - } else { - Some(Location { block: loc.block, statement_index: loc.statement_index - 1 }) - }; - - if_zero_locations.into_iter().flatten().chain(if_not_zero_locations) - } + impl_predecessor_locations!(() unwrap_predecessor_locations); #[inline] pub fn basic_blocks_mut<'a, 'tcx>(&mut self, body: &'a mut Body<'tcx>) -> &'a mut IndexVec> { @@ -240,6 +257,11 @@ impl ReadOnlyBodyCache<'a, 'tcx> { self.cache.unwrap_predecessors_for(bb) } + #[inline] + pub fn predecessor_locations(&self, loc: Location) -> impl Iterator + '_ { + self.cache.unwrap_predecessor_locations(loc, self.body) + } + #[inline] pub fn body(&self) -> &'a Body<'tcx> { self.body diff --git a/src/librustc_mir/borrow_check/borrow_set.rs b/src/librustc_mir/borrow_check/borrow_set.rs index 94323431990..6191a93d228 100644 --- a/src/librustc_mir/borrow_check/borrow_set.rs +++ b/src/librustc_mir/borrow_check/borrow_set.rs @@ -5,7 +5,7 @@ use crate::dataflow::indexes::BorrowIndex; use crate::dataflow::move_paths::MoveData; use rustc::mir::traversal; use rustc::mir::visit::{PlaceContext, Visitor, NonUseContext, MutatingUseContext}; -use rustc::mir::{self, Location, Body, Local}; +use rustc::mir::{self, Location, Body, Local, ReadOnlyBodyCache}; use rustc::ty::{RegionVid, TyCtxt}; use rustc::util::nodemap::{FxHashMap, FxHashSet}; use rustc_index::vec::IndexVec; @@ -90,7 +90,7 @@ crate enum LocalsStateAtExit { impl LocalsStateAtExit { fn build( locals_are_invalidated_at_exit: bool, - body: &Body<'tcx>, + body_cache: &ReadOnlyBodyCache<'_, 'tcx>, move_data: &MoveData<'tcx> ) -> Self { struct HasStorageDead(BitSet); @@ -106,8 +106,8 @@ impl LocalsStateAtExit { if locals_are_invalidated_at_exit { LocalsStateAtExit::AllAreInvalidated } else { - let mut has_storage_dead = HasStorageDead(BitSet::new_empty(body.local_decls.len())); - has_storage_dead.visit_body(body); + let mut has_storage_dead = HasStorageDead(BitSet::new_empty(body_cache.local_decls.len())); + has_storage_dead.visit_body(body_cache); let mut has_storage_dead_or_moved = has_storage_dead.0; for move_out in &move_data.moves { if let Some(index) = move_data.base_local(move_out.path) { @@ -123,23 +123,23 @@ impl LocalsStateAtExit { impl<'tcx> BorrowSet<'tcx> { pub fn build( tcx: TyCtxt<'tcx>, - body: &Body<'tcx>, + body_cache: &ReadOnlyBodyCache<'_, 'tcx>, locals_are_invalidated_at_exit: bool, move_data: &MoveData<'tcx>, ) -> Self { let mut visitor = GatherBorrows { tcx, - body, + body: body_cache.body(), idx_vec: IndexVec::new(), location_map: Default::default(), activation_map: Default::default(), local_map: Default::default(), pending_activations: Default::default(), locals_state_at_exit: - LocalsStateAtExit::build(locals_are_invalidated_at_exit, body, move_data), + LocalsStateAtExit::build(locals_are_invalidated_at_exit, body_cache, move_data), }; - for (block, block_data) in traversal::preorder(body) { + for (block, block_data) in traversal::preorder(body_cache) { visitor.visit_basic_block_data(block, block_data); } diff --git a/src/librustc_mir/borrow_check/conflict_errors.rs b/src/librustc_mir/borrow_check/conflict_errors.rs index 48f8ad9bbd8..b44ef1c1706 100644 --- a/src/librustc_mir/borrow_check/conflict_errors.rs +++ b/src/librustc_mir/borrow_check/conflict_errors.rs @@ -206,7 +206,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } let ty = - Place::ty_from(used_place.base, used_place.projection, self.body, self.infcx.tcx) + Place::ty_from(used_place.base, used_place.projection, self.body_cache.body(), self.infcx.tcx) .ty; let needs_note = match ty.kind { ty::Closure(id, _) => { @@ -222,7 +222,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let mpi = self.move_data.moves[move_out_indices[0]].path; let place = &self.move_data.move_paths[mpi].place; - let ty = place.ty(self.body, self.infcx.tcx).ty; + let ty = place.ty(self.body_cache.body(), self.infcx.tcx).ty; let opt_name = self.describe_place_with_options(place.as_ref(), IncludingDowncast(true)); let note_msg = match opt_name { @@ -314,7 +314,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { None, ).add_explanation_to_diagnostic( self.infcx.tcx, - self.body, + &self.body_cache, &self.local_names, &mut err, "", @@ -356,7 +356,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { self.explain_why_borrow_contains_point(location, borrow, None) .add_explanation_to_diagnostic( self.infcx.tcx, - self.body, + &self.body_cache, &self.local_names, &mut err, "", @@ -578,7 +578,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { explanation.add_explanation_to_diagnostic( self.infcx.tcx, - self.body, + &self.body_cache, &self.local_names, &mut err, first_borrow_desc, @@ -619,7 +619,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // Define a small closure that we can use to check if the type of a place // is a union. let union_ty = |place_base, place_projection| { - let ty = Place::ty_from(place_base, place_projection, self.body, self.infcx.tcx).ty; + let ty = Place::ty_from(place_base, place_projection, self.body_cache.body(), self.infcx.tcx).ty; ty.ty_adt_def().filter(|adt| adt.is_union()).map(|_| ty) }; let describe_place = |place| self.describe_place(place).unwrap_or_else(|| "_".to_owned()); @@ -738,7 +738,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { assert!(root_place.projection.is_empty()); let proper_span = match root_place.base { - PlaceBase::Local(local) => self.body.local_decls[*local].source_info.span, + PlaceBase::Local(local) => self.body_cache.local_decls[*local].source_info.span, _ => drop_span, }; @@ -965,7 +965,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } else { explanation.add_explanation_to_diagnostic( self.infcx.tcx, - self.body, + &self.body_cache, &self.local_names, &mut err, "", @@ -991,7 +991,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ); explanation.add_explanation_to_diagnostic( - self.infcx.tcx, self.body, &self.local_names, &mut err, "", None); + self.infcx.tcx, &self.body_cache, &self.local_names, &mut err, "", None); } err @@ -1051,7 +1051,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { explanation.add_explanation_to_diagnostic( self.infcx.tcx, - self.body, + &self.body_cache, &self.local_names, &mut err, "", @@ -1138,7 +1138,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } explanation.add_explanation_to_diagnostic( self.infcx.tcx, - self.body, + &self.body_cache, &self.local_names, &mut err, "", @@ -1174,7 +1174,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { }; // FIXME use a better heuristic than Spans - let reference_desc = if return_span == self.body.source_info(borrow.reserve_location).span { + let reference_desc = if return_span == self.body_cache.source_info(borrow.reserve_location).span { "reference to" } else { "value referencing" @@ -1182,7 +1182,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let (place_desc, note) = if let Some(place_desc) = opt_place_desc { let local_kind = if let Some(local) = borrow.borrowed_place.as_local() { - match self.body.local_kind(local) { + match self.body_cache.local_kind(local) { LocalKind::ReturnPointer | LocalKind::Temp => bug!("temporary or return pointer with a name"), LocalKind::Var => "local variable ", @@ -1215,7 +1215,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } else { bug!("try_report_cannot_return_reference_to_local: not a local") }; - match self.body.local_kind(*local) { + match self.body_cache.local_kind(*local) { LocalKind::ReturnPointer | LocalKind::Temp => ( "temporary value".to_string(), "temporary value created here".to_string(), @@ -1372,10 +1372,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } fn get_moved_indexes(&mut self, location: Location, mpi: MovePathIndex) -> Vec { - let body = self.body; - let mut stack = Vec::new(); - stack.extend(body.predecessor_locations(location).map(|predecessor| { + stack.extend(self.body_cache.predecessor_locations(location).map(|predecessor| { let is_back_edge = location.dominates(predecessor, &self.dominators); (predecessor, is_back_edge) })); @@ -1394,7 +1392,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } // check for moves - let stmt_kind = body[location.block] + let stmt_kind = self.body_cache[location.block] .statements .get(location.statement_index) .map(|s| &s.kind); @@ -1449,7 +1447,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let mut any_match = false; drop_flag_effects::for_location_inits( self.infcx.tcx, - self.body, + &self.body_cache, self.move_data, location, |m| { @@ -1462,7 +1460,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { continue 'dfs; } - stack.extend(body.predecessor_locations(location).map(|predecessor| { + stack.extend(self.body_cache.predecessor_locations(location).map(|predecessor| { let back_edge = location.dominates(predecessor, &self.dominators); (predecessor, is_back_edge || back_edge) })); @@ -1514,7 +1512,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { self.explain_why_borrow_contains_point(location, loan, None) .add_explanation_to_diagnostic( self.infcx.tcx, - self.body, + &self.body_cache, &self.local_names, &mut err, "", @@ -1539,8 +1537,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ) { let (from_arg, local_decl, local_name) = match err_place.as_local() { Some(local) => ( - self.body.local_kind(local) == LocalKind::Arg, - Some(&self.body.local_decls[local]), + self.body_cache.local_kind(local) == LocalKind::Arg, + Some(&self.body_cache.local_decls[local]), self.local_names[local], ), None => (false, None, None), @@ -1625,7 +1623,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { StorageDeadOrDrop::LocalStorageDead | StorageDeadOrDrop::BoxedStorageDead => { assert!( - Place::ty_from(&place.base, proj_base, self.body, tcx).ty.is_box(), + Place::ty_from(&place.base, proj_base, self.body_cache.body(), tcx).ty.is_box(), "Drop of value behind a reference or raw pointer" ); StorageDeadOrDrop::BoxedStorageDead @@ -1633,7 +1631,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { StorageDeadOrDrop::Destructor(_) => base_access, }, ProjectionElem::Field(..) | ProjectionElem::Downcast(..) => { - let base_ty = Place::ty_from(&place.base, proj_base, self.body, tcx).ty; + let base_ty = Place::ty_from(&place.base, proj_base, self.body_cache.body(), tcx).ty; match base_ty.kind { ty::Adt(def, _) if def.has_dtor(tcx) => { // Report the outermost adt with a destructor @@ -1721,7 +1719,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { location ); if let Some(&Statement { kind: StatementKind::Assign(box(ref reservation, _)), ..}) - = &self.body[location.block].statements.get(location.statement_index) + = &self.body_cache[location.block].statements.get(location.statement_index) { debug!( "annotate_argument_and_return_for_borrow: reservation={:?}", @@ -1729,14 +1727,14 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ); // Check that the initial assignment of the reserve location is into a temporary. let mut target = match reservation.as_local() { - Some(local) if self.body.local_kind(local) == LocalKind::Temp => local, + Some(local) if self.body_cache.local_kind(local) == LocalKind::Temp => local, _ => return None, }; // Next, look through the rest of the block, checking if we are assigning the // `target` (that is, the place that contains our borrow) to anything. let mut annotated_closure = None; - for stmt in &self.body[location.block].statements[location.statement_index + 1..] { + for stmt in &self.body_cache[location.block].statements[location.statement_index + 1..] { debug!( "annotate_argument_and_return_for_borrow: target={:?} stmt={:?}", target, stmt @@ -1861,7 +1859,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } // Check the terminator if we didn't find anything in the statements. - let terminator = &self.body[location.block].terminator(); + let terminator = &self.body_cache[location.block].terminator(); debug!( "annotate_argument_and_return_for_borrow: target={:?} terminator={:?}", target, terminator diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index a555e0b74c2..8267e5c1c4b 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -39,7 +39,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ) { debug!("add_moved_or_invoked_closure_note: location={:?} place={:?}", location, place); let mut target = place.local_or_deref_local(); - for stmt in &self.body[location.block].statements[location.statement_index..] { + for stmt in &self.body_cache[location.block].statements[location.statement_index..] { debug!("add_moved_or_invoked_closure_note: stmt={:?} target={:?}", stmt, target); if let StatementKind::Assign(box(into, Rvalue::Use(from))) = &stmt.kind { debug!("add_fnonce_closure_note: into={:?} from={:?}", into, from); @@ -53,7 +53,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } // Check if we are attempting to call a closure after it has been invoked. - let terminator = self.body[location.block].terminator(); + let terminator = self.body_cache[location.block].terminator(); debug!("add_moved_or_invoked_closure_note: terminator={:?}", terminator); if let TerminatorKind::Call { func: Operand::Constant(box Constant { @@ -76,7 +76,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { }; debug!("add_moved_or_invoked_closure_note: closure={:?}", closure); - if let ty::Closure(did, _) = self.body.local_decls[closure].ty.kind { + if let ty::Closure(did, _) = self.body_cache.local_decls[closure].ty.kind { let hir_id = self.infcx.tcx.hir().as_local_hir_id(did).unwrap(); if let Some((span, name)) = self.infcx.tcx.typeck_tables_of(did) @@ -99,7 +99,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // Check if we are just moving a closure after it has been invoked. if let Some(target) = target { - if let ty::Closure(did, _) = self.body.local_decls[target].ty.kind { + if let ty::Closure(did, _) = self.body_cache.local_decls[target].ty.kind { let hir_id = self.infcx.tcx.hir().as_local_hir_id(did).unwrap(); if let Some((span, name)) = self.infcx.tcx.typeck_tables_of(did) @@ -332,7 +332,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { /// Appends end-user visible description of the `local` place to `buf`. If `local` doesn't have /// a name, or its name was generated by the compiler, then `Err` is returned fn append_local_to_string(&self, local: Local, buf: &mut String) -> Result<(), ()> { - let decl = &self.body.local_decls[local]; + let decl = &self.body_cache.local_decls[local]; match self.local_names[local] { Some(name) if !decl.from_compiler_desugaring() => { buf.push_str(&name.as_str()); @@ -350,7 +350,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { base: PlaceBase::Local(local), projection: [], } => { - let local = &self.body.local_decls[*local]; + let local = &self.body_cache.local_decls[*local]; self.describe_field_from_ty(&local.ty, field, None) } PlaceRef { @@ -370,7 +370,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } ProjectionElem::Downcast(_, variant_index) => { let base_ty = - Place::ty_from(place.base, place.projection, self.body, self.infcx.tcx).ty; + Place::ty_from(place.base, place.projection, self.body_cache.body(), self.infcx.tcx).ty; self.describe_field_from_ty(&base_ty, field, Some(*variant_index)) } ProjectionElem::Field(_, field_type) => { @@ -481,7 +481,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { _ => continue, }; - let bbd = &self.body[loc.block]; + let bbd = &self.body_cache[loc.block]; let is_terminator = bbd.statements.len() == loc.statement_index; debug!( "borrowed_content_source: loc={:?} is_terminator={:?}", @@ -499,7 +499,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { .. }) = bbd.terminator { if let Some(source) - = BorrowedContentSource::from_call(func.ty(self.body, tcx), tcx) + = BorrowedContentSource::from_call(func.ty(self.body_cache.body(), tcx), tcx) { return source; } @@ -512,7 +512,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // If we didn't find an overloaded deref or index, then assume it's a // built in deref and check the type of the base. - let base_ty = Place::ty_from(deref_base.base, deref_base.projection, self.body, tcx).ty; + let base_ty = Place::ty_from(deref_base.base, deref_base.projection, self.body_cache.body(), tcx).ty; if base_ty.is_unsafe_ptr() { BorrowedContentSource::DerefRawPointer } else if base_ty.is_mutable_ptr() { @@ -767,9 +767,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ) -> UseSpans { use self::UseSpans::*; - let stmt = match self.body[location.block].statements.get(location.statement_index) { + let stmt = match self.body_cache[location.block].statements.get(location.statement_index) { Some(stmt) => stmt, - None => return OtherUse(self.body.source_info(location).span), + None => return OtherUse(self.body_cache.source_info(location).span), }; debug!("move_spans: moved_place={:?} location={:?} stmt={:?}", moved_place, location, stmt); @@ -807,7 +807,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { use self::UseSpans::*; debug!("borrow_spans: use_span={:?} location={:?}", use_span, location); - let target = match self.body[location.block] + let target = match self.body_cache[location.block] .statements .get(location.statement_index) { @@ -824,12 +824,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { _ => return OtherUse(use_span), }; - if self.body.local_kind(target) != LocalKind::Temp { + if self.body_cache.local_kind(target) != LocalKind::Temp { // operands are always temporaries. return OtherUse(use_span); } - for stmt in &self.body[location.block].statements[location.statement_index + 1..] { + for stmt in &self.body_cache[location.block].statements[location.statement_index + 1..] { if let StatementKind::Assign( box(_, Rvalue::Aggregate(ref kind, ref places)) ) = stmt.kind { @@ -901,7 +901,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { /// Helper to retrieve span(s) of given borrow from the current MIR /// representation pub(super) fn retrieve_borrow_spans(&self, borrow: &BorrowData<'_>) -> UseSpans { - let span = self.body.source_info(borrow.reserve_location).span; + let span = self.body_cache.source_info(borrow.reserve_location).span; self.borrow_spans(span, borrow.reserve_location) } } diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index f861a423ae2..0c1b0c4e14e 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -10,7 +10,7 @@ use rustc::lint::builtin::{MUTABLE_BORROW_RESERVATION_CONFLICT}; use rustc::mir::{AggregateKind, BasicBlock, BorrowCheckResult, BorrowKind}; use rustc::mir::{ ClearCrossCrate, Local, Location, Body, BodyCache, Mutability, Operand, Place, PlaceBase, - PlaceElem, PlaceRef, Static, StaticKind + PlaceElem, PlaceRef, ReadOnlyBodyCache, Static, StaticKind }; use rustc::mir::{Field, ProjectionElem, Promoted, Rvalue, Statement, StatementKind}; use rustc::mir::{Terminator, TerminatorKind}; @@ -163,16 +163,19 @@ fn do_mir_borrowck<'a, 'tcx>( // be modified (in place) to contain non-lexical lifetimes. It // will have a lifetime tied to the inference context. let mut body: Body<'tcx> = input_body.clone(); - let mut promoted: IndexVec> = input_promoted.clone(); + // TODO(pfaria) this very likely won't work because + let promoted: IndexVec> = input_promoted.clone(); + let mut promoted_cache: IndexVec>> = promoted.iter_mut().map(|body| BodyCache::new(body)).collect(); + let mut body_cache = BodyCache::new(&mut body); let free_regions = - nll::replace_regions_in_mir(infcx, def_id, param_env, &mut body, &mut promoted); + nll::replace_regions_in_mir(infcx, def_id, param_env, &mut body_cache, &mut promoted_cache); + let body_cache = BodyCache::new(&body).read_only(); // no further changes - let body_cache = &BodyCache::new(&body); // no further changes - let location_table = &LocationTable::new(body_cache); + let location_table = &LocationTable::new(&body_cache); let mut errors_buffer = Vec::new(); let (move_data, move_errors): (MoveData<'tcx>, Option, MoveError<'tcx>)>>) = - match MoveData::gather_moves(body_cache, tcx) { + match MoveData::gather_moves(&body_cache, tcx) { Ok(move_data) => (move_data, None), Err((move_data, move_errors)) => (move_data, Some(move_errors)), }; @@ -185,24 +188,24 @@ fn do_mir_borrowck<'a, 'tcx>( let dead_unwinds = BitSet::new_empty(body_cache.basic_blocks().len()); let mut flow_inits = FlowAtLocation::new(do_dataflow( tcx, - body_cache, + &body_cache, def_id, &attributes, &dead_unwinds, - MaybeInitializedPlaces::new(tcx, body_cache, &mdpe), + MaybeInitializedPlaces::new(tcx, &body_cache, &mdpe), |bd, i| DebugFormatted::new(&bd.move_data().move_paths[i]), )); let locals_are_invalidated_at_exit = tcx.hir().body_owner_kind(id).is_fn_or_closure(); let borrow_set = Rc::new(BorrowSet::build( - tcx, body_cache, locals_are_invalidated_at_exit, &mdpe.move_data)); + tcx, &body_cache, locals_are_invalidated_at_exit, &mdpe.move_data)); // If we are in non-lexical mode, compute the non-lexical lifetimes. let (regioncx, polonius_output, opt_closure_req) = nll::compute_regions( infcx, def_id, free_regions, - body_cache, + &body_cache, &promoted, &local_names, &upvars, @@ -223,29 +226,29 @@ fn do_mir_borrowck<'a, 'tcx>( let flow_borrows = FlowAtLocation::new(do_dataflow( tcx, - body_cache, + &body_cache, def_id, &attributes, &dead_unwinds, - Borrows::new(tcx, body_cache, param_env, regioncx.clone(), &borrow_set), + Borrows::new(tcx, &body_cache, param_env, regioncx.clone(), &borrow_set), |rs, i| DebugFormatted::new(&rs.location(i)), )); let flow_uninits = FlowAtLocation::new(do_dataflow( tcx, - body_cache, + &body_cache, def_id, &attributes, &dead_unwinds, - MaybeUninitializedPlaces::new(tcx, body_cache, &mdpe), + MaybeUninitializedPlaces::new(tcx, &body_cache, &mdpe), |bd, i| DebugFormatted::new(&bd.move_data().move_paths[i]), )); let flow_ever_inits = FlowAtLocation::new(do_dataflow( tcx, - body_cache, + &body_cache, def_id, &attributes, &dead_unwinds, - EverInitializedPlaces::new(tcx, body_cache, &mdpe), + EverInitializedPlaces::new(tcx, &body_cache, &mdpe), |bd, i| DebugFormatted::new(&bd.move_data().inits[i]), )); @@ -302,7 +305,7 @@ fn do_mir_borrowck<'a, 'tcx>( mbcx.report_conflicting_borrow(location, (&place, span), bk, &borrow); let scope = mbcx.body.source_info(location).scope; - let lint_root = match &mbcx.body.source_scopes[scope].local_data { + let lint_root = match &mbcx.body_cache.source_scopes[scope].local_data { ClearCrossCrate::Set(data) => data.lint_root, _ => id, }; @@ -324,21 +327,21 @@ fn do_mir_borrowck<'a, 'tcx>( // would have a chance of erroneously adding non-user-defined mutable vars // to the set. let temporary_used_locals: FxHashSet = mbcx.used_mut.iter() - .filter(|&local| !mbcx.body.local_decls[*local].is_user_variable()) + .filter(|&local| !mbcx.body_cache.local_decls[*local].is_user_variable()) .cloned() .collect(); // For the remaining unused locals that are marked as mutable, we avoid linting any that // were never initialized. These locals may have been removed as unreachable code; or will be // linted as unused variables. - let unused_mut_locals = mbcx.body.mut_vars_iter() + let unused_mut_locals = mbcx.body_cache.mut_vars_iter() .filter(|local| !mbcx.used_mut.contains(local)) .collect(); mbcx.gather_used_muts(temporary_used_locals, unused_mut_locals); debug!("mbcx.used_mut: {:?}", mbcx.used_mut); let used_mut = mbcx.used_mut; - for local in mbcx.body.mut_vars_and_args_iter().filter(|local| !used_mut.contains(local)) { - let local_decl = &mbcx.body.local_decls[local]; + for local in mbcx.body_cache.mut_vars_and_args_iter().filter(|local| !used_mut.contains(local)) { + let local_decl = &mbcx.body_cache.local_decls[local]; let lint_root = match &mbcx.body.source_scopes[local_decl.source_info.scope].local_data { ClearCrossCrate::Set(data) => data.lint_root, _ => continue, @@ -399,7 +402,7 @@ fn do_mir_borrowck<'a, 'tcx>( crate struct MirBorrowckCtxt<'cx, 'tcx> { crate infcx: &'cx InferCtxt<'cx, 'tcx>, - body_cache: BodyCache<&'cx Body<'tcx>>, + body_cache: ReadOnlyBodyCache<'cx, 'tcx>, mir_def_id: DefId, param_env: ty::ParamEnv<'tcx>, move_data: &'cx MoveData<'tcx>, @@ -490,7 +493,7 @@ impl<'cx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx, 'tcx type FlowState = Flows<'cx, 'tcx>; fn body(&self) -> &'cx Body<'tcx> { - self.body_cache + &self.body_cache } fn visit_block_entry(&mut self, bb: BasicBlock, flow_state: &Self::FlowState) { @@ -640,7 +643,7 @@ impl<'cx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx, 'tcx let tcx = self.infcx.tcx; // Compute the type with accurate region information. - let drop_place_ty = drop_place.ty(self.body_cache, self.infcx.tcx); + let drop_place_ty = drop_place.ty(self.body_cache.body(), self.infcx.tcx); // Erase the regions. let drop_place_ty = self.infcx.tcx.erase_regions(&drop_place_ty).ty; @@ -984,7 +987,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let mut error_reported = false; let tcx = self.infcx.tcx; - let body = self.body_cache; + let body = self.body_cache.body(); let param_env = self.param_env; let location_table = self.location_table.start_index(location); let borrow_set = self.borrow_set.clone(); @@ -1150,7 +1153,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // (e.g., `x = ...`) so long as it has never been initialized // before (at this point in the flow). if let Some(local) = place_span.0.as_local() { - if let Mutability::Not = self.body.local_decls[local].mutability { + if let Mutability::Not = self.body+cache.local_decls[local].mutability { // check for reassignments to immutable local variables self.check_if_reassignment_to_immutable_state( location, @@ -1303,7 +1306,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { match *operand { Operand::Move(ref place) | Operand::Copy(ref place) => { match place.as_local() { - Some(local) if !self.body.local_decls[local].is_user_variable() => { + Some(local) if !self.body_cache.local_decls[local].is_user_variable() => { if self.body.local_decls[local].ty.is_mutable_ptr() { // The variable will be marked as mutable by the borrow. return; @@ -1335,7 +1338,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { _ => bug!("temporary initialized in arguments"), }; - let bbd = &self.body[loc.block]; + let bbd = &self.body_cache[loc.block]; let stmt = &bbd.statements[loc.statement_index]; debug!("temporary assigned in: stmt={:?}", stmt); @@ -1454,7 +1457,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { if places_conflict::borrow_conflicts_with_place( self.infcx.tcx, self.param_env, - self.body, + &self.body_cache, place, borrow.kind, root_place, @@ -1534,7 +1537,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { if let Some(init_index) = self.is_local_ever_initialized(local, flow_state) { // And, if so, report an error. let init = &self.move_data.inits[init_index]; - let span = init.span(&self.body); + let span = init.span(&self.body_cache); self.report_illegal_reassignment( location, place_span, span, place_span.0 ); @@ -1745,7 +1748,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // assigning to `P.f` requires `P` itself // be already initialized let tcx = self.infcx.tcx; - let base_ty = Place::ty_from(&place.base, proj_base, self.body, tcx).ty; + let base_ty = Place::ty_from(&place.base, proj_base, self.body(), tcx).ty; match base_ty.kind { ty::Adt(def, _) if def.has_dtor(tcx) => { self.check_if_path_or_subpath_is_moved( @@ -1852,12 +1855,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // of the union - we should error in that case. let tcx = this.infcx.tcx; if let ty::Adt(def, _) = - Place::ty_from(base.base, base.projection, this.body, tcx).ty.kind + Place::ty_from(base.base, base.projection, this.body(), tcx).ty.kind { if def.is_union() { if this.move_data.path_map[mpi].iter().any(|moi| { this.move_data.moves[*moi].source.is_predecessor_of( - location, this.body, + location, &this.body_cache, ) }) { return; @@ -2061,7 +2064,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { base: PlaceBase::Local(local), projection: [], } => { - let local = &self.body.local_decls[*local]; + let local = &self.body_cache.local_decls[*local]; match local.mutability { Mutability::Not => match is_local_mutation_allowed { LocalMutationIsAllowed::Yes => Ok(RootPlace { @@ -2122,7 +2125,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { match elem { ProjectionElem::Deref => { let base_ty = - Place::ty_from(place.base, proj_base, self.body, self.infcx.tcx).ty; + Place::ty_from(place.base, proj_base, self.body(), self.infcx.tcx).ty; // Check the kind of deref to decide match base_ty.kind { @@ -2262,7 +2265,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { match place_projection { [base @ .., ProjectionElem::Field(field, _ty)] => { let tcx = self.infcx.tcx; - let base_ty = Place::ty_from(place_ref.base, base, self.body, tcx).ty; + let base_ty = Place::ty_from(place_ref.base, base, self.body(), tcx).ty; if (base_ty.is_closure() || base_ty.is_generator()) && (!by_ref || self.upvars[field.index()].by_ref) { diff --git a/src/librustc_mir/borrow_check/move_errors.rs b/src/librustc_mir/borrow_check/move_errors.rs index bf61eb9f0c5..5907da09c67 100644 --- a/src/librustc_mir/borrow_check/move_errors.rs +++ b/src/librustc_mir/borrow_check/move_errors.rs @@ -90,13 +90,13 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { // flow could be used. if let Some(StatementKind::Assign( box(place, Rvalue::Use(Operand::Move(move_from))) - )) = self.body.basic_blocks()[location.block] + )) = self.body_cache.basic_blocks()[location.block] .statements .get(location.statement_index) .map(|stmt| &stmt.kind) { if let Some(local) = place.as_local() { - let local_decl = &self.body.local_decls[local]; + let local_decl = &self.body_cache.local_decls[local]; // opt_match_place is the // match_span is the span of the expression being matched on // match *x.y { ... } match_place is Some(*x.y) @@ -112,7 +112,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { pat_span: _, }, ))) = local_decl.local_info { - let stmt_source_info = self.body.source_info(location); + let stmt_source_info = self.body_cache.source_info(location); self.append_binding_error( grouped_errors, kind, @@ -300,7 +300,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { // Inspect the type of the content behind the // borrow to provide feedback about why this // was a move rather than a copy. - let ty = deref_target_place.ty(self.body, self.infcx.tcx).ty; + let ty = deref_target_place.ty(self.body_cache.body(), self.infcx.tcx).ty; let upvar_field = self.prefixes(move_place.as_ref(), PrefixSet::All) .find_map(|p| self.is_upvar_field_projection(p)); @@ -318,7 +318,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { base: PlaceBase::Local(local), projection: [], } = deref_base { - let decl = &self.body.local_decls[*local]; + let decl = &self.body_cache.local_decls[*local]; if decl.is_ref_for_guard() { let mut err = self.cannot_move_out_of( span, @@ -411,7 +411,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { }; let move_ty = format!( "{:?}", - move_place.ty(self.body, self.infcx.tcx).ty, + move_place.ty(self.body_cache.body(), self.infcx.tcx).ty, ); if let Ok(snippet) = self.infcx.tcx.sess.source_map().span_to_snippet(span) { let is_option = move_ty.starts_with("std::option::Option"); @@ -454,7 +454,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { } if binds_to.is_empty() { - let place_ty = move_from.ty(self.body, self.infcx.tcx).ty; + let place_ty = move_from.ty(self.body_cache.body(), self.infcx.tcx).ty; let place_desc = match self.describe_place(move_from.as_ref()) { Some(desc) => format!("`{}`", desc), None => format!("value"), @@ -482,7 +482,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { // No binding. Nothing to suggest. GroupedMoveError::OtherIllegalMove { ref original_path, use_spans, .. } => { let span = use_spans.var_or_use(); - let place_ty = original_path.ty(self.body, self.infcx.tcx).ty; + let place_ty = original_path.ty(self.body_cache.body(), self.infcx.tcx).ty; let place_desc = match self.describe_place(original_path.as_ref()) { Some(desc) => format!("`{}`", desc), None => format!("value"), @@ -510,7 +510,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { ) { let mut suggestions: Vec<(Span, &str, String)> = Vec::new(); for local in binds_to { - let bind_to = &self.body.local_decls[*local]; + let bind_to = &self.body_cache.local_decls[*local]; if let LocalInfo::User( ClearCrossCrate::Set(BindingForm::Var(VarBindingForm { pat_span, @@ -559,7 +559,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { binds_to: &[Local], ) { for (j, local) in binds_to.into_iter().enumerate() { - let bind_to = &self.body.local_decls[*local]; + let bind_to = &self.body_cache.local_decls[*local]; let binding_span = bind_to.source_info.span; if j == 0 { diff --git a/src/librustc_mir/borrow_check/mutability_errors.rs b/src/librustc_mir/borrow_check/mutability_errors.rs index bf070c3f07d..654666882cc 100644 --- a/src/librustc_mir/borrow_check/mutability_errors.rs +++ b/src/librustc_mir/borrow_check/mutability_errors.rs @@ -61,7 +61,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { projection: [proj_base @ .., ProjectionElem::Field(upvar_index, _)], } => { debug_assert!(is_closure_or_generator( - Place::ty_from(&the_place_err.base, proj_base, self.body, self.infcx.tcx).ty + Place::ty_from(&the_place_err.base, proj_base, self.body_cache.body(), self.infcx.tcx).ty )); item_msg = format!("`{}`", access_place_desc.unwrap()); @@ -106,12 +106,12 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { proj_base.is_empty() && !self.upvars.is_empty() { item_msg = format!("`{}`", access_place_desc.unwrap()); - debug_assert!(self.body.local_decls[Local::new(1)].ty.is_region_ptr()); + debug_assert!(self.body_cache.local_decls[Local::new(1)].ty.is_region_ptr()); debug_assert!(is_closure_or_generator( Place::ty_from( the_place_err.base, the_place_err.projection, - self.body, + self.body_cache.body(), self.infcx.tcx ) .ty @@ -225,7 +225,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { if let Some((span, message)) = annotate_struct_field( self.infcx.tcx, - Place::ty_from(base, proj_base, self.body, self.infcx.tcx).ty, + Place::ty_from(base, proj_base, self.body_cache.body(), self.infcx.tcx).ty, field, ) { err.span_suggestion( @@ -242,7 +242,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { base: PlaceBase::Local(local), projection: [], } if { - self.body.local_decls.get(*local).map(|local_decl| { + self.body_cache.local_decls.get(*local).map(|local_decl| { if let LocalInfo::User(ClearCrossCrate::Set( mir::BindingForm::ImplicitSelf(kind) )) = local_decl.local_info { @@ -277,12 +277,12 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { PlaceRef { base: PlaceBase::Local(local), projection: [], - } if self.body.local_decls[*local].can_be_made_mutable() => { + } if self.body_cache.local_decls[*local].can_be_made_mutable() => { // ... but it doesn't make sense to suggest it on // variables that are `ref x`, `ref mut x`, `&self`, // or `&mut self` (such variables are simply not // mutable). - let local_decl = &self.body.local_decls[*local]; + let local_decl = &self.body_cache.local_decls[*local]; assert_eq!(local_decl.mutability, Mutability::Not); err.span_label(span, format!("cannot {ACT}", ACT = act)); @@ -300,7 +300,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { projection: [proj_base @ .., ProjectionElem::Field(upvar_index, _)], } => { debug_assert!(is_closure_or_generator( - Place::ty_from(base, proj_base, self.body, self.infcx.tcx).ty + Place::ty_from(base, proj_base, self.body_cache.body(), self.infcx.tcx).ty )); err.span_label(span, format!("cannot {ACT}", ACT = act)); @@ -346,7 +346,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { PlaceRef { base: PlaceBase::Local(local), projection: [ProjectionElem::Deref], - } if self.body.local_decls[*local].is_ref_for_guard() => { + } if self.body_cache.local_decls[*local].is_ref_for_guard() => { err.span_label(span, format!("cannot {ACT}", ACT = act)); err.note( "variables bound in patterns are immutable until the end of the pattern guard", @@ -363,7 +363,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { projection: [ProjectionElem::Deref], } if self.body.local_decls[*local].is_user_variable() => { - let local_decl = &self.body.local_decls[*local]; + let local_decl = &self.body_cache.local_decls[*local]; let suggestion = match local_decl.local_info { LocalInfo::User(ClearCrossCrate::Set(mir::BindingForm::ImplicitSelf(_))) => { Some(suggest_ampmut_self(self.infcx.tcx, local_decl)) @@ -377,7 +377,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { }, ))) => Some(suggest_ampmut( self.infcx.tcx, - self.body, + &self.body_cache, *local, local_decl, opt_ty_info, @@ -451,7 +451,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { { err.span_label(span, format!("cannot {ACT}", ACT = act)); err.span_help( - self.body.span, + self.body_cache.span, "consider changing this to accept closures that implement `FnMut`" ); } diff --git a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs index c7058531958..4097bfeeb35 100644 --- a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs +++ b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs @@ -237,7 +237,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ); let regioncx = &self.nonlexical_regioncx; - let body = self.body; + let body = self.body_cache.body(); let tcx = self.infcx.tcx; let borrow_region_vid = borrow.region; @@ -297,9 +297,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { if let Some(region) = regioncx.to_error_region_vid(borrow_region_vid) { let (category, from_closure, span, region_name) = self.nonlexical_regioncx.free_region_constraint_info( - self.body, - &self.local_names, - &self.upvars, + &self.body_cache, + &self.local_names, + &self.upvars, self.mir_def_id, self.infcx, borrow_region_vid, @@ -365,7 +365,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { return outmost_back_edge; } - let block = &self.body.basic_blocks()[location.block]; + let block = &self.body_cache.basic_blocks()[location.block]; if location.statement_index < block.statements.len() { let successor = location.successor_within_block(); @@ -427,7 +427,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } if loop_head.dominates(from, &self.dominators) { - let block = &self.body.basic_blocks()[from.block]; + let block = &self.body_cache.basic_blocks()[from.block]; if from.statement_index < block.statements.len() { let successor = from.successor_within_block(); @@ -475,7 +475,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { (LaterUseKind::ClosureCapture, var_span) } UseSpans::OtherUse(span) => { - let block = &self.body.basic_blocks()[location.block]; + let block = &self.body_cache.basic_blocks()[location.block]; let kind = if let Some(&Statement { kind: StatementKind::FakeRead(FakeReadCause::ForLet, _), @@ -498,7 +498,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { Operand::Copy(place) | Operand::Move(place) => { if let Some(l) = place.as_local() { - let local_decl = &self.body.local_decls[l]; + let local_decl = &self.body_cache.local_decls[l]; if self.local_names[l].is_none() { local_decl.source_info.span } else { @@ -528,7 +528,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { fn was_captured_by_trait_object(&self, borrow: &BorrowData<'tcx>) -> bool { // Start at the reserve location, find the place that we want to see cast to a trait object. let location = borrow.reserve_location; - let block = &self.body[location.block]; + let block = &self.body_cache[location.block]; let stmt = block.statements.get(location.statement_index); debug!( "was_captured_by_trait_object: location={:?} stmt={:?}", @@ -558,7 +558,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ); while let Some(current_location) = queue.pop() { debug!("was_captured_by_trait: target={:?}", target); - let block = &self.body[current_location.block]; + let block = &self.body_cache[current_location.block]; // We need to check the current location to find out if it is a terminator. let is_terminator = current_location.statement_index == block.statements.len(); if !is_terminator { diff --git a/src/librustc_mir/borrow_check/nll/invalidation.rs b/src/librustc_mir/borrow_check/nll/invalidation.rs index 1d429e3a6de..7cb5b839cee 100644 --- a/src/librustc_mir/borrow_check/nll/invalidation.rs +++ b/src/librustc_mir/borrow_check/nll/invalidation.rs @@ -11,7 +11,7 @@ use crate::borrow_check::path_utils::*; use crate::dataflow::indexes::BorrowIndex; use rustc::ty::{self, TyCtxt}; use rustc::mir::visit::Visitor; -use rustc::mir::{BasicBlock, Location, Body, Place, Rvalue}; +use rustc::mir::{BasicBlock, Location, Body, Place, ReadOnlyBodyCache, Rvalue}; use rustc::mir::{Statement, StatementKind}; use rustc::mir::TerminatorKind; use rustc::mir::{Operand, BorrowKind}; @@ -22,7 +22,7 @@ pub(super) fn generate_invalidates<'tcx>( param_env: ty::ParamEnv<'tcx>, all_facts: &mut Option, location_table: &LocationTable, - body: &Body<'tcx>, + body_cache: &ReadOnlyBodyCache<'_, 'tcx>, borrow_set: &BorrowSet<'tcx>, ) { if all_facts.is_none() { @@ -31,17 +31,17 @@ pub(super) fn generate_invalidates<'tcx>( } if let Some(all_facts) = all_facts { - let dominators = body.dominators(); + let dominators = body_cache.dominators(); let mut ig = InvalidationGenerator { all_facts, borrow_set, param_env, tcx, location_table, - body, + body: body_cache.body(), dominators, }; - ig.visit_body(body); + ig.visit_body(&body_cache); } } diff --git a/src/librustc_mir/borrow_check/nll/mod.rs b/src/librustc_mir/borrow_check/nll/mod.rs index 4d67b72c98c..dac5815fada 100644 --- a/src/librustc_mir/borrow_check/nll/mod.rs +++ b/src/librustc_mir/borrow_check/nll/mod.rs @@ -12,7 +12,8 @@ use crate::borrow_check::Upvar; use rustc::hir::def_id::DefId; use rustc::infer::InferCtxt; use rustc::mir::{ClosureOutlivesSubject, ClosureRegionRequirements, - Local, Location, Body, LocalKind, BasicBlock, Promoted}; + Local, Location, Body, BodyCache, LocalKind, BasicBlock, + Promoted, ReadOnlyBodyCache}; use rustc::ty::{self, RegionKind, RegionVid}; use rustc_index::vec::IndexVec; use rustc_errors::Diagnostic; @@ -54,8 +55,8 @@ pub(in crate::borrow_check) fn replace_regions_in_mir<'cx, 'tcx>( infcx: &InferCtxt<'cx, 'tcx>, def_id: DefId, param_env: ty::ParamEnv<'tcx>, - body: &mut Body<'tcx>, - promoted: &mut IndexVec>, + body_cache: &mut BodyCache<&mut Body<'tcx>>, + promoted: &mut IndexVec>>, ) -> UniversalRegions<'tcx> { debug!("replace_regions_in_mir(def_id={:?})", def_id); @@ -63,10 +64,10 @@ pub(in crate::borrow_check) fn replace_regions_in_mir<'cx, 'tcx>( let universal_regions = UniversalRegions::new(infcx, def_id, param_env); // Replace all remaining regions with fresh inference variables. - renumber::renumber_mir(infcx, body, promoted); + renumber::renumber_mir(infcx, body_cache, promoted); let source = MirSource::item(def_id); - mir_util::dump_mir(infcx.tcx, None, "renumber", &0, source, body, |_, _| Ok(())); + mir_util::dump_mir(infcx.tcx, None, "renumber", &0, source, body_cache, |_, _| Ok(())); universal_regions } @@ -157,7 +158,7 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>( infcx: &InferCtxt<'cx, 'tcx>, def_id: DefId, universal_regions: UniversalRegions<'tcx>, - body: &Body<'tcx>, + body_cache: &ReadOnlyBodyCache<'_, 'tcx>, promoted: &IndexVec>, local_names: &IndexVec>, upvars: &[Upvar], @@ -180,7 +181,7 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>( let universal_regions = Rc::new(universal_regions); - let elements = &Rc::new(RegionValueElements::new(body)); + let elements = &Rc::new(RegionValueElements::new(body_cache)); // Run the MIR type-checker. let MirTypeckResults { @@ -189,7 +190,7 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>( } = type_check::type_check( infcx, param_env, - body, + body_cache, promoted, def_id, &universal_regions, @@ -205,7 +206,7 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>( all_facts .universal_region .extend(universal_regions.universal_regions()); - populate_polonius_move_facts(all_facts, move_data, location_table, body); + populate_polonius_move_facts(all_facts, move_data, location_table, body_cache); } // Create the region inference context, taking ownership of the @@ -229,7 +230,7 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>( &mut liveness_constraints, &mut all_facts, location_table, - &body, + body_cache, borrow_set, ); @@ -238,7 +239,7 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>( universal_regions, placeholder_indices, universal_region_relations, - body, + body_cache, outlives_constraints, member_constraints, closure_bounds_mapping, @@ -253,7 +254,7 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>( param_env, &mut all_facts, location_table, - &body, + body_cache, borrow_set, ); @@ -283,21 +284,21 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>( // Solve the region constraints. let closure_region_requirements = - regioncx.solve(infcx, body, local_names, upvars, def_id, errors_buffer); + regioncx.solve(infcx, body_cache, local_names, upvars, def_id, errors_buffer); // Dump MIR results into a file, if that is enabled. This let us // write unit-tests, as well as helping with debugging. dump_mir_results( infcx, MirSource::item(def_id), - &body, + body_cache, ®ioncx, &closure_region_requirements, ); // We also have a `#[rustc_nll]` annotation that causes us to dump // information - dump_annotation(infcx, &body, def_id, ®ioncx, &closure_region_requirements, errors_buffer); + dump_annotation(infcx, body_cache, def_id, ®ioncx, &closure_region_requirements, errors_buffer); (regioncx, polonius_output, closure_region_requirements) } diff --git a/src/librustc_mir/borrow_check/nll/region_infer/values.rs b/src/librustc_mir/borrow_check/nll/region_infer/values.rs index 7a86536573d..5d1891c0bf6 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/values.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/values.rs @@ -1,4 +1,4 @@ -use rustc::mir::{BasicBlock, Location, Body}; +use rustc::mir::{BasicBlock, Location, Body, ReadOnlyBodyCache}; use rustc::ty::{self, RegionVid}; use rustc_index::bit_set::{HybridBitSet, SparseBitMatrix}; use rustc_data_structures::fx::FxHashMap; @@ -92,7 +92,7 @@ impl RegionValueElements { /// Pushes all predecessors of `index` onto `stack`. crate fn push_predecessors( &self, - body: &Body<'_>, + body_cache: &ReadOnlyBodyCache<'_, '_>, index: PointIndex, stack: &mut Vec, ) { @@ -104,9 +104,9 @@ impl RegionValueElements { // If this is a basic block head, then the predecessors are // the terminators of other basic blocks stack.extend( - body.predecessors_for(block) + body_cache.predecessors_for(block) .iter() - .map(|&pred_bb| body.terminator_loc(pred_bb)) + .map(|&pred_bb| body_cache.terminator_loc(pred_bb)) .map(|pred_loc| self.point_from_location(pred_loc)), ); } else { diff --git a/src/librustc_mir/borrow_check/nll/renumber.rs b/src/librustc_mir/borrow_check/nll/renumber.rs index d949c7e01aa..57e977eacba 100644 --- a/src/librustc_mir/borrow_check/nll/renumber.rs +++ b/src/librustc_mir/borrow_check/nll/renumber.rs @@ -1,6 +1,6 @@ use rustc::ty::subst::SubstsRef; use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; -use rustc::mir::{Body, Location, PlaceElem, Promoted}; +use rustc::mir::{Body, BodyCache, Location, PlaceElem, Promoted}; use rustc::mir::visit::{MutVisitor, TyContext}; use rustc::infer::{InferCtxt, NLLRegionVariableOrigin}; use rustc_index::vec::IndexVec; @@ -9,11 +9,11 @@ use rustc_index::vec::IndexVec; /// inference variables, returning the number of variables created. pub fn renumber_mir<'tcx>( infcx: &InferCtxt<'_, 'tcx>, - body: &mut Body<'tcx>, - promoted: &mut IndexVec>, + body_cache: &mut BodyCache<&mut Body<'tcx>>, + promoted: &mut IndexVec>>, ) { debug!("renumber_mir()"); - debug!("renumber_mir: body.arg_count={:?}", body.arg_count); + debug!("renumber_mir: body.arg_count={:?}", body_cache.arg_count); let mut visitor = NLLVisitor { infcx }; @@ -21,7 +21,7 @@ pub fn renumber_mir<'tcx>( visitor.visit_body(body); } - visitor.visit_body(body); + visitor.visit_body(body_cache); } /// Replaces all regions appearing in `value` with fresh inference diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index 4f95aa4a7b0..2de9f0e1282 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -115,7 +115,7 @@ mod relate_tys; pub(crate) fn type_check<'tcx>( infcx: &InferCtxt<'_, 'tcx>, param_env: ty::ParamEnv<'tcx>, - body: &Body<'tcx>, + body_cache: &ReadOnlyBodyCache<'_, 'tcx>, promoted: &IndexVec>, mir_def_id: DefId, universal_regions: &Rc>, @@ -161,15 +161,15 @@ pub(crate) fn type_check<'tcx>( infcx, mir_def_id, param_env, - body, + body_cache, promoted, ®ion_bound_pairs, implicit_region_bound, &mut borrowck_context, &universal_region_relations, |mut cx| { - cx.equate_inputs_and_outputs(body, universal_regions, &normalized_inputs_and_output); - liveness::generate(&mut cx, body, elements, flow_inits, move_data, location_table); + cx.equate_inputs_and_outputs(body_cache, universal_regions, &normalized_inputs_and_output); + liveness::generate(&mut cx, body_cache, elements, flow_inits, move_data, location_table); translate_outlives_facts(cx.borrowck_context); }, @@ -185,7 +185,7 @@ fn type_check_internal<'a, 'tcx, R>( infcx: &'a InferCtxt<'a, 'tcx>, mir_def_id: DefId, param_env: ty::ParamEnv<'tcx>, - body: &'a Body<'tcx>, + body_cache: &ReadOnlyBodyCache<'a, 'tcx>, promoted: &'a IndexVec>, region_bound_pairs: &'a RegionBoundPairs<'tcx>, implicit_region_bound: ty::Region<'tcx>, @@ -195,7 +195,7 @@ fn type_check_internal<'a, 'tcx, R>( ) -> R where { let mut checker = TypeChecker::new( infcx, - body, + body_cache, mir_def_id, param_env, region_bound_pairs, @@ -204,14 +204,14 @@ fn type_check_internal<'a, 'tcx, R>( universal_region_relations, ); let errors_reported = { - let mut verifier = TypeVerifier::new(&mut checker, body, promoted); - verifier.visit_body(body); + let mut verifier = TypeVerifier::new(&mut checker, body_cache, promoted); + verifier.visit_body(body_cache); verifier.errors_reported }; if !errors_reported { // if verifier failed, don't do further checks to avoid ICEs - checker.typeck_mir(body); + checker.typeck_mir(body_cache); } extra(&mut checker) @@ -385,7 +385,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> { } } - fn visit_body(&mut self, body_cache: &BodyCache<&'_ Body<'tcx>>) { + fn visit_body(&mut self, body_cache: &ReadOnlyBodyCache<'_, 'tcx>) { self.sanitize_type(&"return type", body_cache.return_ty()); for local_decl in &body_cache.local_decls { self.sanitize_type(local_decl, local_decl.ty); diff --git a/src/librustc_mir/borrow_check/prefixes.rs b/src/librustc_mir/borrow_check/prefixes.rs index 57833cac9cb..aa02c0641e3 100644 --- a/src/librustc_mir/borrow_check/prefixes.rs +++ b/src/librustc_mir/borrow_check/prefixes.rs @@ -56,7 +56,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { Prefixes { next: Some(place_ref), kind, - body: self.body, + body: &self.body_cache, tcx: self.infcx.tcx, } } diff --git a/src/librustc_mir/borrow_check/used_muts.rs b/src/librustc_mir/borrow_check/used_muts.rs index 95471afb788..430452efe42 100644 --- a/src/librustc_mir/borrow_check/used_muts.rs +++ b/src/librustc_mir/borrow_check/used_muts.rs @@ -32,7 +32,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { never_initialized_mut_locals: &mut never_initialized_mut_locals, mbcx: self, }; - visitor.visit_body(visitor.mbcx.body); + visitor.visit_body(&visitor.mbcx.body_cache); } // Take the union of the existed `used_mut` set with those variables we've found were