about summary refs log tree commit diff
path: root/compiler/rustc_passes/src/reachable.rs
diff options
context:
space:
mode:
authorOli Scherer <git-spam-no-reply9815368754983@oli-obk.de>2024-02-26 18:03:06 +0000
committerOli Scherer <git-spam-no-reply9815368754983@oli-obk.de>2024-03-12 05:53:46 +0000
commitd3514a036dc65c1d31ee5b1b4bd58b9be1edf5af (patch)
tree95685bb9f89cc23836f86c958b346447e8fd5356 /compiler/rustc_passes/src/reachable.rs
parent92414ab25d5b9ddbee37d458e53e70ee4813d5ca (diff)
downloadrust-d3514a036dc65c1d31ee5b1b4bd58b9be1edf5af.tar.gz
rust-d3514a036dc65c1d31ee5b1b4bd58b9be1edf5af.zip
Ensure nested allocations in statics do not get deduplicated
Diffstat (limited to 'compiler/rustc_passes/src/reachable.rs')
-rw-r--r--compiler/rustc_passes/src/reachable.rs39
1 files changed, 38 insertions, 1 deletions
diff --git a/compiler/rustc_passes/src/reachable.rs b/compiler/rustc_passes/src/reachable.rs
index 9a22f5a1b63..e86c0522b3c 100644
--- a/compiler/rustc_passes/src/reachable.rs
+++ b/compiler/rustc_passes/src/reachable.rs
@@ -13,6 +13,7 @@ use rustc_hir::intravisit::{self, Visitor};
 use rustc_hir::Node;
 use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
 use rustc_middle::middle::privacy::{self, Level};
+use rustc_middle::mir::interpret::{ConstAllocation, GlobalAlloc};
 use rustc_middle::query::Providers;
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_session::config::CrateType;
@@ -197,10 +198,23 @@ impl<'tcx> ReachableContext<'tcx> {
                     // Reachable constants will be inlined into other crates
                     // unconditionally, so we need to make sure that their
                     // contents are also reachable.
-                    hir::ItemKind::Const(_, _, init) | hir::ItemKind::Static(_, _, init) => {
+                    hir::ItemKind::Const(_, _, init) => {
                         self.visit_nested_body(init);
                     }
 
+                    // Reachable statics are inlined if read from another constant or static
+                    // in other crates. Additionally anonymous nested statics may be created
+                    // when evaluating a static, so preserve those, too.
+                    hir::ItemKind::Static(_, _, init) => {
+                        // FIXME(oli-obk): remove this body walking and instead walk the evaluated initializer
+                        // to find nested items that end up in the final value instead of also marking symbols
+                        // as reachable that are only needed for evaluation.
+                        self.visit_nested_body(init);
+                        if let Ok(alloc) = self.tcx.eval_static_initializer(item.owner_id.def_id) {
+                            self.propagate_statics_from_alloc(item.owner_id.def_id, alloc);
+                        }
+                    }
+
                     // These are normal, nothing reachable about these
                     // inherently and their children are already in the
                     // worklist, as determined by the privacy pass
@@ -266,6 +280,29 @@ impl<'tcx> ReachableContext<'tcx> {
             }
         }
     }
+
+    /// Finds anonymous nested statics created for nested allocations and adds them to `reachable_symbols`.
+    fn propagate_statics_from_alloc(&mut self, root: LocalDefId, alloc: ConstAllocation<'tcx>) {
+        if !self.any_library {
+            return;
+        }
+        for (_, prov) in alloc.0.provenance().ptrs().iter() {
+            match self.tcx.global_alloc(prov.alloc_id()) {
+                GlobalAlloc::Static(def_id) => {
+                    if let Some(def_id) = def_id.as_local()
+                        && self.tcx.local_parent(def_id) == root
+                        // This is the main purpose of this function: add the def_id we find
+                        // to `reachable_symbols`.
+                        && self.reachable_symbols.insert(def_id)
+                        && let Ok(alloc) = self.tcx.eval_static_initializer(def_id)
+                    {
+                        self.propagate_statics_from_alloc(root, alloc);
+                    }
+                }
+                GlobalAlloc::Function(_) | GlobalAlloc::VTable(_, _) | GlobalAlloc::Memory(_) => {}
+            }
+        }
+    }
 }
 
 fn check_item<'tcx>(