about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
authorStuart Cook <Zalathar@users.noreply.github.com>2025-09-21 14:42:35 +1000
committerGitHub <noreply@github.com>2025-09-21 14:42:35 +1000
commit5c1c47925e8669831f1c75eed0784d4ff9ac85fb (patch)
tree61c50b2a747df76bbb2e866f2953718727c9cd57 /compiler
parent6333a8b9fe3a399ab70bff9ea1a26c31ce263649 (diff)
parent7ce81d145359aa230f8fc2d7de12650091508329 (diff)
downloadrust-5c1c47925e8669831f1c75eed0784d4ff9ac85fb.tar.gz
rust-5c1c47925e8669831f1c75eed0784d4ff9ac85fb.zip
Rollup merge of #146744 - beepster4096:derefs_in_ref_prop, r=cjgillot
Deref related cleanups in ref_prop

Cherry picked from rust-lang/rust#146710

r? cjgillot
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_mir_transform/src/ref_prop.rs33
1 files changed, 13 insertions, 20 deletions
diff --git a/compiler/rustc_mir_transform/src/ref_prop.rs b/compiler/rustc_mir_transform/src/ref_prop.rs
index 6f61215cee2..b9d6e74ecae 100644
--- a/compiler/rustc_mir_transform/src/ref_prop.rs
+++ b/compiler/rustc_mir_transform/src/ref_prop.rs
@@ -195,10 +195,10 @@ fn compute_replacement<'tcx>(
     //   including DEF. This violates the DEF dominates USE condition, and so is impossible.
     let is_constant_place = |place: Place<'_>| {
         // We only allow `Deref` as the first projection, to avoid surprises.
-        if place.projection.first() == Some(&PlaceElem::Deref) {
+        if let Some((&PlaceElem::Deref, rest)) = place.projection.split_first() {
             // `place == (*some_local).xxx`, it is constant only if `some_local` is constant.
             // We approximate constness using SSAness.
-            ssa.is_ssa(place.local) && place.projection[1..].iter().all(PlaceElem::is_stable_offset)
+            ssa.is_ssa(place.local) && rest.iter().all(PlaceElem::is_stable_offset)
         } else {
             storage_live.has_single_storage(place.local)
                 && place.projection[..].iter().all(PlaceElem::is_stable_offset)
@@ -206,7 +206,7 @@ fn compute_replacement<'tcx>(
     };
 
     let mut can_perform_opt = |target: Place<'tcx>, loc: Location| {
-        if target.projection.first() == Some(&PlaceElem::Deref) {
+        if target.is_indirect_first_projection() {
             // We are creating a reborrow. As `place.local` is a reference, removing the storage
             // statements should not make it much harder for LLVM to optimize.
             storage_to_remove.insert(target.local);
@@ -266,7 +266,7 @@ fn compute_replacement<'tcx>(
             Rvalue::Ref(_, _, place) | Rvalue::RawPtr(_, place) => {
                 let mut place = *place;
                 // Try to see through `place` in order to collapse reborrow chains.
-                if place.projection.first() == Some(&PlaceElem::Deref)
+                if let Some((&PlaceElem::Deref, rest)) = place.projection.split_first()
                     && let Value::Pointer(target, inner_needs_unique) = targets[place.local]
                     // Only see through immutable reference and pointers, as we do not know yet if
                     // mutable references are fully replaced.
@@ -274,7 +274,7 @@ fn compute_replacement<'tcx>(
                     // Only collapse chain if the pointee is definitely live.
                     && can_perform_opt(target, location)
                 {
-                    place = target.project_deeper(&place.projection[1..], tcx);
+                    place = target.project_deeper(rest, tcx);
                 }
                 assert_ne!(place.local, local);
                 if is_constant_place(place) {
@@ -323,7 +323,7 @@ fn compute_replacement<'tcx>(
                 return;
             }
 
-            if place.projection.first() != Some(&PlaceElem::Deref) {
+            if !place.is_indirect_first_projection() {
                 // This is not a dereference, nothing to do.
                 return;
             }
@@ -392,20 +392,15 @@ impl<'tcx> MutVisitor<'tcx> for Replacer<'tcx> {
     }
 
     fn visit_var_debug_info(&mut self, debuginfo: &mut VarDebugInfo<'tcx>) {
-        // If the debuginfo is a pointer to another place:
-        // - if it's a reborrow, see through it;
-        // - if it's a direct borrow, increase `debuginfo.references`.
+        // If the debuginfo is a pointer to another place
+        // and it's a reborrow: see through it
         while let VarDebugInfoContents::Place(ref mut place) = debuginfo.value
             && place.projection.is_empty()
             && let Value::Pointer(target, _) = self.targets[place.local]
-            && target.projection.iter().all(|p| p.can_use_in_debuginfo())
+            && let &[PlaceElem::Deref] = &target.projection[..]
         {
-            if let Some((&PlaceElem::Deref, rest)) = target.projection.split_last() {
-                *place = Place::from(target.local).project_deeper(rest, self.tcx);
-                self.any_replacement = true;
-            } else {
-                break;
-            }
+            *place = Place::from(target.local);
+            self.any_replacement = true;
         }
 
         // Simplify eventual projections left inside `debuginfo`.
@@ -414,9 +409,7 @@ impl<'tcx> MutVisitor<'tcx> for Replacer<'tcx> {
 
     fn visit_place(&mut self, place: &mut Place<'tcx>, ctxt: PlaceContext, loc: Location) {
         loop {
-            if place.projection.first() != Some(&PlaceElem::Deref) {
-                return;
-            }
+            let Some((&PlaceElem::Deref, rest)) = place.projection.split_first() else { return };
 
             let Value::Pointer(target, _) = self.targets[place.local] else { return };
 
@@ -432,7 +425,7 @@ impl<'tcx> MutVisitor<'tcx> for Replacer<'tcx> {
                 return;
             }
 
-            *place = target.project_deeper(&place.projection[1..], self.tcx);
+            *place = target.project_deeper(rest, self.tcx);
             self.any_replacement = true;
         }
     }