about summary refs log tree commit diff
diff options
context:
space:
mode:
authorCamille Gillot <gillot.camille@gmail.com>2025-08-07 02:22:24 +0000
committerCamille Gillot <gillot.camille@gmail.com>2025-08-07 23:34:15 +0000
commitebd60b9b8fb1dd1aaac5e1b705d1852f7bc6869b (patch)
tree81fb7188ca8023f0c151ad9c2fe8f24c966ec82d
parent8a87857320207f32f42270b25ec87f8d1bcfd903 (diff)
downloadrust-ebd60b9b8fb1dd1aaac5e1b705d1852f7bc6869b.tar.gz
rust-ebd60b9b8fb1dd1aaac5e1b705d1852f7bc6869b.zip
Do not flatten derefs with ProjectionElem::Index.
-rw-r--r--compiler/rustc_mir_transform/src/gvn.rs15
-rw-r--r--tests/mir-opt/gvn.dereference_indexing.GVN.panic-abort.diff3
-rw-r--r--tests/mir-opt/gvn.dereference_indexing.GVN.panic-unwind.diff3
3 files changed, 15 insertions, 6 deletions
diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs
index dc99b67a1e8..952da2cdf72 100644
--- a/compiler/rustc_mir_transform/src/gvn.rs
+++ b/compiler/rustc_mir_transform/src/gvn.rs
@@ -756,7 +756,13 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
                 && let Some(v) = self.simplify_place_value(&mut pointee, location)
             {
                 value = v;
-                place_ref = pointee.project_deeper(&place.projection[index..], self.tcx).as_ref();
+                // `pointee` holds a `Place`, so `ProjectionElem::Index` holds a `Local`.
+                // That local is SSA, but we otherwise have no guarantee on that local's value at
+                // the current location compared to its value where `pointee` was borrowed.
+                if pointee.projection.iter().all(|elem| !matches!(elem, ProjectionElem::Index(_))) {
+                    place_ref =
+                        pointee.project_deeper(&place.projection[index..], self.tcx).as_ref();
+                }
             }
             if let Some(local) = self.try_as_local(value, location) {
                 // Both `local` and `Place { local: place.local, projection: projection[..index] }`
@@ -774,7 +780,12 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
             && let Some(v) = self.simplify_place_value(&mut pointee, location)
         {
             value = v;
-            place_ref = pointee.project_deeper(&[], self.tcx).as_ref();
+            // `pointee` holds a `Place`, so `ProjectionElem::Index` holds a `Local`.
+            // That local is SSA, but we otherwise have no guarantee on that local's value at
+            // the current location compared to its value where `pointee` was borrowed.
+            if pointee.projection.iter().all(|elem| !matches!(elem, ProjectionElem::Index(_))) {
+                place_ref = pointee.project_deeper(&[], self.tcx).as_ref();
+            }
         }
         if let Some(new_local) = self.try_as_local(value, location) {
             place_ref = PlaceRef { local: new_local, projection: &[] };
diff --git a/tests/mir-opt/gvn.dereference_indexing.GVN.panic-abort.diff b/tests/mir-opt/gvn.dereference_indexing.GVN.panic-abort.diff
index 1a07638cbaf..9bdcc2f108a 100644
--- a/tests/mir-opt/gvn.dereference_indexing.GVN.panic-abort.diff
+++ b/tests/mir-opt/gvn.dereference_indexing.GVN.panic-abort.diff
@@ -43,8 +43,7 @@
 +         nop;
           StorageLive(_8);
           StorageLive(_9);
--         _9 = copy (*_3);
-+         _9 = copy _1[_4];
+          _9 = copy (*_3);
           _8 = opaque::<u8>(move _9) -> [return: bb2, unwind unreachable];
       }
   
diff --git a/tests/mir-opt/gvn.dereference_indexing.GVN.panic-unwind.diff b/tests/mir-opt/gvn.dereference_indexing.GVN.panic-unwind.diff
index 6e67b66e783..f38bc51adc4 100644
--- a/tests/mir-opt/gvn.dereference_indexing.GVN.panic-unwind.diff
+++ b/tests/mir-opt/gvn.dereference_indexing.GVN.panic-unwind.diff
@@ -43,8 +43,7 @@
 +         nop;
           StorageLive(_8);
           StorageLive(_9);
--         _9 = copy (*_3);
-+         _9 = copy _1[_4];
+          _9 = copy (*_3);
           _8 = opaque::<u8>(move _9) -> [return: bb2, unwind continue];
       }