Avoid cloning Place in report_use_of_moved_or_uninitialized and friends

This commit is contained in:
Santiago Pastorino 2019-07-11 19:25:37 +02:00
parent ec65db07ef
commit 46f81fc53d
17 changed files with 252 additions and 230 deletions

View file

@ -1826,7 +1826,7 @@ newtype_index! {
}
}
#[derive(Debug)]
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
pub struct PlaceRef<'a, 'tcx> {
pub base: &'a PlaceBase<'tcx>,
pub projection: &'a Option<Box<Projection<'tcx>>>,
@ -1961,6 +1961,27 @@ impl<'a, 'tcx> PlaceRef<'a, 'tcx> {
) -> R {
Place::iterate_over(self.base, self.projection, op)
}
/// Finds the innermost `Local` from this `Place`, *if* it is either a local itself or
/// a single deref of a local.
//
// FIXME: can we safely swap the semantics of `fn base_local` below in here instead?
pub fn local_or_deref_local(&self) -> Option<Local> {
match self {
PlaceRef {
base: PlaceBase::Local(local),
projection: None,
} |
PlaceRef {
base: PlaceBase::Local(local),
projection: Some(box Projection {
base: None,
elem: ProjectionElem::Deref,
}),
} => Some(*local),
_ => None,
}
}
}
/// A linked list of projections running up the stack; begins with the

View file

@ -2,7 +2,7 @@ use rustc::hir;
use rustc::hir::def_id::DefId;
use rustc::mir::{
self, AggregateKind, BindingForm, BorrowKind, ClearCrossCrate, ConstraintCategory, Local,
LocalDecl, LocalKind, Location, Operand, Place, PlaceBase, Projection,
LocalDecl, LocalKind, Location, Operand, Place, PlaceBase, Projection, PlaceRef,
ProjectionElem, Rvalue, Statement, StatementKind, TerminatorKind, VarBindingForm,
};
use rustc::ty::{self, Ty};
@ -48,7 +48,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
&mut self,
location: Location,
desired_action: InitializationRequiringAction,
(moved_place, used_place, span): (&Place<'tcx>, &Place<'tcx>, Span),
(moved_place, used_place, span): (PlaceRef<'cx, 'tcx>, PlaceRef<'cx, 'tcx>, Span),
mpi: MovePathIndex,
) {
debug!(
@ -73,14 +73,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
if move_out_indices.is_empty() {
let root_place = self
.prefixes(&used_place.base, &used_place.projection, PrefixSet::All)
.prefixes(used_place, PrefixSet::All)
.last()
.unwrap();
if self.uninitialized_error_reported.contains(&Place {
base: root_place.0.clone(),
projection: root_place.1.clone(),
}) {
if self.uninitialized_error_reported.contains(&root_place) {
debug!(
"report_use_of_moved_or_uninitialized place: error about {:?} suppressed",
root_place
@ -88,10 +85,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
return;
}
self.uninitialized_error_reported.insert(Place {
base: root_place.0.clone(),
projection: root_place.1.clone(),
});
self.uninitialized_error_reported.insert(root_place);
let item_msg = match self.describe_place_with_options(used_place,
IncludingDowncast(true)) {
@ -114,8 +108,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
err.buffer(&mut self.errors_buffer);
} else {
if let Some((reported_place, _)) = self.move_error_reported.get(&move_out_indices) {
if self.prefixes(&reported_place.base, &reported_place.projection, PrefixSet::All)
.any(|p| *p.0 == used_place.base && *p.1 == used_place.projection)
if self.prefixes(*reported_place, PrefixSet::All)
.any(|p| p == used_place)
{
debug!(
"report_use_of_moved_or_uninitialized place: error suppressed \
@ -132,7 +126,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
span,
desired_action.as_noun(),
msg,
self.describe_place_with_options(&moved_place, IncludingDowncast(true)),
self.describe_place_with_options(moved_place, IncludingDowncast(true)),
);
self.add_moved_or_invoked_closure_note(
@ -145,13 +139,14 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
let is_partial_move = move_site_vec.iter().any(|move_site| {
let move_out = self.move_data.moves[(*move_site).moi];
let moved_place = &self.move_data.move_paths[move_out.path].place;
used_place != moved_place && used_place.is_prefix_of(moved_place)
used_place != moved_place.as_place_ref()
&& used_place.is_prefix_of(moved_place.as_place_ref())
});
for move_site in &move_site_vec {
let move_out = self.move_data.moves[(*move_site).moi];
let moved_place = &self.move_data.move_paths[move_out.path].place;
let move_spans = self.move_spans(moved_place, move_out.source);
let move_spans = self.move_spans(moved_place.as_place_ref(), move_out.source);
let move_span = move_spans.args_or_use();
let move_msg = if move_spans.for_closure() {
@ -209,7 +204,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
);
}
let ty = used_place.ty(self.body, self.infcx.tcx).ty;
let ty =
Place::ty_from(used_place.base, used_place.projection, self.body, self.infcx.tcx)
.ty;
let needs_note = match ty.sty {
ty::Closure(id, _) => {
let tables = self.infcx.tcx.typeck_tables_of(id);
@ -225,7 +222,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
let place = &self.move_data.move_paths[mpi].place;
let ty = place.ty(self.body, self.infcx.tcx).ty;
let opt_name = self.describe_place_with_options(place, IncludingDowncast(true));
let opt_name =
self.describe_place_with_options(place.as_place_ref(), IncludingDowncast(true));
let note_msg = match opt_name {
Some(ref name) => format!("`{}`", name),
None => "value".to_owned(),
@ -259,7 +257,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
}
if let Some((_, mut old_err)) = self.move_error_reported
.insert(move_out_indices, (used_place.clone(), err))
.insert(move_out_indices, (used_place, err))
{
// Cancel the old error so it doesn't ICE.
old_err.cancel();
@ -289,7 +287,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
let borrow_spans = self.retrieve_borrow_spans(borrow);
let borrow_span = borrow_spans.args_or_use();
let move_spans = self.move_spans(place, location);
let move_spans = self.move_spans(place.as_place_ref(), location);
let span = move_spans.args_or_use();
let mut err = self.cannot_move_when_borrowed(
@ -328,7 +326,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
// Conflicting borrows are reported separately, so only check for move
// captures.
let use_spans = self.move_spans(place, location);
let use_spans = self.move_spans(place.as_place_ref(), location);
let span = use_spans.var_or_use();
let mut err = self.cannot_use_when_mutably_borrowed(
@ -698,25 +696,23 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
);
let drop_span = place_span.1;
let root_place = self.prefixes(&borrow.borrowed_place.base,
&borrow.borrowed_place.projection,
PrefixSet::All)
let root_place = self.prefixes(borrow.borrowed_place.as_place_ref(), PrefixSet::All)
.last()
.unwrap();
let borrow_spans = self.retrieve_borrow_spans(borrow);
let borrow_span = borrow_spans.var_or_use();
assert!(root_place.1.is_none());
let proper_span = match root_place.0 {
assert!(root_place.projection.is_none());
let proper_span = match root_place.base {
PlaceBase::Local(local) => self.body.local_decls[*local].source_info.span,
_ => drop_span,
};
if self.access_place_error_reported
.contains(&(Place {
base: root_place.0.clone(),
projection: root_place.1.clone(),
base: root_place.base.clone(),
projection: root_place.projection.clone(),
}, borrow_span))
{
debug!(
@ -728,8 +724,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
self.access_place_error_reported
.insert((Place {
base: root_place.0.clone(),
projection: root_place.1.clone(),
base: root_place.base.clone(),
projection: root_place.projection.clone(),
}, borrow_span));
if let StorageDeadOrDrop::Destructor(dropped_ty) =
@ -739,7 +735,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
// we're not in the uninteresting case where `B` is a
// prefix of `D`), then report this as a more interesting
// destructor conflict.
if !borrow.borrowed_place.is_prefix_of(place_span.0) {
if !borrow.borrowed_place.as_place_ref().is_prefix_of(place_span.0.as_place_ref()) {
self.report_borrow_conflicts_with_destructor(
location, borrow, place_span, kind, dropped_ty,
);
@ -753,10 +749,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
let explanation = self.explain_why_borrow_contains_point(location, &borrow, kind_place);
let err = match (place_desc, explanation) {
(Some(_), _) if self.is_place_thread_local(&Place {
base: root_place.0.clone(),
projection: root_place.1.clone(),
}) => {
(Some(_), _) if self.is_place_thread_local(root_place) => {
self.report_thread_local_value_does_not_live_long_enough(drop_span, borrow_span)
}
// If the outlives constraint comes from inside the closure,
@ -1133,12 +1126,14 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
format!("`{}` is borrowed here", place_desc),
)
} else {
let root_place = self.prefixes(&borrow.borrowed_place.base,
&borrow.borrowed_place.projection,
let root_place = self.prefixes(borrow.borrowed_place.as_place_ref(),
PrefixSet::All)
.last()
.unwrap();
let local = if let (PlaceBase::Local(local), None) = root_place {
let local = if let PlaceRef {
base: PlaceBase::Local(local),
projection: None,
} = root_place {
local
} else {
bug!("try_report_cannot_return_reference_to_local: not a local")

View file

@ -3,8 +3,8 @@ use rustc::hir::def::Namespace;
use rustc::hir::def_id::DefId;
use rustc::mir::{
AggregateKind, Constant, Field, Local, LocalKind, Location, Operand,
Place, PlaceBase, ProjectionElem, Rvalue, Statement, StatementKind, Static,
StaticKind, Terminator, TerminatorKind,
Place, PlaceBase, PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind,
Static, StaticKind, Terminator, TerminatorKind,
};
use rustc::ty::{self, DefIdTree, Ty, TyCtxt};
use rustc::ty::layout::VariantIdx;
@ -34,7 +34,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
pub(super) fn add_moved_or_invoked_closure_note(
&self,
location: Location,
place: &Place<'tcx>,
place: PlaceRef<'cx, 'tcx>,
diag: &mut DiagnosticBuilder<'_>,
) {
debug!("add_moved_or_invoked_closure_note: location={:?} place={:?}", location, place);
@ -122,7 +122,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
/// End-user visible description of `place` if one can be found. If the
/// place is a temporary for instance, None will be returned.
pub(super) fn describe_place(&self, place: &Place<'tcx>) -> Option<String> {
self.describe_place_with_options(place, IncludingDowncast(false))
self.describe_place_with_options(place.as_place_ref(), IncludingDowncast(false))
}
/// End-user visible description of `place` if one can be found. If the
@ -131,7 +131,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
/// `Downcast` and `IncludingDowncast` is true
pub(super) fn describe_place_with_options(
&self,
place: &Place<'tcx>,
place: PlaceRef<'cx, 'tcx>,
including_downcast: IncludingDowncast,
) -> Option<String> {
let mut buf = String::new();
@ -144,19 +144,19 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
/// Appends end-user visible description of `place` to `buf`.
fn append_place_to_string(
&self,
place: &Place<'tcx>,
place: PlaceRef<'cx, 'tcx>,
buf: &mut String,
mut autoderef: bool,
including_downcast: &IncludingDowncast,
) -> Result<(), ()> {
match *place {
Place {
match place {
PlaceRef {
base: PlaceBase::Local(local),
projection: None,
} => {
self.append_local_to_string(local, buf)?;
self.append_local_to_string(*local, buf)?;
}
Place {
PlaceRef {
base:
PlaceBase::Static(box Static {
kind: StaticKind::Promoted(_),
@ -166,7 +166,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
} => {
buf.push_str("promoted");
}
Place {
PlaceRef {
base:
PlaceBase::Static(box Static {
kind: StaticKind::Static(def_id),
@ -174,9 +174,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
}),
projection: None,
} => {
buf.push_str(&self.infcx.tcx.item_name(def_id).to_string());
buf.push_str(&self.infcx.tcx.item_name(*def_id).to_string());
}
Place {
PlaceRef {
ref base,
projection: Some(ref proj),
} => {
@ -196,9 +196,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
if autoderef {
// FIXME turn this recursion into iteration
self.append_place_to_string(
&Place {
base: base.clone(),
projection: proj.base.clone(),
PlaceRef {
base: &base,
projection: &proj.base,
},
buf,
autoderef,
@ -209,9 +209,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
(None, PlaceBase::Local(local)) => {
if self.body.local_decls[*local].is_ref_for_guard() {
self.append_place_to_string(
&Place {
base: base.clone(),
projection: proj.base.clone(),
PlaceRef {
base: &base,
projection: &proj.base,
},
buf,
autoderef,
@ -221,9 +221,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
// FIXME deduplicate this and the _ => body below
buf.push_str(&"*");
self.append_place_to_string(
&Place {
base: base.clone(),
projection: proj.base.clone(),
PlaceRef {
base: &base,
projection: &proj.base,
},
buf,
autoderef,
@ -235,9 +235,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
_ => {
buf.push_str(&"*");
self.append_place_to_string(
&Place {
base: base.clone(),
projection: proj.base.clone(),
PlaceRef {
base: &base,
projection: &proj.base,
},
buf,
autoderef,
@ -250,9 +250,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
}
ProjectionElem::Downcast(..) => {
self.append_place_to_string(
&Place {
base: base.clone(),
projection: proj.base.clone(),
PlaceRef {
base: &base,
projection: &proj.base,
},
buf,
autoderef,
@ -273,13 +273,13 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
buf.push_str(&name);
} else {
let field_name = self.describe_field(&Place {
base: base.clone(),
base: (*base).clone(),
projection: proj.base.clone(),
}, field);
self.append_place_to_string(
&Place {
base: base.clone(),
projection: proj.base.clone(),
PlaceRef {
base: &base,
projection: &proj.base,
},
buf,
autoderef,
@ -292,9 +292,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
autoderef = true;
self.append_place_to_string(
&Place {
base: base.clone(),
projection: proj.base.clone(),
PlaceRef {
base: &base,
projection: &proj.base,
},
buf,
autoderef,
@ -312,9 +312,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
// then use another while the borrow is held, don't output indices details
// to avoid confusing the end-user
self.append_place_to_string(
&Place {
base: base.clone(),
projection: proj.base.clone(),
PlaceRef {
base: &base,
projection: &proj.base,
},
buf,
autoderef,
@ -436,14 +436,14 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
}
/// Checks if a place is a thread-local static.
pub fn is_place_thread_local(&self, place: &Place<'tcx>) -> bool {
if let Place {
pub fn is_place_thread_local(&self, place_ref: PlaceRef<'cx, 'tcx>) -> bool {
if let PlaceRef {
base: PlaceBase::Static(box Static {
kind: StaticKind::Static(def_id),
..
}),
projection: None,
} = place {
} = place_ref {
let attrs = self.infcx.tcx.get_attrs(*def_id);
let is_thread_local = attrs.iter().any(|attr| attr.check_name(sym::thread_local));
@ -487,7 +487,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
// Look up the provided place and work out the move path index for it,
// we'll use this to check whether it was originally from an overloaded
// operator.
match self.move_data.rev_lookup.find(deref_base) {
match self.move_data.rev_lookup.find(deref_base.as_place_ref()) {
LookupResult::Exact(mpi) | LookupResult::Parent(Some(mpi)) => {
debug!("borrowed_content_source: mpi={:?}", mpi);
@ -775,7 +775,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
/// Finds the spans associated to a move or copy of move_place at location.
pub(super) fn move_spans(
&self,
moved_place: &Place<'tcx>, // Could also be an upvar.
moved_place: PlaceRef<'cx, 'tcx>, // Could also be an upvar.
location: Location,
) -> UseSpans {
use self::UseSpans::*;
@ -854,7 +854,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
def_id, is_generator, places
);
if let Some((args_span, var_span)) = self.closure_span(
*def_id, &Place::from(target), places
*def_id, Place::from(target).as_place_ref(), places
) {
return ClosureUse {
is_generator,
@ -878,7 +878,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
fn closure_span(
&self,
def_id: DefId,
target_place: &Place<'tcx>,
target_place: PlaceRef<'cx, 'tcx>,
places: &Vec<Operand<'tcx>>,
) -> Option<(Span, Span)> {
debug!(
@ -894,7 +894,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
for (upvar, place) in self.infcx.tcx.upvars(def_id)?.values().zip(places) {
match place {
Operand::Copy(place) |
Operand::Move(place) if target_place == place => {
Operand::Move(place) if target_place == place.as_place_ref() => {
debug!("closure_span: found captured local {:?}", place);
return Some((*args_span, upvar.span));
},

View file

@ -10,9 +10,8 @@ use rustc::lint::builtin::{MUTABLE_BORROW_RESERVATION_CONFLICT};
use rustc::middle::borrowck::SignalledError;
use rustc::mir::{AggregateKind, BasicBlock, BorrowCheckResult, BorrowKind};
use rustc::mir::{
ClearCrossCrate, Local, Location, Body, Mutability, Operand, Place, PlaceBase, Static,
StaticKind
ClearCrossCrate, Local, Location, Body, Mutability, Operand, Place, PlaceBase, PlaceRef,
Static, StaticKind
};
use rustc::mir::{Field, Projection, ProjectionElem, Rvalue, Statement, StatementKind};
use rustc::mir::{Terminator, TerminatorKind};
@ -474,10 +473,10 @@ crate struct MirBorrowckCtxt<'cx, 'tcx> {
/// `BTreeMap` is used to preserve the order of insertions when iterating. This is necessary
/// when errors in the map are being re-added to the error buffer so that errors with the
/// same primary span come out in a consistent order.
move_error_reported: BTreeMap<Vec<MoveOutIndex>, (Place<'tcx>, DiagnosticBuilder<'cx>)>,
move_error_reported: BTreeMap<Vec<MoveOutIndex>, (PlaceRef<'cx, 'tcx>, DiagnosticBuilder<'cx>)>,
/// This field keeps track of errors reported in the checking of uninitialized variables,
/// so that we don't report seemingly duplicate errors.
uninitialized_error_reported: FxHashSet<Place<'tcx>>,
uninitialized_error_reported: FxHashSet<PlaceRef<'cx, 'tcx>>,
/// Errors to be reported buffer
errors_buffer: Vec<Diagnostic>,
/// This field keeps track of all the local variables that are declared mut and are mutated.
@ -520,7 +519,7 @@ impl<'cx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx, 'tcx
fn visit_statement_entry(
&mut self,
location: Location,
stmt: &Statement<'tcx>,
stmt: &'cx Statement<'tcx>,
flow_state: &Self::FlowState,
) {
debug!(
@ -561,7 +560,7 @@ impl<'cx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx, 'tcx
self.check_if_path_or_subpath_is_moved(
location,
InitializationRequiringAction::Use,
(place, span),
(place.as_place_ref(), span),
flow_state,
);
}
@ -592,7 +591,7 @@ impl<'cx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx, 'tcx
self.check_if_path_or_subpath_is_moved(
location,
InitializationRequiringAction::Use,
(output, o.span),
(output.as_place_ref(), o.span),
flow_state,
);
} else {
@ -631,7 +630,7 @@ impl<'cx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx, 'tcx
fn visit_terminator_entry(
&mut self,
location: Location,
term: &Terminator<'tcx>,
term: &'cx Terminator<'tcx>,
flow_state: &Self::FlowState,
) {
let loc = location;
@ -1144,7 +1143,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
fn mutate_place(
&mut self,
location: Location,
place_span: (&Place<'tcx>, Span),
place_span: (&'cx Place<'tcx>, Span),
kind: AccessDepth,
mode: MutateMode,
flow_state: &Flows<'cx, 'tcx>,
@ -1155,7 +1154,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
self.check_if_path_or_subpath_is_moved(
location,
InitializationRequiringAction::Update,
place_span,
(place_span.0.as_place_ref(), place_span.1),
flow_state,
);
}
@ -1196,7 +1195,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
fn consume_rvalue(
&mut self,
location: Location,
(rvalue, span): (&Rvalue<'tcx>, Span),
(rvalue, span): (&'cx Rvalue<'tcx>, Span),
flow_state: &Flows<'cx, 'tcx>,
) {
match *rvalue {
@ -1233,7 +1232,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
self.check_if_path_or_subpath_is_moved(
location,
action,
(place, span),
(place.as_place_ref(), span),
flow_state,
);
}
@ -1261,7 +1260,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
self.check_if_path_or_subpath_is_moved(
location,
InitializationRequiringAction::Use,
(place, span),
(place.as_place_ref(), span),
flow_state,
);
}
@ -1310,7 +1309,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
fn propagate_closure_used_mut_upvar(&mut self, operand: &Operand<'tcx>) {
let propagate_closure_used_mut_place = |this: &mut Self, place: &Place<'tcx>| {
if place.projection.is_some() {
if let Some(field) = this.is_upvar_field_projection(place) {
if let Some(field) = this.is_upvar_field_projection(place.as_place_ref()) {
this.used_mut_upvars.push(field);
}
} else if let PlaceBase::Local(local) = place.base {
@ -1383,7 +1382,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
fn consume_operand(
&mut self,
location: Location,
(operand, span): (&Operand<'tcx>, Span),
(operand, span): (&'cx Operand<'tcx>, Span),
flow_state: &Flows<'cx, 'tcx>,
) {
match *operand {
@ -1402,7 +1401,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
self.check_if_path_or_subpath_is_moved(
location,
InitializationRequiringAction::Use,
(place, span),
(place.as_place_ref(), span),
flow_state,
);
}
@ -1420,7 +1419,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
self.check_if_path_or_subpath_is_moved(
location,
InitializationRequiringAction::Use,
(place, span),
(place.as_place_ref(), span),
flow_state,
);
}
@ -1438,8 +1437,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
) {
debug!("check_for_invalidation_at_exit({:?})", borrow);
let place = &borrow.borrowed_place;
let root_place =
self.prefixes(&place.base, &place.projection, PrefixSet::All).last().unwrap();
let root_place = self.prefixes(place.as_place_ref(), PrefixSet::All).last().unwrap();
// FIXME(nll-rfc#40): do more precise destructor tracking here. For now
// we just know that all locals are dropped at function exit (otherwise
@ -1447,8 +1445,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
//
// FIXME: allow thread-locals to borrow other thread locals?
assert!(root_place.1.is_none());
let (might_be_alive, will_be_dropped) = match root_place.0 {
assert!(root_place.projection.is_none());
let (might_be_alive, will_be_dropped) = match root_place.base {
PlaceBase::Static(box Static {
kind: StaticKind::Promoted(_),
..
@ -1461,10 +1459,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
}) => {
// Thread-locals might be dropped after the function exits, but
// "true" statics will never be.
(true, self.is_place_thread_local(&Place {
base: root_place.0.clone(),
projection: root_place.1.clone(),
}))
(true, self.is_place_thread_local(root_place))
}
PlaceBase::Local(_) => {
// Locals are always dropped at function exit, and if they
@ -1488,10 +1483,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
self.body,
place,
borrow.kind,
&Place {
base: root_place.0.clone(),
projection: root_place.1.clone(),
},
root_place,
sd,
places_conflict::PlaceConflictBias::Overlap,
) {
@ -1579,7 +1571,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
&mut self,
location: Location,
desired_action: InitializationRequiringAction,
place_span: (&Place<'tcx>, Span),
place_span: (PlaceRef<'cx, 'tcx>, Span),
flow_state: &Flows<'cx, 'tcx>,
) {
let maybe_uninits = &flow_state.uninits;
@ -1626,7 +1618,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
self.report_use_of_moved_or_uninitialized(
location,
desired_action,
(&prefix, place_span.0, place_span.1),
(prefix, place_span.0, place_span.1),
mpi,
);
return; // don't bother finding other problems.
@ -1647,7 +1639,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
&mut self,
location: Location,
desired_action: InitializationRequiringAction,
place_span: (&Place<'tcx>, Span),
place_span: (PlaceRef<'cx, 'tcx>, Span),
flow_state: &Flows<'cx, 'tcx>,
) {
let maybe_uninits = &flow_state.uninits;
@ -1704,22 +1696,16 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
/// static variable, as we do not track those in the MoveData.
fn move_path_closest_to(
&mut self,
place: &Place<'tcx>,
) -> Result<(Place<'tcx>, MovePathIndex), NoMovePathFound> {
let mut last_prefix = &place.base;
place: PlaceRef<'cx, 'tcx>,
) -> Result<(PlaceRef<'cx, 'tcx>, MovePathIndex), NoMovePathFound> {
let mut last_prefix = place.base;
for prefix in self.prefixes(&place.base, &place.projection, PrefixSet::All) {
if let Some(mpi) = self.move_path_for_place(&Place {
base: prefix.0.clone(),
projection: prefix.1.clone(),
}) {
return Ok((Place {
base: prefix.0.clone(),
projection: prefix.1.clone(),
}, mpi));
for prefix in self.prefixes(place, PrefixSet::All) {
if let Some(mpi) = self.move_path_for_place(prefix) {
return Ok((prefix, mpi));
}
last_prefix = prefix.0;
last_prefix = prefix.base;
}
match last_prefix {
@ -1728,7 +1714,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
}
}
fn move_path_for_place(&mut self, place: &Place<'tcx>) -> Option<MovePathIndex> {
fn move_path_for_place(&mut self, place: PlaceRef<'cx, 'tcx>) -> Option<MovePathIndex> {
// If returns None, then there is no move path corresponding
// to a direct owner of `place` (which means there is nothing
// that borrowck tracks for its analysis).
@ -1742,7 +1728,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
fn check_if_assigned_path_is_moved(
&mut self,
location: Location,
(place, span): (&Place<'tcx>, Span),
(place, span): (&'cx Place<'tcx>, Span),
flow_state: &Flows<'cx, 'tcx>,
) {
debug!("check_if_assigned_path_is_moved place: {:?}", place);
@ -1766,9 +1752,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
ProjectionElem::Deref => {
self.check_if_full_path_is_moved(
location, InitializationRequiringAction::Use,
(&Place {
base: place.base.clone(),
projection: base.clone(),
(PlaceRef {
base: &place.base,
projection: base,
}, span), flow_state);
// (base initialized; no need to
// recur further)
@ -1790,9 +1776,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
ty::Adt(def, _) if def.has_dtor(tcx) => {
self.check_if_path_or_subpath_is_moved(
location, InitializationRequiringAction::Assignment,
(&Place {
base: place.base.clone(),
projection: base.clone(),
(PlaceRef {
base: &place.base,
projection: base,
}, span), flow_state);
// (base initialized; no need to
@ -1803,9 +1789,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
// Once `let s; s.x = V; read(s.x);`,
// is allowed, remove this match arm.
ty::Adt(..) | ty::Tuple(..) => {
check_parent_of_field(self, location, &Place {
base: place.base.clone(),
projection: base.clone(),
check_parent_of_field(self, location, PlaceRef {
base: &place.base,
projection: base,
}, span, flow_state);
if let PlaceBase::Local(local) = place.base {
@ -1832,7 +1818,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
fn check_parent_of_field<'cx, 'tcx>(
this: &mut MirBorrowckCtxt<'cx, 'tcx>,
location: Location,
base: &Place<'tcx>,
base: PlaceRef<'cx, 'tcx>,
span: Span,
flow_state: &Flows<'cx, 'tcx>,
) {
@ -1872,11 +1858,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
// Find the shortest uninitialized prefix you can reach
// without going over a Deref.
let mut shortest_uninit_seen = None;
for prefix in this.prefixes(&base.base, &base.projection, PrefixSet::Shallow) {
let mpi = match this.move_path_for_place(&Place {
base: prefix.0.clone(),
projection: prefix.1.clone(),
}) {
for prefix in this.prefixes(base, PrefixSet::Shallow) {
let mpi = match this.move_path_for_place(prefix) {
Some(mpi) => mpi, None => continue,
};
@ -1896,7 +1879,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
// no move out from an earlier location) then this is an attempt at initialization
// of the union - we should error in that case.
let tcx = this.infcx.tcx;
if let ty::Adt(def, _) = base.ty(this.body, tcx).ty.sty {
if let ty::Adt(def, _) =
Place::ty_from(base.base, base.projection, this.body, tcx).ty.sty
{
if def.is_union() {
if this.move_data.path_map[mpi].iter().any(|moi| {
this.move_data.moves[*moi].source.is_predecessor_of(
@ -1911,10 +1896,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
this.report_use_of_moved_or_uninitialized(
location,
InitializationRequiringAction::PartialAssignment,
(&Place {
base: prefix.0.clone(),
projection: prefix.1.clone(),
}, base, span),
(prefix, base, span),
mpi,
);
}
@ -2103,12 +2085,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
} => {}
RootPlace {
place_base,
place_projection: Some(proj),
place_projection: place_projection @ Some(_),
is_local_mutation_allowed: _,
} => {
if let Some(field) = self.is_upvar_field_projection(&Place {
base: place_base.clone(),
projection: Some(proj.clone()),
if let Some(field) = self.is_upvar_field_projection(PlaceRef {
base: &place_base,
projection: &place_projection,
}) {
self.used_mut_upvars.push(field);
}
@ -2193,9 +2175,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
// Mutably borrowed data is mutable, but only if we have a
// unique path to the `&mut`
hir::MutMutable => {
let mode = match self.is_upvar_field_projection(&Place {
base: place_base.clone(),
projection: place_projection.clone(),
let mode = match self.is_upvar_field_projection(PlaceRef {
base: &place_base,
projection: &place_projection,
}) {
Some(field)
if self.upvars[field.index()].by_ref =>
@ -2239,9 +2221,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
| ProjectionElem::ConstantIndex { .. }
| ProjectionElem::Subslice { .. }
| ProjectionElem::Downcast(..) => {
let upvar_field_projection = self.is_upvar_field_projection(&Place {
base: place_base.clone(),
projection: place_projection.clone(),
let upvar_field_projection = self.is_upvar_field_projection(PlaceRef {
base: &place_base,
projection: &place_projection,
});
if let Some(field) = upvar_field_projection {
let upvar = &self.upvars[field.index()];
@ -2306,15 +2288,15 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
/// then returns the index of the field being projected. Note that this closure will always
/// be `self` in the current MIR, because that is the only time we directly access the fields
/// of a closure type.
pub fn is_upvar_field_projection(&self, place: &Place<'tcx>) -> Option<Field> {
let mut place_projection = place.projection.clone();
pub fn is_upvar_field_projection(&self, place_ref: PlaceRef<'cx, 'tcx>) -> Option<Field> {
let mut place_projection = place_ref.projection;
let mut by_ref = false;
if let Some(box Projection {
base,
elem: ProjectionElem::Deref,
}) = place_projection {
place_projection = base;
place_projection = &base;
by_ref = true;
}
@ -2324,11 +2306,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
elem: ProjectionElem::Field(field, _ty),
}) => {
let tcx = self.infcx.tcx;
let base_ty = Place::ty_from(&place.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) {
Some(field)
Some(*field)
} else {
None
}

View file

@ -131,7 +131,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
}
}
let move_spans = self.move_spans(&original_path, location);
let move_spans = self.move_spans(original_path.as_place_ref(), location);
grouped_errors.push(GroupedMoveError::OtherIllegalMove {
use_spans: move_spans,
original_path,
@ -160,7 +160,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
let from_simple_let = match_place.is_none();
let match_place = match_place.as_ref().unwrap_or(move_from);
match self.move_data.rev_lookup.find(match_place) {
match self.move_data.rev_lookup.find(match_place.as_place_ref()) {
// Error with the match place
LookupResult::Parent(_) => {
for ge in &mut *grouped_errors {
@ -192,7 +192,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
}
// Error with the pattern
LookupResult::Exact(_) => {
let mpi = match self.move_data.rev_lookup.find(move_from) {
let mpi = match self.move_data.rev_lookup.find(move_from.as_place_ref()) {
LookupResult::Parent(Some(mpi)) => mpi,
// move_from should be a projection from match_place.
_ => unreachable!("Probably not unreachable..."),
@ -242,7 +242,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
};
debug!("report: original_path={:?} span={:?}, kind={:?} \
original_path.is_upvar_field_projection={:?}", original_path, span, kind,
self.is_upvar_field_projection(original_path));
self.is_upvar_field_projection(original_path.as_place_ref()));
(
match kind {
IllegalMoveOriginKind::Static => {
@ -308,11 +308,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
// 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 upvar_field = self.prefixes(&move_place.base, &move_place.projection, PrefixSet::All)
.find_map(|p| self.is_upvar_field_projection(&Place {
base: p.0.clone(),
projection: p.1.clone(),
}));
let upvar_field = self.prefixes(move_place.as_place_ref(), PrefixSet::All)
.find_map(|p| self.is_upvar_field_projection(p));
let deref_base = match deref_target_place.projection {
Some(box Projection { ref base, elem: ProjectionElem::Deref }) => Place {
@ -368,7 +365,10 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
let place_name = self.describe_place(move_place).unwrap();
let place_description = if self.is_upvar_field_projection(move_place).is_some() {
let place_description = if self
.is_upvar_field_projection(move_place.as_place_ref())
.is_some()
{
format!("`{}`, a {}", place_name, capture_description)
} else {
format!(

View file

@ -75,7 +75,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
));
item_msg = format!("`{}`", access_place_desc.unwrap());
if self.is_upvar_field_projection(access_place).is_some() {
if self.is_upvar_field_projection(access_place.as_place_ref()).is_some() {
reason = ", as it is not declared as mutable".to_string();
} else {
let name = self.upvars[upvar_index.index()].name;
@ -100,11 +100,12 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
the_place_err.ty(self.body, self.infcx.tcx).ty
));
reason = if self.is_upvar_field_projection(access_place).is_some() {
", as it is a captured variable in a `Fn` closure".to_string()
} else {
", as `Fn` closures cannot mutate their captured variables".to_string()
}
reason =
if self.is_upvar_field_projection(access_place.as_place_ref()).is_some() {
", as it is a captured variable in a `Fn` closure".to_string()
} else {
", as `Fn` closures cannot mutate their captured variables".to_string()
}
} else if {
if let (PlaceBase::Local(local), None) = (&the_place_err.base, base) {
self.body.local_decls[*local].is_ref_for_guard()

View file

@ -252,7 +252,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
Some(Cause::LiveVar(local, location)) => {
let span = body.source_info(location).span;
let spans = self
.move_spans(&Place::from(local), location)
.move_spans(Place::from(local).as_place_ref(), location)
.or_else(|| self.borrow_spans(span, location));
let borrow_location = location;

View file

@ -50,7 +50,7 @@ pub(super) fn each_borrow_involving_path<'tcx, F, I, S>(
body,
&borrowed.borrowed_place,
borrowed.kind,
place,
place.as_place_ref(),
access,
places_conflict::PlaceConflictBias::Overlap,
) {

View file

@ -3,8 +3,8 @@ use crate::borrow_check::Overlap;
use crate::borrow_check::{Deep, Shallow, AccessDepth};
use rustc::hir;
use rustc::mir::{
BorrowKind, Body, Place, PlaceBase, Projection, ProjectionElem, ProjectionsIter,
StaticKind
Body, BorrowKind, Place, PlaceBase, PlaceRef, Projection, ProjectionElem, ProjectionsIter,
StaticKind,
};
use rustc::ty::{self, TyCtxt};
use std::cmp::max;
@ -36,7 +36,7 @@ crate fn places_conflict<'tcx>(
body,
borrow_place,
BorrowKind::Mut { allow_two_phase_borrow: true },
access_place,
access_place.as_place_ref(),
AccessDepth::Deep,
bias,
)
@ -51,7 +51,7 @@ pub(super) fn borrow_conflicts_with_place<'tcx>(
body: &Body<'tcx>,
borrow_place: &Place<'tcx>,
borrow_kind: BorrowKind,
access_place: &Place<'tcx>,
access_place: PlaceRef<'_, 'tcx>,
access: AccessDepth,
bias: PlaceConflictBias,
) -> bool {
@ -66,7 +66,7 @@ pub(super) fn borrow_conflicts_with_place<'tcx>(
base: PlaceBase::Local(l1),
projection: None,
} = borrow_place {
if let Place {
if let PlaceRef {
base: PlaceBase::Local(l2),
projection: None,
} = access_place {

View file

@ -11,17 +11,17 @@ use super::MirBorrowckCtxt;
use rustc::hir;
use rustc::ty::{self, TyCtxt};
use rustc::mir::{Body, Place, PlaceBase, Projection, ProjectionElem};
use rustc::mir::{Body, Place, PlaceBase, PlaceRef, ProjectionElem};
pub trait IsPrefixOf<'tcx> {
fn is_prefix_of(&self, other: &Place<'tcx>) -> bool;
pub trait IsPrefixOf<'cx, 'tcx> {
fn is_prefix_of(&self, other: PlaceRef<'cx, 'tcx>) -> bool;
}
impl<'tcx> IsPrefixOf<'tcx> for Place<'tcx> {
fn is_prefix_of(&self, other: &Place<'tcx>) -> bool {
let mut cursor = &other.projection;
impl<'cx, 'tcx> IsPrefixOf<'cx, 'tcx> for PlaceRef<'cx, 'tcx> {
fn is_prefix_of(&self, other: PlaceRef<'cx, 'tcx>) -> bool {
let mut cursor = other.projection;
loop {
if self.projection == *cursor {
if self.projection == cursor {
return self.base == other.base;
}
@ -37,7 +37,7 @@ pub(super) struct Prefixes<'cx, 'tcx> {
body: &'cx Body<'tcx>,
tcx: TyCtxt<'tcx>,
kind: PrefixSet,
next: Option<(&'cx PlaceBase<'tcx>, &'cx Option<Box<Projection<'tcx>>>)>,
next: Option<(PlaceRef<'cx, 'tcx>)>,
}
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
@ -58,12 +58,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
/// terminating the iteration early based on `kind`.
pub(super) fn prefixes(
&self,
place_base: &'cx PlaceBase<'tcx>,
place_projection: &'cx Option<Box<Projection<'tcx>>>,
place_ref: PlaceRef<'cx, 'tcx>,
kind: PrefixSet,
) -> Prefixes<'cx, 'tcx> {
Prefixes {
next: Some((place_base, place_projection)),
next: Some(place_ref),
kind,
body: self.body,
tcx: self.infcx.tcx,
@ -72,7 +71,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
}
impl<'cx, 'tcx> Iterator for Prefixes<'cx, 'tcx> {
type Item = (&'cx PlaceBase<'tcx>, &'cx Option<Box<Projection<'tcx>>>);
type Item = PlaceRef<'cx, 'tcx>;
fn next(&mut self) -> Option<Self::Item> {
let mut cursor = self.next?;
@ -82,27 +81,42 @@ impl<'cx, 'tcx> Iterator for Prefixes<'cx, 'tcx> {
// downcasts here, but may return a base of a downcast).
'cursor: loop {
let proj = match cursor {
(&PlaceBase::Local(_), &None)
let proj = match &cursor {
PlaceRef {
base: PlaceBase::Local(_),
projection: None,
}
| // search yielded this leaf
(&PlaceBase::Static(_), &None) => {
PlaceRef {
base: PlaceBase::Static(_),
projection: None,
} => {
self.next = None;
return Some(cursor);
}
(_, &Some(ref proj)) => proj,
PlaceRef {
base: _,
projection: Some(proj),
} => proj,
};
match proj.elem {
ProjectionElem::Field(_ /*field*/, _ /*ty*/) => {
// FIXME: add union handling
self.next = Some((cursor.0, &proj.base));
self.next = Some(PlaceRef {
base: cursor.base,
projection: &proj.base,
});
return Some(cursor);
}
ProjectionElem::Downcast(..) |
ProjectionElem::Subslice { .. } |
ProjectionElem::ConstantIndex { .. } |
ProjectionElem::Index(_) => {
cursor = (cursor.0, &proj.base);
cursor = PlaceRef {
base: cursor.base,
projection: &proj.base,
};
continue 'cursor;
}
ProjectionElem::Deref => {
@ -123,7 +137,10 @@ impl<'cx, 'tcx> Iterator for Prefixes<'cx, 'tcx> {
PrefixSet::All => {
// all prefixes: just blindly enqueue the base
// of the projection
self.next = Some((cursor.0, &proj.base));
self.next = Some(PlaceRef {
base: cursor.base,
projection: &proj.base,
});
return Some(cursor);
}
PrefixSet::Supporting => {
@ -136,7 +153,7 @@ impl<'cx, 'tcx> Iterator for Prefixes<'cx, 'tcx> {
// derefs, except we stop at the deref of a shared
// reference.
let ty = Place::ty_from(cursor.0, &proj.base, self.body, self.tcx).ty;
let ty = Place::ty_from(cursor.base, &proj.base, self.body, self.tcx).ty;
match ty.sty {
ty::RawPtr(_) |
ty::Ref(
@ -154,12 +171,18 @@ impl<'cx, 'tcx> Iterator for Prefixes<'cx, 'tcx> {
_, /*ty*/
hir::MutMutable,
) => {
self.next = Some((cursor.0, &proj.base));
self.next = Some(PlaceRef {
base: cursor.base,
projection: &proj.base,
});
return Some(cursor);
}
ty::Adt(..) if ty.is_box() => {
self.next = Some((cursor.0, &proj.base));
self.next = Some(PlaceRef {
base: cursor.base,
projection: &proj.base,
});
return Some(cursor);
}

View file

@ -171,7 +171,7 @@ pub(crate) fn drop_flag_effects_for_function_entry<'tcx, F>(
let move_data = &ctxt.move_data;
for arg in body.args_iter() {
let place = mir::Place::from(arg);
let lookup_result = move_data.rev_lookup.find(&place);
let lookup_result = move_data.rev_lookup.find(place.as_place_ref());
on_lookup_result_bits(tcx, body, move_data,
lookup_result,
|mpi| callback(mpi, DropFlagState::Present));

View file

@ -309,7 +309,7 @@ impl<'a, 'tcx> BitDenotation<'tcx> for MaybeInitializedPlaces<'a, 'tcx> {
// when a call returns successfully, that means we need to set
// the bits for that dest_place to 1 (initialized).
on_lookup_result_bits(self.tcx, self.body, self.move_data(),
self.move_data().rev_lookup.find(dest_place),
self.move_data().rev_lookup.find(dest_place.as_place_ref()),
|mpi| { in_out.insert(mpi); });
}
}
@ -367,7 +367,7 @@ impl<'a, 'tcx> BitDenotation<'tcx> for MaybeUninitializedPlaces<'a, 'tcx> {
// when a call returns successfully, that means we need to set
// the bits for that dest_place to 0 (initialized).
on_lookup_result_bits(self.tcx, self.body, self.move_data(),
self.move_data().rev_lookup.find(dest_place),
self.move_data().rev_lookup.find(dest_place.as_place_ref()),
|mpi| { in_out.remove(mpi); });
}
}
@ -423,7 +423,7 @@ impl<'a, 'tcx> BitDenotation<'tcx> for DefinitelyInitializedPlaces<'a, 'tcx> {
// when a call returns successfully, that means we need to set
// the bits for that dest_place to 1 (initialized).
on_lookup_result_bits(self.tcx, self.body, self.move_data(),
self.move_data().rev_lookup.find(dest_place),
self.move_data().rev_lookup.find(dest_place.as_place_ref()),
|mpi| { in_out.insert(mpi); });
}
}

View file

@ -314,12 +314,12 @@ pub(crate) trait DataflowResultsConsumer<'a, 'tcx: 'a> {
fn visit_statement_entry(&mut self,
_loc: Location,
_stmt: &Statement<'tcx>,
_stmt: &'a Statement<'tcx>,
_flow_state: &Self::FlowState) {}
fn visit_terminator_entry(&mut self,
_loc: Location,
_term: &Terminator<'tcx>,
_term: &'a Terminator<'tcx>,
_flow_state: &Self::FlowState) {}
// Main entry point: this drives the processing of results.

View file

@ -454,7 +454,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
_ => place.clone()
};
if let LookupResult::Exact(path) = self.builder.data.rev_lookup.find(&place) {
if let LookupResult::Exact(path) = self.builder.data.rev_lookup.find(place.as_place_ref()) {
let init = self.builder.data.inits.push(Init {
location: InitLocation::Statement(self.loc),
path,

View file

@ -240,8 +240,8 @@ impl MovePathLookup {
// alternative will *not* create a MovePath on the fly for an
// unknown place, but will rather return the nearest available
// parent.
pub fn find(&self, place: &Place<'tcx>) -> LookupResult {
place.iterate(|place_base, place_projection| {
pub fn find(&self, place_ref: PlaceRef<'cx, 'tcx>) -> LookupResult {
place_ref.iterate(|place_base, place_projection| {
let mut result = match place_base {
PlaceBase::Local(local) => self.locals[*local],
PlaceBase::Static(..) => return LookupResult::Parent(None),

View file

@ -105,7 +105,7 @@ fn find_dead_unwinds<'tcx>(
init_data.apply_location(tcx, body, env, loc);
}
let path = match env.move_data.rev_lookup.find(location) {
let path = match env.move_data.rev_lookup.find(location.as_place_ref()) {
LookupResult::Exact(e) => e,
LookupResult::Parent(..) => {
debug!("find_dead_unwinds: has parent; skipping");
@ -360,7 +360,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
statement_index: data.statements.len()
});
let path = self.move_data().rev_lookup.find(location);
let path = self.move_data().rev_lookup.find(location.as_place_ref());
debug!("collect_drop_flags: {:?}, place {:?} ({:?})",
bb, location, path);
@ -399,7 +399,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
match terminator.kind {
TerminatorKind::Drop { ref location, target, unwind } => {
let init_data = self.initialization_data_at(loc);
match self.move_data().rev_lookup.find(location) {
match self.move_data().rev_lookup.find(location.as_place_ref()) {
LookupResult::Exact(path) => {
elaborate_drop(
&mut Elaborator {
@ -488,7 +488,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
is_cleanup: false,
});
match self.move_data().rev_lookup.find(location) {
match self.move_data().rev_lookup.find(location.as_place_ref()) {
LookupResult::Exact(path) => {
debug!("elaborate_drop_and_replace({:?}) - tracked {:?}", terminator, path);
let init_data = self.initialization_data_at(loc);
@ -558,7 +558,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
assert!(!self.patch.is_patched(bb));
let loc = Location { block: tgt, statement_index: 0 };
let path = self.move_data().rev_lookup.find(place);
let path = self.move_data().rev_lookup.find(place.as_place_ref());
on_lookup_result_bits(
self.tcx, self.body, self.move_data(), path,
|child| self.set_drop_flag(loc, child, DropFlagState::Present)
@ -632,7 +632,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
assert!(!self.patch.is_patched(bb));
let loc = Location { block: bb, statement_index: data.statements.len() };
let path = self.move_data().rev_lookup.find(place);
let path = self.move_data().rev_lookup.find(place.as_place_ref());
on_lookup_result_bits(
self.tcx, self.body, self.move_data(), path,
|child| self.set_drop_flag(loc, child, DropFlagState::Present)

View file

@ -168,7 +168,7 @@ fn each_block<'tcx, O>(
if place == peek_arg_place {
if let mir::Rvalue::Ref(_, mir::BorrowKind::Shared, ref peeking_at_place) = **rvalue {
// Okay, our search is over.
match move_data.rev_lookup.find(peeking_at_place) {
match move_data.rev_lookup.find(peeking_at_place.as_place_ref()) {
LookupResult::Exact(peek_mpi) => {
let bit_state = on_entry.contains(peek_mpi);
debug!("rustc_peek({:?} = &{:?}) bit_state: {}",
@ -192,7 +192,7 @@ fn each_block<'tcx, O>(
}
}
let lhs_mpi = move_data.rev_lookup.find(place);
let lhs_mpi = move_data.rev_lookup.find(place.as_place_ref());
debug!("rustc_peek: computing effect on place: {:?} ({:?}) in stmt: {:?}",
place, lhs_mpi, stmt);