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
This commit is contained in:
commit
9718f7a09f
@ -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.
|
||||
//
|
||||
|
@ -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(..) => {},
|
||||
}
|
||||
match place.base {
|
||||
PlaceBase::Static(_) => false,
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
true
|
||||
})
|
||||
// Reborrow of already borrowed data is ignored
|
||||
// Any errors will be caught on the initial borrow
|
||||
PlaceBase::Local(_) => !place.is_indirect(),
|
||||
}
|
||||
}
|
||||
|
@ -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<'_> {
|
||||
|
Loading…
x
Reference in New Issue
Block a user