1
Fork 0

Fix a large number of Body -> (ReadOnly)BodyCache type errors, add predecessor_locations fn to ReadOnlyBodyCache

This commit is contained in:
Paul Daniel Faria 2019-10-24 00:38:01 -04:00
parent 2eed90a621
commit ab98c595ea
15 changed files with 206 additions and 182 deletions

View file

@ -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<Item = Location> + '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 { impl Cache {
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {
@ -80,27 +115,9 @@ impl Cache {
} }
#[inline] #[inline]
pub fn predecessor_locations<'a>(&'a mut self, loc: Location, body: &'a Body<'a>) -> impl Iterator<Item = Location> + 'a { impl_predecessor_locations!((pub) predecessor_locations mut);
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
};
let if_not_zero_locations = if loc.statement_index == 0 { impl_predecessor_locations!(() unwrap_predecessor_locations);
None
} else {
Some(Location { block: loc.block, statement_index: loc.statement_index - 1 })
};
if_zero_locations.into_iter().flatten().chain(if_not_zero_locations)
}
#[inline] #[inline]
pub fn basic_blocks_mut<'a, 'tcx>(&mut self, body: &'a mut Body<'tcx>) -> &'a mut IndexVec<BasicBlock, BasicBlockData<'tcx>> { pub fn basic_blocks_mut<'a, 'tcx>(&mut self, body: &'a mut Body<'tcx>) -> &'a mut IndexVec<BasicBlock, BasicBlockData<'tcx>> {
@ -240,6 +257,11 @@ impl ReadOnlyBodyCache<'a, 'tcx> {
self.cache.unwrap_predecessors_for(bb) self.cache.unwrap_predecessors_for(bb)
} }
#[inline]
pub fn predecessor_locations(&self, loc: Location) -> impl Iterator<Item = Location> + '_ {
self.cache.unwrap_predecessor_locations(loc, self.body)
}
#[inline] #[inline]
pub fn body(&self) -> &'a Body<'tcx> { pub fn body(&self) -> &'a Body<'tcx> {
self.body self.body

View file

@ -5,7 +5,7 @@ use crate::dataflow::indexes::BorrowIndex;
use crate::dataflow::move_paths::MoveData; use crate::dataflow::move_paths::MoveData;
use rustc::mir::traversal; use rustc::mir::traversal;
use rustc::mir::visit::{PlaceContext, Visitor, NonUseContext, MutatingUseContext}; 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::ty::{RegionVid, TyCtxt};
use rustc::util::nodemap::{FxHashMap, FxHashSet}; use rustc::util::nodemap::{FxHashMap, FxHashSet};
use rustc_index::vec::IndexVec; use rustc_index::vec::IndexVec;
@ -90,7 +90,7 @@ crate enum LocalsStateAtExit {
impl LocalsStateAtExit { impl LocalsStateAtExit {
fn build( fn build(
locals_are_invalidated_at_exit: bool, locals_are_invalidated_at_exit: bool,
body: &Body<'tcx>, body_cache: &ReadOnlyBodyCache<'_, 'tcx>,
move_data: &MoveData<'tcx> move_data: &MoveData<'tcx>
) -> Self { ) -> Self {
struct HasStorageDead(BitSet<Local>); struct HasStorageDead(BitSet<Local>);
@ -106,8 +106,8 @@ impl LocalsStateAtExit {
if locals_are_invalidated_at_exit { if locals_are_invalidated_at_exit {
LocalsStateAtExit::AllAreInvalidated LocalsStateAtExit::AllAreInvalidated
} else { } else {
let mut has_storage_dead = HasStorageDead(BitSet::new_empty(body.local_decls.len())); let mut has_storage_dead = HasStorageDead(BitSet::new_empty(body_cache.local_decls.len()));
has_storage_dead.visit_body(body); has_storage_dead.visit_body(body_cache);
let mut has_storage_dead_or_moved = has_storage_dead.0; let mut has_storage_dead_or_moved = has_storage_dead.0;
for move_out in &move_data.moves { for move_out in &move_data.moves {
if let Some(index) = move_data.base_local(move_out.path) { if let Some(index) = move_data.base_local(move_out.path) {
@ -123,23 +123,23 @@ impl LocalsStateAtExit {
impl<'tcx> BorrowSet<'tcx> { impl<'tcx> BorrowSet<'tcx> {
pub fn build( pub fn build(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
body: &Body<'tcx>, body_cache: &ReadOnlyBodyCache<'_, 'tcx>,
locals_are_invalidated_at_exit: bool, locals_are_invalidated_at_exit: bool,
move_data: &MoveData<'tcx>, move_data: &MoveData<'tcx>,
) -> Self { ) -> Self {
let mut visitor = GatherBorrows { let mut visitor = GatherBorrows {
tcx, tcx,
body, body: body_cache.body(),
idx_vec: IndexVec::new(), idx_vec: IndexVec::new(),
location_map: Default::default(), location_map: Default::default(),
activation_map: Default::default(), activation_map: Default::default(),
local_map: Default::default(), local_map: Default::default(),
pending_activations: Default::default(), pending_activations: Default::default(),
locals_state_at_exit: 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); visitor.visit_basic_block_data(block, block_data);
} }

View file

@ -206,7 +206,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
} }
let ty = 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; .ty;
let needs_note = match ty.kind { let needs_note = match ty.kind {
ty::Closure(id, _) => { 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 mpi = self.move_data.moves[move_out_indices[0]].path;
let place = &self.move_data.move_paths[mpi].place; 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 = let opt_name =
self.describe_place_with_options(place.as_ref(), IncludingDowncast(true)); self.describe_place_with_options(place.as_ref(), IncludingDowncast(true));
let note_msg = match opt_name { let note_msg = match opt_name {
@ -314,7 +314,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
None, None,
).add_explanation_to_diagnostic( ).add_explanation_to_diagnostic(
self.infcx.tcx, self.infcx.tcx,
self.body, &self.body_cache,
&self.local_names, &self.local_names,
&mut err, &mut err,
"", "",
@ -356,7 +356,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
self.explain_why_borrow_contains_point(location, borrow, None) self.explain_why_borrow_contains_point(location, borrow, None)
.add_explanation_to_diagnostic( .add_explanation_to_diagnostic(
self.infcx.tcx, self.infcx.tcx,
self.body, &self.body_cache,
&self.local_names, &self.local_names,
&mut err, &mut err,
"", "",
@ -578,7 +578,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
explanation.add_explanation_to_diagnostic( explanation.add_explanation_to_diagnostic(
self.infcx.tcx, self.infcx.tcx,
self.body, &self.body_cache,
&self.local_names, &self.local_names,
&mut err, &mut err,
first_borrow_desc, 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 // Define a small closure that we can use to check if the type of a place
// is a union. // is a union.
let union_ty = |place_base, place_projection| { 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) ty.ty_adt_def().filter(|adt| adt.is_union()).map(|_| ty)
}; };
let describe_place = |place| self.describe_place(place).unwrap_or_else(|| "_".to_owned()); 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()); assert!(root_place.projection.is_empty());
let proper_span = match root_place.base { 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, _ => drop_span,
}; };
@ -965,7 +965,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
} else { } else {
explanation.add_explanation_to_diagnostic( explanation.add_explanation_to_diagnostic(
self.infcx.tcx, self.infcx.tcx,
self.body, &self.body_cache,
&self.local_names, &self.local_names,
&mut err, &mut err,
"", "",
@ -991,7 +991,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
); );
explanation.add_explanation_to_diagnostic( 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 err
@ -1051,7 +1051,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
explanation.add_explanation_to_diagnostic( explanation.add_explanation_to_diagnostic(
self.infcx.tcx, self.infcx.tcx,
self.body, &self.body_cache,
&self.local_names, &self.local_names,
&mut err, &mut err,
"", "",
@ -1138,7 +1138,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
} }
explanation.add_explanation_to_diagnostic( explanation.add_explanation_to_diagnostic(
self.infcx.tcx, self.infcx.tcx,
self.body, &self.body_cache,
&self.local_names, &self.local_names,
&mut err, &mut err,
"", "",
@ -1174,7 +1174,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
}; };
// FIXME use a better heuristic than Spans // 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" "reference to"
} else { } else {
"value referencing" "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 (place_desc, note) = if let Some(place_desc) = opt_place_desc {
let local_kind = if let Some(local) = borrow.borrowed_place.as_local() { 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::ReturnPointer
| LocalKind::Temp => bug!("temporary or return pointer with a name"), | LocalKind::Temp => bug!("temporary or return pointer with a name"),
LocalKind::Var => "local variable ", LocalKind::Var => "local variable ",
@ -1215,7 +1215,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
} else { } else {
bug!("try_report_cannot_return_reference_to_local: not a local") 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 => ( LocalKind::ReturnPointer | LocalKind::Temp => (
"temporary value".to_string(), "temporary value".to_string(),
"temporary value created here".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<MoveSite> { fn get_moved_indexes(&mut self, location: Location, mpi: MovePathIndex) -> Vec<MoveSite> {
let body = self.body;
let mut stack = Vec::new(); 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); let is_back_edge = location.dominates(predecessor, &self.dominators);
(predecessor, is_back_edge) (predecessor, is_back_edge)
})); }));
@ -1394,7 +1392,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
} }
// check for moves // check for moves
let stmt_kind = body[location.block] let stmt_kind = self.body_cache[location.block]
.statements .statements
.get(location.statement_index) .get(location.statement_index)
.map(|s| &s.kind); .map(|s| &s.kind);
@ -1449,7 +1447,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
let mut any_match = false; let mut any_match = false;
drop_flag_effects::for_location_inits( drop_flag_effects::for_location_inits(
self.infcx.tcx, self.infcx.tcx,
self.body, &self.body_cache,
self.move_data, self.move_data,
location, location,
|m| { |m| {
@ -1462,7 +1460,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
continue 'dfs; 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); let back_edge = location.dominates(predecessor, &self.dominators);
(predecessor, is_back_edge || back_edge) (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) self.explain_why_borrow_contains_point(location, loan, None)
.add_explanation_to_diagnostic( .add_explanation_to_diagnostic(
self.infcx.tcx, self.infcx.tcx,
self.body, &self.body_cache,
&self.local_names, &self.local_names,
&mut err, &mut err,
"", "",
@ -1539,8 +1537,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
) { ) {
let (from_arg, local_decl, local_name) = match err_place.as_local() { let (from_arg, local_decl, local_name) = match err_place.as_local() {
Some(local) => ( Some(local) => (
self.body.local_kind(local) == LocalKind::Arg, self.body_cache.local_kind(local) == LocalKind::Arg,
Some(&self.body.local_decls[local]), Some(&self.body_cache.local_decls[local]),
self.local_names[local], self.local_names[local],
), ),
None => (false, None, None), None => (false, None, None),
@ -1625,7 +1623,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
StorageDeadOrDrop::LocalStorageDead StorageDeadOrDrop::LocalStorageDead
| StorageDeadOrDrop::BoxedStorageDead => { | StorageDeadOrDrop::BoxedStorageDead => {
assert!( 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" "Drop of value behind a reference or raw pointer"
); );
StorageDeadOrDrop::BoxedStorageDead StorageDeadOrDrop::BoxedStorageDead
@ -1633,7 +1631,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
StorageDeadOrDrop::Destructor(_) => base_access, StorageDeadOrDrop::Destructor(_) => base_access,
}, },
ProjectionElem::Field(..) | ProjectionElem::Downcast(..) => { 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 { match base_ty.kind {
ty::Adt(def, _) if def.has_dtor(tcx) => { ty::Adt(def, _) if def.has_dtor(tcx) => {
// Report the outermost adt with a destructor // Report the outermost adt with a destructor
@ -1721,7 +1719,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
location location
); );
if let Some(&Statement { kind: StatementKind::Assign(box(ref reservation, _)), ..}) 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!( debug!(
"annotate_argument_and_return_for_borrow: reservation={:?}", "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. // Check that the initial assignment of the reserve location is into a temporary.
let mut target = match reservation.as_local() { 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, _ => return None,
}; };
// Next, look through the rest of the block, checking if we are assigning the // 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. // `target` (that is, the place that contains our borrow) to anything.
let mut annotated_closure = None; 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!( debug!(
"annotate_argument_and_return_for_borrow: target={:?} stmt={:?}", "annotate_argument_and_return_for_borrow: target={:?} stmt={:?}",
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. // 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!( debug!(
"annotate_argument_and_return_for_borrow: target={:?} terminator={:?}", "annotate_argument_and_return_for_borrow: target={:?} terminator={:?}",
target, terminator target, terminator

View file

@ -39,7 +39,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
) { ) {
debug!("add_moved_or_invoked_closure_note: location={:?} place={:?}", location, place); debug!("add_moved_or_invoked_closure_note: location={:?} place={:?}", location, place);
let mut target = place.local_or_deref_local(); 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); debug!("add_moved_or_invoked_closure_note: stmt={:?} target={:?}", stmt, target);
if let StatementKind::Assign(box(into, Rvalue::Use(from))) = &stmt.kind { if let StatementKind::Assign(box(into, Rvalue::Use(from))) = &stmt.kind {
debug!("add_fnonce_closure_note: into={:?} from={:?}", into, from); 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. // 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); debug!("add_moved_or_invoked_closure_note: terminator={:?}", terminator);
if let TerminatorKind::Call { if let TerminatorKind::Call {
func: Operand::Constant(box Constant { func: Operand::Constant(box Constant {
@ -76,7 +76,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
}; };
debug!("add_moved_or_invoked_closure_note: closure={:?}", closure); 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(); 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) 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. // Check if we are just moving a closure after it has been invoked.
if let Some(target) = target { 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(); 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) 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 /// 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 /// 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<(), ()> { 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] { match self.local_names[local] {
Some(name) if !decl.from_compiler_desugaring() => { Some(name) if !decl.from_compiler_desugaring() => {
buf.push_str(&name.as_str()); buf.push_str(&name.as_str());
@ -350,7 +350,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
base: PlaceBase::Local(local), base: PlaceBase::Local(local),
projection: [], 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) self.describe_field_from_ty(&local.ty, field, None)
} }
PlaceRef { PlaceRef {
@ -370,7 +370,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
} }
ProjectionElem::Downcast(_, variant_index) => { ProjectionElem::Downcast(_, variant_index) => {
let base_ty = 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)) self.describe_field_from_ty(&base_ty, field, Some(*variant_index))
} }
ProjectionElem::Field(_, field_type) => { ProjectionElem::Field(_, field_type) => {
@ -481,7 +481,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
_ => continue, _ => continue,
}; };
let bbd = &self.body[loc.block]; let bbd = &self.body_cache[loc.block];
let is_terminator = bbd.statements.len() == loc.statement_index; let is_terminator = bbd.statements.len() == loc.statement_index;
debug!( debug!(
"borrowed_content_source: loc={:?} is_terminator={:?}", "borrowed_content_source: loc={:?} is_terminator={:?}",
@ -499,7 +499,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
.. ..
}) = bbd.terminator { }) = bbd.terminator {
if let Some(source) 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; 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 // 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. // 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() { if base_ty.is_unsafe_ptr() {
BorrowedContentSource::DerefRawPointer BorrowedContentSource::DerefRawPointer
} else if base_ty.is_mutable_ptr() { } else if base_ty.is_mutable_ptr() {
@ -767,9 +767,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
) -> UseSpans { ) -> UseSpans {
use self::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, 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); debug!("move_spans: moved_place={:?} location={:?} stmt={:?}", moved_place, location, stmt);
@ -807,7 +807,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
use self::UseSpans::*; use self::UseSpans::*;
debug!("borrow_spans: use_span={:?} location={:?}", use_span, location); 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 .statements
.get(location.statement_index) .get(location.statement_index)
{ {
@ -824,12 +824,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
_ => return OtherUse(use_span), _ => 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. // operands are always temporaries.
return OtherUse(use_span); 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( if let StatementKind::Assign(
box(_, Rvalue::Aggregate(ref kind, ref places)) box(_, Rvalue::Aggregate(ref kind, ref places))
) = stmt.kind { ) = stmt.kind {
@ -901,7 +901,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
/// Helper to retrieve span(s) of given borrow from the current MIR /// Helper to retrieve span(s) of given borrow from the current MIR
/// representation /// representation
pub(super) fn retrieve_borrow_spans(&self, borrow: &BorrowData<'_>) -> UseSpans { 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) self.borrow_spans(span, borrow.reserve_location)
} }
} }

View file

@ -10,7 +10,7 @@ use rustc::lint::builtin::{MUTABLE_BORROW_RESERVATION_CONFLICT};
use rustc::mir::{AggregateKind, BasicBlock, BorrowCheckResult, BorrowKind}; use rustc::mir::{AggregateKind, BasicBlock, BorrowCheckResult, BorrowKind};
use rustc::mir::{ use rustc::mir::{
ClearCrossCrate, Local, Location, Body, BodyCache, Mutability, Operand, Place, PlaceBase, 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::{Field, ProjectionElem, Promoted, Rvalue, Statement, StatementKind};
use rustc::mir::{Terminator, TerminatorKind}; 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 // be modified (in place) to contain non-lexical lifetimes. It
// will have a lifetime tied to the inference context. // will have a lifetime tied to the inference context.
let mut body: Body<'tcx> = input_body.clone(); let mut body: Body<'tcx> = input_body.clone();
let mut promoted: IndexVec<Promoted, Body<'tcx>> = input_promoted.clone(); // TODO(pfaria) this very likely won't work because
let promoted: IndexVec<Promoted, Body<'tcx>> = input_promoted.clone();
let mut promoted_cache: IndexVec<Promoted, BodyCache<&mut Body<'tcx>>> = promoted.iter_mut().map(|body| BodyCache::new(body)).collect();
let mut body_cache = BodyCache::new(&mut body);
let free_regions = 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 mut errors_buffer = Vec::new();
let (move_data, move_errors): (MoveData<'tcx>, Option<Vec<(Place<'tcx>, MoveError<'tcx>)>>) = let (move_data, move_errors): (MoveData<'tcx>, Option<Vec<(Place<'tcx>, MoveError<'tcx>)>>) =
match MoveData::gather_moves(body_cache, tcx) { match MoveData::gather_moves(&body_cache, tcx) {
Ok(move_data) => (move_data, None), Ok(move_data) => (move_data, None),
Err((move_data, move_errors)) => (move_data, Some(move_errors)), 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 dead_unwinds = BitSet::new_empty(body_cache.basic_blocks().len());
let mut flow_inits = FlowAtLocation::new(do_dataflow( let mut flow_inits = FlowAtLocation::new(do_dataflow(
tcx, tcx,
body_cache, &body_cache,
def_id, def_id,
&attributes, &attributes,
&dead_unwinds, &dead_unwinds,
MaybeInitializedPlaces::new(tcx, body_cache, &mdpe), MaybeInitializedPlaces::new(tcx, &body_cache, &mdpe),
|bd, i| DebugFormatted::new(&bd.move_data().move_paths[i]), |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 locals_are_invalidated_at_exit = tcx.hir().body_owner_kind(id).is_fn_or_closure();
let borrow_set = Rc::new(BorrowSet::build( 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. // If we are in non-lexical mode, compute the non-lexical lifetimes.
let (regioncx, polonius_output, opt_closure_req) = nll::compute_regions( let (regioncx, polonius_output, opt_closure_req) = nll::compute_regions(
infcx, infcx,
def_id, def_id,
free_regions, free_regions,
body_cache, &body_cache,
&promoted, &promoted,
&local_names, &local_names,
&upvars, &upvars,
@ -223,29 +226,29 @@ fn do_mir_borrowck<'a, 'tcx>(
let flow_borrows = FlowAtLocation::new(do_dataflow( let flow_borrows = FlowAtLocation::new(do_dataflow(
tcx, tcx,
body_cache, &body_cache,
def_id, def_id,
&attributes, &attributes,
&dead_unwinds, &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)), |rs, i| DebugFormatted::new(&rs.location(i)),
)); ));
let flow_uninits = FlowAtLocation::new(do_dataflow( let flow_uninits = FlowAtLocation::new(do_dataflow(
tcx, tcx,
body_cache, &body_cache,
def_id, def_id,
&attributes, &attributes,
&dead_unwinds, &dead_unwinds,
MaybeUninitializedPlaces::new(tcx, body_cache, &mdpe), MaybeUninitializedPlaces::new(tcx, &body_cache, &mdpe),
|bd, i| DebugFormatted::new(&bd.move_data().move_paths[i]), |bd, i| DebugFormatted::new(&bd.move_data().move_paths[i]),
)); ));
let flow_ever_inits = FlowAtLocation::new(do_dataflow( let flow_ever_inits = FlowAtLocation::new(do_dataflow(
tcx, tcx,
body_cache, &body_cache,
def_id, def_id,
&attributes, &attributes,
&dead_unwinds, &dead_unwinds,
EverInitializedPlaces::new(tcx, body_cache, &mdpe), EverInitializedPlaces::new(tcx, &body_cache, &mdpe),
|bd, i| DebugFormatted::new(&bd.move_data().inits[i]), |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); mbcx.report_conflicting_borrow(location, (&place, span), bk, &borrow);
let scope = mbcx.body.source_info(location).scope; 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, ClearCrossCrate::Set(data) => data.lint_root,
_ => id, _ => id,
}; };
@ -324,21 +327,21 @@ fn do_mir_borrowck<'a, 'tcx>(
// would have a chance of erroneously adding non-user-defined mutable vars // would have a chance of erroneously adding non-user-defined mutable vars
// to the set. // to the set.
let temporary_used_locals: FxHashSet<Local> = mbcx.used_mut.iter() let temporary_used_locals: FxHashSet<Local> = 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() .cloned()
.collect(); .collect();
// For the remaining unused locals that are marked as mutable, we avoid linting any that // 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 // were never initialized. These locals may have been removed as unreachable code; or will be
// linted as unused variables. // 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)) .filter(|local| !mbcx.used_mut.contains(local))
.collect(); .collect();
mbcx.gather_used_muts(temporary_used_locals, unused_mut_locals); mbcx.gather_used_muts(temporary_used_locals, unused_mut_locals);
debug!("mbcx.used_mut: {:?}", mbcx.used_mut); debug!("mbcx.used_mut: {:?}", mbcx.used_mut);
let 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)) { for local in mbcx.body_cache.mut_vars_and_args_iter().filter(|local| !used_mut.contains(local)) {
let local_decl = &mbcx.body.local_decls[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 { let lint_root = match &mbcx.body.source_scopes[local_decl.source_info.scope].local_data {
ClearCrossCrate::Set(data) => data.lint_root, ClearCrossCrate::Set(data) => data.lint_root,
_ => continue, _ => continue,
@ -399,7 +402,7 @@ fn do_mir_borrowck<'a, 'tcx>(
crate struct MirBorrowckCtxt<'cx, 'tcx> { crate struct MirBorrowckCtxt<'cx, 'tcx> {
crate infcx: &'cx InferCtxt<'cx, 'tcx>, crate infcx: &'cx InferCtxt<'cx, 'tcx>,
body_cache: BodyCache<&'cx Body<'tcx>>, body_cache: ReadOnlyBodyCache<'cx, 'tcx>,
mir_def_id: DefId, mir_def_id: DefId,
param_env: ty::ParamEnv<'tcx>, param_env: ty::ParamEnv<'tcx>,
move_data: &'cx MoveData<'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>; type FlowState = Flows<'cx, 'tcx>;
fn body(&self) -> &'cx Body<'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) { 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; let tcx = self.infcx.tcx;
// Compute the type with accurate region information. // 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. // Erase the regions.
let drop_place_ty = self.infcx.tcx.erase_regions(&drop_place_ty).ty; 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 mut error_reported = false;
let tcx = self.infcx.tcx; let tcx = self.infcx.tcx;
let body = self.body_cache; let body = self.body_cache.body();
let param_env = self.param_env; let param_env = self.param_env;
let location_table = self.location_table.start_index(location); let location_table = self.location_table.start_index(location);
let borrow_set = self.borrow_set.clone(); 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 // (e.g., `x = ...`) so long as it has never been initialized
// before (at this point in the flow). // before (at this point in the flow).
if let Some(local) = place_span.0.as_local() { 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 // check for reassignments to immutable local variables
self.check_if_reassignment_to_immutable_state( self.check_if_reassignment_to_immutable_state(
location, location,
@ -1303,7 +1306,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
match *operand { match *operand {
Operand::Move(ref place) | Operand::Copy(ref place) => { Operand::Move(ref place) | Operand::Copy(ref place) => {
match place.as_local() { 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() { if self.body.local_decls[local].ty.is_mutable_ptr() {
// The variable will be marked as mutable by the borrow. // The variable will be marked as mutable by the borrow.
return; return;
@ -1335,7 +1338,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
_ => bug!("temporary initialized in arguments"), _ => 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]; let stmt = &bbd.statements[loc.statement_index];
debug!("temporary assigned in: stmt={:?}", stmt); debug!("temporary assigned in: stmt={:?}", stmt);
@ -1454,7 +1457,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
if places_conflict::borrow_conflicts_with_place( if places_conflict::borrow_conflicts_with_place(
self.infcx.tcx, self.infcx.tcx,
self.param_env, self.param_env,
self.body, &self.body_cache,
place, place,
borrow.kind, borrow.kind,
root_place, 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) { if let Some(init_index) = self.is_local_ever_initialized(local, flow_state) {
// And, if so, report an error. // And, if so, report an error.
let init = &self.move_data.inits[init_index]; 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( self.report_illegal_reassignment(
location, place_span, span, place_span.0 location, place_span, span, place_span.0
); );
@ -1745,7 +1748,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
// assigning to `P.f` requires `P` itself // assigning to `P.f` requires `P` itself
// be already initialized // be already initialized
let tcx = self.infcx.tcx; 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 { match base_ty.kind {
ty::Adt(def, _) if def.has_dtor(tcx) => { ty::Adt(def, _) if def.has_dtor(tcx) => {
self.check_if_path_or_subpath_is_moved( 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. // of the union - we should error in that case.
let tcx = this.infcx.tcx; let tcx = this.infcx.tcx;
if let ty::Adt(def, _) = 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 def.is_union() {
if this.move_data.path_map[mpi].iter().any(|moi| { if this.move_data.path_map[mpi].iter().any(|moi| {
this.move_data.moves[*moi].source.is_predecessor_of( this.move_data.moves[*moi].source.is_predecessor_of(
location, this.body, location, &this.body_cache,
) )
}) { }) {
return; return;
@ -2061,7 +2064,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
base: PlaceBase::Local(local), base: PlaceBase::Local(local),
projection: [], projection: [],
} => { } => {
let local = &self.body.local_decls[*local]; let local = &self.body_cache.local_decls[*local];
match local.mutability { match local.mutability {
Mutability::Not => match is_local_mutation_allowed { Mutability::Not => match is_local_mutation_allowed {
LocalMutationIsAllowed::Yes => Ok(RootPlace { LocalMutationIsAllowed::Yes => Ok(RootPlace {
@ -2122,7 +2125,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
match elem { match elem {
ProjectionElem::Deref => { ProjectionElem::Deref => {
let base_ty = 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 // Check the kind of deref to decide
match base_ty.kind { match base_ty.kind {
@ -2262,7 +2265,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
match place_projection { match place_projection {
[base @ .., ProjectionElem::Field(field, _ty)] => { [base @ .., ProjectionElem::Field(field, _ty)] => {
let tcx = self.infcx.tcx; 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()) && if (base_ty.is_closure() || base_ty.is_generator()) &&
(!by_ref || self.upvars[field.index()].by_ref) { (!by_ref || self.upvars[field.index()].by_ref) {

View file

@ -90,13 +90,13 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
// flow could be used. // flow could be used.
if let Some(StatementKind::Assign( if let Some(StatementKind::Assign(
box(place, Rvalue::Use(Operand::Move(move_from))) box(place, Rvalue::Use(Operand::Move(move_from)))
)) = self.body.basic_blocks()[location.block] )) = self.body_cache.basic_blocks()[location.block]
.statements .statements
.get(location.statement_index) .get(location.statement_index)
.map(|stmt| &stmt.kind) .map(|stmt| &stmt.kind)
{ {
if let Some(local) = place.as_local() { 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 // opt_match_place is the
// match_span is the span of the expression being matched on // match_span is the span of the expression being matched on
// match *x.y { ... } match_place is Some(*x.y) // match *x.y { ... } match_place is Some(*x.y)
@ -112,7 +112,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
pat_span: _, pat_span: _,
}, },
))) = local_decl.local_info { ))) = 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( self.append_binding_error(
grouped_errors, grouped_errors,
kind, kind,
@ -300,7 +300,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
// Inspect the type of the content behind the // Inspect the type of the content behind the
// borrow to provide feedback about why this // borrow to provide feedback about why this
// was a move rather than a copy. // 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) let upvar_field = self.prefixes(move_place.as_ref(), PrefixSet::All)
.find_map(|p| self.is_upvar_field_projection(p)); .find_map(|p| self.is_upvar_field_projection(p));
@ -318,7 +318,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
base: PlaceBase::Local(local), base: PlaceBase::Local(local),
projection: [], projection: [],
} = deref_base { } = deref_base {
let decl = &self.body.local_decls[*local]; let decl = &self.body_cache.local_decls[*local];
if decl.is_ref_for_guard() { if decl.is_ref_for_guard() {
let mut err = self.cannot_move_out_of( let mut err = self.cannot_move_out_of(
span, span,
@ -411,7 +411,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
}; };
let move_ty = format!( 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) { if let Ok(snippet) = self.infcx.tcx.sess.source_map().span_to_snippet(span) {
let is_option = move_ty.starts_with("std::option::Option"); 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() { 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()) { let place_desc = match self.describe_place(move_from.as_ref()) {
Some(desc) => format!("`{}`", desc), Some(desc) => format!("`{}`", desc),
None => format!("value"), None => format!("value"),
@ -482,7 +482,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
// No binding. Nothing to suggest. // No binding. Nothing to suggest.
GroupedMoveError::OtherIllegalMove { ref original_path, use_spans, .. } => { GroupedMoveError::OtherIllegalMove { ref original_path, use_spans, .. } => {
let span = use_spans.var_or_use(); 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()) { let place_desc = match self.describe_place(original_path.as_ref()) {
Some(desc) => format!("`{}`", desc), Some(desc) => format!("`{}`", desc),
None => format!("value"), None => format!("value"),
@ -510,7 +510,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
) { ) {
let mut suggestions: Vec<(Span, &str, String)> = Vec::new(); let mut suggestions: Vec<(Span, &str, String)> = Vec::new();
for local in binds_to { 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( if let LocalInfo::User(
ClearCrossCrate::Set(BindingForm::Var(VarBindingForm { ClearCrossCrate::Set(BindingForm::Var(VarBindingForm {
pat_span, pat_span,
@ -559,7 +559,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
binds_to: &[Local], binds_to: &[Local],
) { ) {
for (j, local) in binds_to.into_iter().enumerate() { 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; let binding_span = bind_to.source_info.span;
if j == 0 { if j == 0 {

View file

@ -61,7 +61,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
projection: [proj_base @ .., ProjectionElem::Field(upvar_index, _)], projection: [proj_base @ .., ProjectionElem::Field(upvar_index, _)],
} => { } => {
debug_assert!(is_closure_or_generator( 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()); item_msg = format!("`{}`", access_place_desc.unwrap());
@ -106,12 +106,12 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
proj_base.is_empty() && proj_base.is_empty() &&
!self.upvars.is_empty() { !self.upvars.is_empty() {
item_msg = format!("`{}`", access_place_desc.unwrap()); 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( debug_assert!(is_closure_or_generator(
Place::ty_from( Place::ty_from(
the_place_err.base, the_place_err.base,
the_place_err.projection, the_place_err.projection,
self.body, self.body_cache.body(),
self.infcx.tcx self.infcx.tcx
) )
.ty .ty
@ -225,7 +225,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
if let Some((span, message)) = annotate_struct_field( if let Some((span, message)) = annotate_struct_field(
self.infcx.tcx, 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, field,
) { ) {
err.span_suggestion( err.span_suggestion(
@ -242,7 +242,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
base: PlaceBase::Local(local), base: PlaceBase::Local(local),
projection: [], projection: [],
} if { } 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( if let LocalInfo::User(ClearCrossCrate::Set(
mir::BindingForm::ImplicitSelf(kind) mir::BindingForm::ImplicitSelf(kind)
)) = local_decl.local_info { )) = local_decl.local_info {
@ -277,12 +277,12 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
PlaceRef { PlaceRef {
base: PlaceBase::Local(local), base: PlaceBase::Local(local),
projection: [], 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 // ... but it doesn't make sense to suggest it on
// variables that are `ref x`, `ref mut x`, `&self`, // variables that are `ref x`, `ref mut x`, `&self`,
// or `&mut self` (such variables are simply not // or `&mut self` (such variables are simply not
// mutable). // 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); assert_eq!(local_decl.mutability, Mutability::Not);
err.span_label(span, format!("cannot {ACT}", ACT = act)); 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, _)], projection: [proj_base @ .., ProjectionElem::Field(upvar_index, _)],
} => { } => {
debug_assert!(is_closure_or_generator( 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)); err.span_label(span, format!("cannot {ACT}", ACT = act));
@ -346,7 +346,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
PlaceRef { PlaceRef {
base: PlaceBase::Local(local), base: PlaceBase::Local(local),
projection: [ProjectionElem::Deref], 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.span_label(span, format!("cannot {ACT}", ACT = act));
err.note( err.note(
"variables bound in patterns are immutable until the end of the pattern guard", "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], projection: [ProjectionElem::Deref],
} if self.body.local_decls[*local].is_user_variable() => } 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 { let suggestion = match local_decl.local_info {
LocalInfo::User(ClearCrossCrate::Set(mir::BindingForm::ImplicitSelf(_))) => { LocalInfo::User(ClearCrossCrate::Set(mir::BindingForm::ImplicitSelf(_))) => {
Some(suggest_ampmut_self(self.infcx.tcx, local_decl)) Some(suggest_ampmut_self(self.infcx.tcx, local_decl))
@ -377,7 +377,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
}, },
))) => Some(suggest_ampmut( ))) => Some(suggest_ampmut(
self.infcx.tcx, self.infcx.tcx,
self.body, &self.body_cache,
*local, *local,
local_decl, local_decl,
opt_ty_info, opt_ty_info,
@ -451,7 +451,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
{ {
err.span_label(span, format!("cannot {ACT}", ACT = act)); err.span_label(span, format!("cannot {ACT}", ACT = act));
err.span_help( err.span_help(
self.body.span, self.body_cache.span,
"consider changing this to accept closures that implement `FnMut`" "consider changing this to accept closures that implement `FnMut`"
); );
} }

View file

@ -237,7 +237,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
); );
let regioncx = &self.nonlexical_regioncx; let regioncx = &self.nonlexical_regioncx;
let body = self.body; let body = self.body_cache.body();
let tcx = self.infcx.tcx; let tcx = self.infcx.tcx;
let borrow_region_vid = borrow.region; let borrow_region_vid = borrow.region;
@ -297,7 +297,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
if let Some(region) = regioncx.to_error_region_vid(borrow_region_vid) { if let Some(region) = regioncx.to_error_region_vid(borrow_region_vid) {
let (category, from_closure, span, region_name) = let (category, from_closure, span, region_name) =
self.nonlexical_regioncx.free_region_constraint_info( self.nonlexical_regioncx.free_region_constraint_info(
self.body, &self.body_cache,
&self.local_names, &self.local_names,
&self.upvars, &self.upvars,
self.mir_def_id, self.mir_def_id,
@ -365,7 +365,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
return outmost_back_edge; 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() { if location.statement_index < block.statements.len() {
let successor = location.successor_within_block(); let successor = location.successor_within_block();
@ -427,7 +427,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
} }
if loop_head.dominates(from, &self.dominators) { 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() { if from.statement_index < block.statements.len() {
let successor = from.successor_within_block(); let successor = from.successor_within_block();
@ -475,7 +475,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
(LaterUseKind::ClosureCapture, var_span) (LaterUseKind::ClosureCapture, var_span)
} }
UseSpans::OtherUse(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 { let kind = if let Some(&Statement {
kind: StatementKind::FakeRead(FakeReadCause::ForLet, _), kind: StatementKind::FakeRead(FakeReadCause::ForLet, _),
@ -498,7 +498,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
Operand::Copy(place) | Operand::Copy(place) |
Operand::Move(place) => { Operand::Move(place) => {
if let Some(l) = place.as_local() { 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() { if self.local_names[l].is_none() {
local_decl.source_info.span local_decl.source_info.span
} else { } else {
@ -528,7 +528,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
fn was_captured_by_trait_object(&self, borrow: &BorrowData<'tcx>) -> bool { 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. // Start at the reserve location, find the place that we want to see cast to a trait object.
let location = borrow.reserve_location; 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); let stmt = block.statements.get(location.statement_index);
debug!( debug!(
"was_captured_by_trait_object: location={:?} stmt={:?}", "was_captured_by_trait_object: location={:?} stmt={:?}",
@ -558,7 +558,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
); );
while let Some(current_location) = queue.pop() { while let Some(current_location) = queue.pop() {
debug!("was_captured_by_trait: target={:?}", target); 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. // 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(); let is_terminator = current_location.statement_index == block.statements.len();
if !is_terminator { if !is_terminator {

View file

@ -11,7 +11,7 @@ use crate::borrow_check::path_utils::*;
use crate::dataflow::indexes::BorrowIndex; use crate::dataflow::indexes::BorrowIndex;
use rustc::ty::{self, TyCtxt}; use rustc::ty::{self, TyCtxt};
use rustc::mir::visit::Visitor; 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::{Statement, StatementKind};
use rustc::mir::TerminatorKind; use rustc::mir::TerminatorKind;
use rustc::mir::{Operand, BorrowKind}; use rustc::mir::{Operand, BorrowKind};
@ -22,7 +22,7 @@ pub(super) fn generate_invalidates<'tcx>(
param_env: ty::ParamEnv<'tcx>, param_env: ty::ParamEnv<'tcx>,
all_facts: &mut Option<AllFacts>, all_facts: &mut Option<AllFacts>,
location_table: &LocationTable, location_table: &LocationTable,
body: &Body<'tcx>, body_cache: &ReadOnlyBodyCache<'_, 'tcx>,
borrow_set: &BorrowSet<'tcx>, borrow_set: &BorrowSet<'tcx>,
) { ) {
if all_facts.is_none() { if all_facts.is_none() {
@ -31,17 +31,17 @@ pub(super) fn generate_invalidates<'tcx>(
} }
if let Some(all_facts) = all_facts { if let Some(all_facts) = all_facts {
let dominators = body.dominators(); let dominators = body_cache.dominators();
let mut ig = InvalidationGenerator { let mut ig = InvalidationGenerator {
all_facts, all_facts,
borrow_set, borrow_set,
param_env, param_env,
tcx, tcx,
location_table, location_table,
body, body: body_cache.body(),
dominators, dominators,
}; };
ig.visit_body(body); ig.visit_body(&body_cache);
} }
} }

View file

@ -12,7 +12,8 @@ use crate::borrow_check::Upvar;
use rustc::hir::def_id::DefId; use rustc::hir::def_id::DefId;
use rustc::infer::InferCtxt; use rustc::infer::InferCtxt;
use rustc::mir::{ClosureOutlivesSubject, ClosureRegionRequirements, 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::ty::{self, RegionKind, RegionVid};
use rustc_index::vec::IndexVec; use rustc_index::vec::IndexVec;
use rustc_errors::Diagnostic; use rustc_errors::Diagnostic;
@ -54,8 +55,8 @@ pub(in crate::borrow_check) fn replace_regions_in_mir<'cx, 'tcx>(
infcx: &InferCtxt<'cx, 'tcx>, infcx: &InferCtxt<'cx, 'tcx>,
def_id: DefId, def_id: DefId,
param_env: ty::ParamEnv<'tcx>, param_env: ty::ParamEnv<'tcx>,
body: &mut Body<'tcx>, body_cache: &mut BodyCache<&mut Body<'tcx>>,
promoted: &mut IndexVec<Promoted, Body<'tcx>>, promoted: &mut IndexVec<Promoted, BodyCache<&mut Body<'tcx>>>,
) -> UniversalRegions<'tcx> { ) -> UniversalRegions<'tcx> {
debug!("replace_regions_in_mir(def_id={:?})", def_id); 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); let universal_regions = UniversalRegions::new(infcx, def_id, param_env);
// Replace all remaining regions with fresh inference variables. // 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); 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 universal_regions
} }
@ -157,7 +158,7 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>(
infcx: &InferCtxt<'cx, 'tcx>, infcx: &InferCtxt<'cx, 'tcx>,
def_id: DefId, def_id: DefId,
universal_regions: UniversalRegions<'tcx>, universal_regions: UniversalRegions<'tcx>,
body: &Body<'tcx>, body_cache: &ReadOnlyBodyCache<'_, 'tcx>,
promoted: &IndexVec<Promoted, Body<'tcx>>, promoted: &IndexVec<Promoted, Body<'tcx>>,
local_names: &IndexVec<Local, Option<Symbol>>, local_names: &IndexVec<Local, Option<Symbol>>,
upvars: &[Upvar], upvars: &[Upvar],
@ -180,7 +181,7 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>(
let universal_regions = Rc::new(universal_regions); 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. // Run the MIR type-checker.
let MirTypeckResults { let MirTypeckResults {
@ -189,7 +190,7 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>(
} = type_check::type_check( } = type_check::type_check(
infcx, infcx,
param_env, param_env,
body, body_cache,
promoted, promoted,
def_id, def_id,
&universal_regions, &universal_regions,
@ -205,7 +206,7 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>(
all_facts all_facts
.universal_region .universal_region
.extend(universal_regions.universal_regions()); .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 // 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 liveness_constraints,
&mut all_facts, &mut all_facts,
location_table, location_table,
&body, body_cache,
borrow_set, borrow_set,
); );
@ -238,7 +239,7 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>(
universal_regions, universal_regions,
placeholder_indices, placeholder_indices,
universal_region_relations, universal_region_relations,
body, body_cache,
outlives_constraints, outlives_constraints,
member_constraints, member_constraints,
closure_bounds_mapping, closure_bounds_mapping,
@ -253,7 +254,7 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>(
param_env, param_env,
&mut all_facts, &mut all_facts,
location_table, location_table,
&body, body_cache,
borrow_set, borrow_set,
); );
@ -283,21 +284,21 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>(
// Solve the region constraints. // Solve the region constraints.
let closure_region_requirements = 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 // Dump MIR results into a file, if that is enabled. This let us
// write unit-tests, as well as helping with debugging. // write unit-tests, as well as helping with debugging.
dump_mir_results( dump_mir_results(
infcx, infcx,
MirSource::item(def_id), MirSource::item(def_id),
&body, body_cache,
&regioncx, &regioncx,
&closure_region_requirements, &closure_region_requirements,
); );
// We also have a `#[rustc_nll]` annotation that causes us to dump // We also have a `#[rustc_nll]` annotation that causes us to dump
// information // information
dump_annotation(infcx, &body, def_id, &regioncx, &closure_region_requirements, errors_buffer); dump_annotation(infcx, body_cache, def_id, &regioncx, &closure_region_requirements, errors_buffer);
(regioncx, polonius_output, closure_region_requirements) (regioncx, polonius_output, closure_region_requirements)
} }

View file

@ -1,4 +1,4 @@
use rustc::mir::{BasicBlock, Location, Body}; use rustc::mir::{BasicBlock, Location, Body, ReadOnlyBodyCache};
use rustc::ty::{self, RegionVid}; use rustc::ty::{self, RegionVid};
use rustc_index::bit_set::{HybridBitSet, SparseBitMatrix}; use rustc_index::bit_set::{HybridBitSet, SparseBitMatrix};
use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::fx::FxHashMap;
@ -92,7 +92,7 @@ impl RegionValueElements {
/// Pushes all predecessors of `index` onto `stack`. /// Pushes all predecessors of `index` onto `stack`.
crate fn push_predecessors( crate fn push_predecessors(
&self, &self,
body: &Body<'_>, body_cache: &ReadOnlyBodyCache<'_, '_>,
index: PointIndex, index: PointIndex,
stack: &mut Vec<PointIndex>, stack: &mut Vec<PointIndex>,
) { ) {
@ -104,9 +104,9 @@ impl RegionValueElements {
// If this is a basic block head, then the predecessors are // If this is a basic block head, then the predecessors are
// the terminators of other basic blocks // the terminators of other basic blocks
stack.extend( stack.extend(
body.predecessors_for(block) body_cache.predecessors_for(block)
.iter() .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)), .map(|pred_loc| self.point_from_location(pred_loc)),
); );
} else { } else {

View file

@ -1,6 +1,6 @@
use rustc::ty::subst::SubstsRef; use rustc::ty::subst::SubstsRef;
use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; 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::mir::visit::{MutVisitor, TyContext};
use rustc::infer::{InferCtxt, NLLRegionVariableOrigin}; use rustc::infer::{InferCtxt, NLLRegionVariableOrigin};
use rustc_index::vec::IndexVec; use rustc_index::vec::IndexVec;
@ -9,11 +9,11 @@ use rustc_index::vec::IndexVec;
/// inference variables, returning the number of variables created. /// inference variables, returning the number of variables created.
pub fn renumber_mir<'tcx>( pub fn renumber_mir<'tcx>(
infcx: &InferCtxt<'_, 'tcx>, infcx: &InferCtxt<'_, 'tcx>,
body: &mut Body<'tcx>, body_cache: &mut BodyCache<&mut Body<'tcx>>,
promoted: &mut IndexVec<Promoted, Body<'tcx>>, promoted: &mut IndexVec<Promoted, BodyCache<&mut Body<'tcx>>>,
) { ) {
debug!("renumber_mir()"); 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 }; 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); visitor.visit_body(body_cache);
} }
/// Replaces all regions appearing in `value` with fresh inference /// Replaces all regions appearing in `value` with fresh inference

View file

@ -115,7 +115,7 @@ mod relate_tys;
pub(crate) fn type_check<'tcx>( pub(crate) fn type_check<'tcx>(
infcx: &InferCtxt<'_, 'tcx>, infcx: &InferCtxt<'_, 'tcx>,
param_env: ty::ParamEnv<'tcx>, param_env: ty::ParamEnv<'tcx>,
body: &Body<'tcx>, body_cache: &ReadOnlyBodyCache<'_, 'tcx>,
promoted: &IndexVec<Promoted, Body<'tcx>>, promoted: &IndexVec<Promoted, Body<'tcx>>,
mir_def_id: DefId, mir_def_id: DefId,
universal_regions: &Rc<UniversalRegions<'tcx>>, universal_regions: &Rc<UniversalRegions<'tcx>>,
@ -161,15 +161,15 @@ pub(crate) fn type_check<'tcx>(
infcx, infcx,
mir_def_id, mir_def_id,
param_env, param_env,
body, body_cache,
promoted, promoted,
&region_bound_pairs, &region_bound_pairs,
implicit_region_bound, implicit_region_bound,
&mut borrowck_context, &mut borrowck_context,
&universal_region_relations, &universal_region_relations,
|mut cx| { |mut cx| {
cx.equate_inputs_and_outputs(body, universal_regions, &normalized_inputs_and_output); cx.equate_inputs_and_outputs(body_cache, universal_regions, &normalized_inputs_and_output);
liveness::generate(&mut cx, body, elements, flow_inits, move_data, location_table); liveness::generate(&mut cx, body_cache, elements, flow_inits, move_data, location_table);
translate_outlives_facts(cx.borrowck_context); translate_outlives_facts(cx.borrowck_context);
}, },
@ -185,7 +185,7 @@ fn type_check_internal<'a, 'tcx, R>(
infcx: &'a InferCtxt<'a, 'tcx>, infcx: &'a InferCtxt<'a, 'tcx>,
mir_def_id: DefId, mir_def_id: DefId,
param_env: ty::ParamEnv<'tcx>, param_env: ty::ParamEnv<'tcx>,
body: &'a Body<'tcx>, body_cache: &ReadOnlyBodyCache<'a, 'tcx>,
promoted: &'a IndexVec<Promoted, Body<'tcx>>, promoted: &'a IndexVec<Promoted, Body<'tcx>>,
region_bound_pairs: &'a RegionBoundPairs<'tcx>, region_bound_pairs: &'a RegionBoundPairs<'tcx>,
implicit_region_bound: ty::Region<'tcx>, implicit_region_bound: ty::Region<'tcx>,
@ -195,7 +195,7 @@ fn type_check_internal<'a, 'tcx, R>(
) -> R where { ) -> R where {
let mut checker = TypeChecker::new( let mut checker = TypeChecker::new(
infcx, infcx,
body, body_cache,
mir_def_id, mir_def_id,
param_env, param_env,
region_bound_pairs, region_bound_pairs,
@ -204,14 +204,14 @@ fn type_check_internal<'a, 'tcx, R>(
universal_region_relations, universal_region_relations,
); );
let errors_reported = { let errors_reported = {
let mut verifier = TypeVerifier::new(&mut checker, body, promoted); let mut verifier = TypeVerifier::new(&mut checker, body_cache, promoted);
verifier.visit_body(body); verifier.visit_body(body_cache);
verifier.errors_reported verifier.errors_reported
}; };
if !errors_reported { if !errors_reported {
// if verifier failed, don't do further checks to avoid ICEs // if verifier failed, don't do further checks to avoid ICEs
checker.typeck_mir(body); checker.typeck_mir(body_cache);
} }
extra(&mut checker) 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()); self.sanitize_type(&"return type", body_cache.return_ty());
for local_decl in &body_cache.local_decls { for local_decl in &body_cache.local_decls {
self.sanitize_type(local_decl, local_decl.ty); self.sanitize_type(local_decl, local_decl.ty);

View file

@ -56,7 +56,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
Prefixes { Prefixes {
next: Some(place_ref), next: Some(place_ref),
kind, kind,
body: self.body, body: &self.body_cache,
tcx: self.infcx.tcx, tcx: self.infcx.tcx,
} }
} }

View file

@ -32,7 +32,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
never_initialized_mut_locals: &mut never_initialized_mut_locals, never_initialized_mut_locals: &mut never_initialized_mut_locals,
mbcx: self, 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 // Take the union of the existed `used_mut` set with those variables we've found were