Rollup merge of #114505 - ouz-a:cleanup_mir, r=RalfJung

Add documentation to has_deref

Documentation of `has_deref` needed some polish to be more clear about where it should be used and what's it's purpose.

cc https://github.com/rust-lang/rust/issues/114401

r? `@RalfJung`
This commit is contained in:
Matthias Krüger 2023-08-06 17:26:29 +02:00 committed by GitHub
commit 13de583583
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 23 additions and 17 deletions

View File

@ -441,7 +441,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
LocalRef::Place(place) => place, LocalRef::Place(place) => place,
LocalRef::UnsizedPlace(place) => bx.load_operand(place).deref(cx), LocalRef::UnsizedPlace(place) => bx.load_operand(place).deref(cx),
LocalRef::Operand(..) => { LocalRef::Operand(..) => {
if place_ref.has_deref() { if place_ref.is_indirect_first_projection() {
base = 1; base = 1;
let cg_base = self.codegen_consume( let cg_base = self.codegen_consume(
bx, bx,

View File

@ -247,7 +247,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
AddressOf(_, place) => { AddressOf(_, place) => {
// Figure out whether this is an addr_of of an already raw place. // Figure out whether this is an addr_of of an already raw place.
let place_base_raw = if place.has_deref() { let place_base_raw = if place.is_indirect_first_projection() {
let ty = self.frame().body.local_decls[place.local].ty; let ty = self.frame().body.local_decls[place.local].ty;
ty.is_unsafe_ptr() ty.is_unsafe_ptr()
} else { } else {

View File

@ -1592,14 +1592,13 @@ impl<'tcx> Place<'tcx> {
self.projection.iter().any(|elem| elem.is_indirect()) self.projection.iter().any(|elem| elem.is_indirect())
} }
/// If MirPhase >= Derefered and if projection contains Deref, /// Returns `true` if this `Place`'s first projection is `Deref`.
/// It's guaranteed to be in the first place ///
pub fn has_deref(&self) -> bool { /// This is useful because for MIR phases `AnalysisPhase::PostCleanup` and later,
// To make sure this is not accidentally used in wrong mir phase /// `Deref` projections can only occur as the first projection. In that case this method
debug_assert!( /// is equivalent to `is_indirect`, but faster.
self.projection.is_empty() || !self.projection[1..].contains(&PlaceElem::Deref) pub fn is_indirect_first_projection(&self) -> bool {
); self.as_ref().is_indirect_first_projection()
self.projection.first() == Some(&PlaceElem::Deref)
} }
/// Finds the innermost `Local` from this `Place`, *if* it is either a local itself or /// Finds the innermost `Local` from this `Place`, *if* it is either a local itself or
@ -1672,9 +1671,16 @@ impl<'tcx> PlaceRef<'tcx> {
self.projection.iter().any(|elem| elem.is_indirect()) self.projection.iter().any(|elem| elem.is_indirect())
} }
/// If MirPhase >= Derefered and if projection contains Deref, /// Returns `true` if this `Place`'s first projection is `Deref`.
/// It's guaranteed to be in the first place ///
pub fn has_deref(&self) -> bool { /// This is useful because for MIR phases `AnalysisPhase::PostCleanup` and later,
/// `Deref` projections can only occur as the first projection. In that case this method
/// is equivalent to `is_indirect`, but faster.
pub fn is_indirect_first_projection(&self) -> bool {
// To make sure this is not accidentally used in wrong mir phase
debug_assert!(
self.projection.is_empty() || !self.projection[1..].contains(&PlaceElem::Deref)
);
self.projection.first() == Some(&PlaceElem::Deref) self.projection.first() == Some(&PlaceElem::Deref)
} }

View File

@ -839,7 +839,7 @@ impl Map {
tail_elem: Option<TrackElem>, tail_elem: Option<TrackElem>,
f: &mut impl FnMut(ValueIndex), f: &mut impl FnMut(ValueIndex),
) { ) {
if place.has_deref() { if place.is_indirect_first_projection() {
// We do not track indirect places. // We do not track indirect places.
return; return;
} }

View File

@ -60,7 +60,7 @@ impl<'tcx> MirPass<'tcx> for AddRetag {
let basic_blocks = body.basic_blocks.as_mut(); let basic_blocks = body.basic_blocks.as_mut();
let local_decls = &body.local_decls; let local_decls = &body.local_decls;
let needs_retag = |place: &Place<'tcx>| { let needs_retag = |place: &Place<'tcx>| {
!place.has_deref() // we're not really interested in stores to "outside" locations, they are hard to keep track of anyway !place.is_indirect_first_projection() // we're not really interested in stores to "outside" locations, they are hard to keep track of anyway
&& may_contain_reference(place.ty(&*local_decls, tcx).ty, /*depth*/ 3, tcx) && may_contain_reference(place.ty(&*local_decls, tcx).ty, /*depth*/ 3, tcx)
&& !local_decls[place.local].is_deref_temp() && !local_decls[place.local].is_deref_temp()
}; };

View File

@ -154,7 +154,7 @@ impl<'tcx> MutVisitor<'tcx> for Replacer<'_, 'tcx> {
fn visit_operand(&mut self, operand: &mut Operand<'tcx>, loc: Location) { fn visit_operand(&mut self, operand: &mut Operand<'tcx>, loc: Location) {
if let Operand::Move(place) = *operand if let Operand::Move(place) = *operand
// A move out of a projection of a copy is equivalent to a copy of the original projection. // A move out of a projection of a copy is equivalent to a copy of the original projection.
&& !place.has_deref() && !place.is_indirect_first_projection()
&& !self.fully_moved.contains(place.local) && !self.fully_moved.contains(place.local)
{ {
*operand = Operand::Copy(place); *operand = Operand::Copy(place);

View File

@ -1170,7 +1170,7 @@ fn referent_used_exactly_once<'tcx>(
&& let [location] = *local_assignments(mir, local).as_slice() && let [location] = *local_assignments(mir, local).as_slice()
&& let Some(statement) = mir.basic_blocks[location.block].statements.get(location.statement_index) && let Some(statement) = mir.basic_blocks[location.block].statements.get(location.statement_index)
&& let StatementKind::Assign(box (_, Rvalue::Ref(_, _, place))) = statement.kind && let StatementKind::Assign(box (_, Rvalue::Ref(_, _, place))) = statement.kind
&& !place.has_deref() && !place.is_indirect_first_projection()
// Ensure not in a loop (https://github.com/rust-lang/rust-clippy/issues/9710) // Ensure not in a loop (https://github.com/rust-lang/rust-clippy/issues/9710)
&& TriColorDepthFirstSearch::new(&mir.basic_blocks).run_from(location.block, &mut CycleDetector).is_none() && TriColorDepthFirstSearch::new(&mir.basic_blocks).run_from(location.block, &mut CycleDetector).is_none()
{ {