diff options
| author | Mazdak Farrokhzad <twingoow@gmail.com> | 2019-09-05 03:59:37 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2019-09-05 03:59:37 +0200 |
| commit | 9718f7a09fc9c5b97f8b2c873faf87ba86c11fc6 (patch) | |
| tree | 143556b1e9f6ff0f837ff9407e860ea2fdc2c095 | |
| parent | d1d511df8c56af39bc491afcd7e896ed4202fdd4 (diff) | |
| parent | 96ac02b8b3aeebc463d434c57b4a2ada9a3003e6 (diff) | |
| download | rust-9718f7a09fc9c5b97f8b2c873faf87ba86c11fc6.tar.gz rust-9718f7a09fc9c5b97f8b2c873faf87ba86c11fc6.zip | |
Rollup merge of #64005 - ecstatic-morse:is-indirect, r=oli-obk
Add a `Place::is_indirect` method to determine whether a `Place` contains a `Deref` projection Working on #63860 requires tracking some property about each local. This requires differentiating `Place`s like `x` and `x.field[index]` from ones like `*x` and `*x.field`, since the first two will always access the same region of memory as `x` while the latter two may access any region of memory. This functionality is duplicated in various places across the compiler. This PR adds a helper method to `Place` which determines whether that `Place` has a `Deref` projection at any point and changes some existing code to use the new method. I've not converted `qualify_consts.rs` to use the new method, since it's not a trivial conversion and it will get replaced anyway by #63860. There may be other potential uses besides the two I change in this PR. r? @oli-obk
| -rw-r--r-- | src/librustc/mir/mod.rs | 25 | ||||
| -rw-r--r-- | src/librustc_mir/borrow_check/path_utils.rs | 23 | ||||
| -rw-r--r-- | src/librustc_mir/dataflow/impls/borrowed_locals.rs | 17 |
3 files changed, 36 insertions, 29 deletions
diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 5ac99ba1470..8956cbb2bae 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -1808,6 +1808,23 @@ pub enum ProjectionElem<V, T> { Downcast(Option<Symbol>, VariantIdx), } +impl<V, T> ProjectionElem<V, T> { + /// Returns `true` if the target of this projection may refer to a different region of memory + /// than the base. + fn is_indirect(&self) -> bool { + match self { + Self::Deref => true, + + | Self::Field(_, _) + | Self::Index(_) + | Self::ConstantIndex { .. } + | Self::Subslice { .. } + | Self::Downcast(_, _) + => false + } + } +} + /// Alias for projections as they appear in places, where the base is a place /// and the index is a local. pub type PlaceElem<'tcx> = ProjectionElem<Local, Ty<'tcx>>; @@ -1869,6 +1886,14 @@ impl<'tcx> Place<'tcx> { } } + /// Returns `true` if this `Place` contains a `Deref` projection. + /// + /// If `Place::is_indirect` returns false, the caller knows that the `Place` refers to the + /// same region of memory as its base. + pub fn is_indirect(&self) -> bool { + self.iterate(|_, mut projections| projections.any(|proj| proj.elem.is_indirect())) + } + /// Finds the innermost `Local` from this `Place`, *if* it is either a local itself or /// a single deref of a local. // diff --git a/src/librustc_mir/borrow_check/path_utils.rs b/src/librustc_mir/borrow_check/path_utils.rs index 43a012e1494..bac08090817 100644 --- a/src/librustc_mir/borrow_check/path_utils.rs +++ b/src/librustc_mir/borrow_check/path_utils.rs @@ -3,7 +3,7 @@ use crate::borrow_check::places_conflict; use crate::borrow_check::AccessDepth; use crate::dataflow::indexes::BorrowIndex; use rustc::mir::{BasicBlock, Location, Body, Place, PlaceBase}; -use rustc::mir::{ProjectionElem, BorrowKind}; +use rustc::mir::BorrowKind; use rustc::ty::{self, TyCtxt}; use rustc_data_structures::graph::dominators::Dominators; @@ -133,20 +133,11 @@ pub(super) fn is_active<'tcx>( /// Determines if a given borrow is borrowing local data /// This is called for all Yield statements on movable generators pub(super) fn borrow_of_local_data(place: &Place<'_>) -> bool { - place.iterate(|place_base, place_projection| { - match place_base { - PlaceBase::Static(..) => return false, - PlaceBase::Local(..) => {}, - } - - for proj in place_projection { - // Reborrow of already borrowed data is ignored - // Any errors will be caught on the initial borrow - if proj.elem == ProjectionElem::Deref { - return false; - } - } + match place.base { + PlaceBase::Static(_) => false, - true - }) + // Reborrow of already borrowed data is ignored + // Any errors will be caught on the initial borrow + PlaceBase::Local(_) => !place.is_indirect(), + } } diff --git a/src/librustc_mir/dataflow/impls/borrowed_locals.rs b/src/librustc_mir/dataflow/impls/borrowed_locals.rs index d94ebdbae24..1c43a553cc3 100644 --- a/src/librustc_mir/dataflow/impls/borrowed_locals.rs +++ b/src/librustc_mir/dataflow/impls/borrowed_locals.rs @@ -93,19 +93,10 @@ struct BorrowedLocalsVisitor<'gk> { } fn find_local(place: &Place<'_>) -> Option<Local> { - place.iterate(|place_base, place_projection| { - for proj in place_projection { - if proj.elem == ProjectionElem::Deref { - return None; - } - } - - if let PlaceBase::Local(local) = place_base { - Some(*local) - } else { - None - } - }) + match place.base { + PlaceBase::Local(local) if !place.is_indirect() => Some(local), + _ => None, + } } impl<'tcx> Visitor<'tcx> for BorrowedLocalsVisitor<'_> { |
