diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index f27cc632c1f..b113f87fb86 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -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>>, @@ -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 { + 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 diff --git a/src/librustc_mir/borrow_check/conflict_errors.rs b/src/librustc_mir/borrow_check/conflict_errors.rs index 7bd3a4729ac..ce4460e8ded 100644 --- a/src/librustc_mir/borrow_check/conflict_errors.rs +++ b/src/librustc_mir/borrow_check/conflict_errors.rs @@ -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") diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index 54f041865a1..aa772e64aa2 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -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 { - 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 { 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>, ) -> 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)); }, diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index bebdd68cb05..b159bf4dd04 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -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, (Place<'tcx>, DiagnosticBuilder<'cx>)>, + move_error_reported: BTreeMap, (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>, + uninitialized_error_reported: FxHashSet>, /// Errors to be reported buffer errors_buffer: Vec, /// 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 { + fn move_path_for_place(&mut self, place: PlaceRef<'cx, 'tcx>) -> Option { // 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 { - let mut place_projection = place.projection.clone(); + pub fn is_upvar_field_projection(&self, place_ref: PlaceRef<'cx, 'tcx>) -> Option { + 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 } diff --git a/src/librustc_mir/borrow_check/move_errors.rs b/src/librustc_mir/borrow_check/move_errors.rs index b58d0e62a99..d933932309e 100644 --- a/src/librustc_mir/borrow_check/move_errors.rs +++ b/src/librustc_mir/borrow_check/move_errors.rs @@ -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!( diff --git a/src/librustc_mir/borrow_check/mutability_errors.rs b/src/librustc_mir/borrow_check/mutability_errors.rs index bc6c1c93a30..adde4ac85c8 100644 --- a/src/librustc_mir/borrow_check/mutability_errors.rs +++ b/src/librustc_mir/borrow_check/mutability_errors.rs @@ -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() diff --git a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs index d4ae15467be..6885baf8223 100644 --- a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs +++ b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs @@ -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; diff --git a/src/librustc_mir/borrow_check/path_utils.rs b/src/librustc_mir/borrow_check/path_utils.rs index 538ac6881d9..75065816df0 100644 --- a/src/librustc_mir/borrow_check/path_utils.rs +++ b/src/librustc_mir/borrow_check/path_utils.rs @@ -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, ) { diff --git a/src/librustc_mir/borrow_check/places_conflict.rs b/src/librustc_mir/borrow_check/places_conflict.rs index 8f7695b40e8..348214f97f2 100644 --- a/src/librustc_mir/borrow_check/places_conflict.rs +++ b/src/librustc_mir/borrow_check/places_conflict.rs @@ -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 { diff --git a/src/librustc_mir/borrow_check/prefixes.rs b/src/librustc_mir/borrow_check/prefixes.rs index 38be4ae4644..ecafd4eb115 100644 --- a/src/librustc_mir/borrow_check/prefixes.rs +++ b/src/librustc_mir/borrow_check/prefixes.rs @@ -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>>)>, + 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>>, + 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>>); + type Item = PlaceRef<'cx, 'tcx>; fn next(&mut self) -> Option { 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); } diff --git a/src/librustc_mir/dataflow/drop_flag_effects.rs b/src/librustc_mir/dataflow/drop_flag_effects.rs index 51a0a10b33d..b6dd544d395 100644 --- a/src/librustc_mir/dataflow/drop_flag_effects.rs +++ b/src/librustc_mir/dataflow/drop_flag_effects.rs @@ -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)); diff --git a/src/librustc_mir/dataflow/impls/mod.rs b/src/librustc_mir/dataflow/impls/mod.rs index 065cfe8a4e8..ade732bbb75 100644 --- a/src/librustc_mir/dataflow/impls/mod.rs +++ b/src/librustc_mir/dataflow/impls/mod.rs @@ -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); }); } } diff --git a/src/librustc_mir/dataflow/mod.rs b/src/librustc_mir/dataflow/mod.rs index f05dfad3257..3bdd3e3da04 100644 --- a/src/librustc_mir/dataflow/mod.rs +++ b/src/librustc_mir/dataflow/mod.rs @@ -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. diff --git a/src/librustc_mir/dataflow/move_paths/builder.rs b/src/librustc_mir/dataflow/move_paths/builder.rs index 8eff8b74e4f..93e8fd69361 100644 --- a/src/librustc_mir/dataflow/move_paths/builder.rs +++ b/src/librustc_mir/dataflow/move_paths/builder.rs @@ -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, diff --git a/src/librustc_mir/dataflow/move_paths/mod.rs b/src/librustc_mir/dataflow/move_paths/mod.rs index b30750850b5..5c2255882b2 100644 --- a/src/librustc_mir/dataflow/move_paths/mod.rs +++ b/src/librustc_mir/dataflow/move_paths/mod.rs @@ -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), diff --git a/src/librustc_mir/transform/elaborate_drops.rs b/src/librustc_mir/transform/elaborate_drops.rs index ad19b974d7d..0748321f605 100644 --- a/src/librustc_mir/transform/elaborate_drops.rs +++ b/src/librustc_mir/transform/elaborate_drops.rs @@ -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) diff --git a/src/librustc_mir/transform/rustc_peek.rs b/src/librustc_mir/transform/rustc_peek.rs index 6def9dc2b5e..1fd865c42fc 100644 --- a/src/librustc_mir/transform/rustc_peek.rs +++ b/src/librustc_mir/transform/rustc_peek.rs @@ -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);