Avoid cloning Place in report_use_of_moved_or_uninitialized and friends
This commit is contained in:
parent
ec65db07ef
commit
46f81fc53d
17 changed files with 252 additions and 230 deletions
|
@ -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
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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));
|
||||
},
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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!(
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
) {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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); });
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue