about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock1
-rw-r--r--compiler/rustc_passes/Cargo.toml1
-rw-r--r--compiler/rustc_passes/src/reachable.rs35
-rw-r--r--compiler/rustc_privacy/src/lib.rs4
-rw-r--r--tests/ui/cross-crate/auxiliary/static_init_aux.rs21
-rw-r--r--tests/ui/cross-crate/static-init.rs4
6 files changed, 60 insertions, 6 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 16aed3dc49c..94e2570ebaf 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -4400,6 +4400,7 @@ dependencies = [
  "rustc_lexer",
  "rustc_macros",
  "rustc_middle",
+ "rustc_privacy",
  "rustc_session",
  "rustc_span",
  "rustc_target",
diff --git a/compiler/rustc_passes/Cargo.toml b/compiler/rustc_passes/Cargo.toml
index 6abfa08c530..b45a8dae277 100644
--- a/compiler/rustc_passes/Cargo.toml
+++ b/compiler/rustc_passes/Cargo.toml
@@ -18,6 +18,7 @@ rustc_index = { path = "../rustc_index" }
 rustc_lexer = { path = "../rustc_lexer" }
 rustc_macros = { path = "../rustc_macros" }
 rustc_middle = { path = "../rustc_middle" }
+rustc_privacy = { path = "../rustc_privacy" }
 rustc_session = { path = "../rustc_session" }
 rustc_span = { path = "../rustc_span" }
 rustc_target = { path = "../rustc_target" }
diff --git a/compiler/rustc_passes/src/reachable.rs b/compiler/rustc_passes/src/reachable.rs
index 0dd3185fc83..718c2345397 100644
--- a/compiler/rustc_passes/src/reachable.rs
+++ b/compiler/rustc_passes/src/reachable.rs
@@ -16,7 +16,8 @@ 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_middle::ty::{self, ExistentialTraitRef, TyCtxt};
+use rustc_privacy::DefIdVisitor;
 use rustc_session::config::CrateType;
 use rustc_target::spec::abi::Abi;
 
@@ -272,13 +273,22 @@ impl<'tcx> ReachableContext<'tcx> {
                     self.propagate_item(Res::Def(self.tcx.def_kind(def_id), def_id))
                 }
                 GlobalAlloc::Function(instance) => {
+                    // Manually visit to actually see the instance's `DefId`. Type visitors won't see it
                     self.propagate_item(Res::Def(
                         self.tcx.def_kind(instance.def_id()),
                         instance.def_id(),
-                    ))
-                    // TODO: walk generic args
+                    ));
+                    self.visit(instance.args);
+                }
+                GlobalAlloc::VTable(ty, trait_ref) => {
+                    self.visit(ty);
+                    // Manually visit to actually see the trait's `DefId`. Type visitors won't see it
+                    if let Some(trait_ref) = trait_ref {
+                        let ExistentialTraitRef { def_id, args } = trait_ref.skip_binder();
+                        self.visit_def_id(def_id, "", &"");
+                        self.visit(args);
+                    }
                 }
-                GlobalAlloc::VTable(ty, trait_ref) => todo!("{ty:?}, {trait_ref:?}"),
                 GlobalAlloc::Memory(alloc) => self.propagate_from_alloc(alloc),
             }
         }
@@ -318,6 +328,23 @@ impl<'tcx> ReachableContext<'tcx> {
     }
 }
 
+impl<'tcx> DefIdVisitor<'tcx> for ReachableContext<'tcx> {
+    type Result = ();
+
+    fn tcx(&self) -> TyCtxt<'tcx> {
+        self.tcx
+    }
+
+    fn visit_def_id(
+        &mut self,
+        def_id: DefId,
+        _kind: &str,
+        _descr: &dyn std::fmt::Display,
+    ) -> Self::Result {
+        self.propagate_item(Res::Def(self.tcx.def_kind(def_id), def_id))
+    }
+}
+
 fn check_item<'tcx>(
     tcx: TyCtxt<'tcx>,
     id: hir::ItemId,
diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs
index 9f8cb8fcb41..073982ca5c3 100644
--- a/compiler/rustc_privacy/src/lib.rs
+++ b/compiler/rustc_privacy/src/lib.rs
@@ -67,7 +67,7 @@ impl<'tcx> fmt::Display for LazyDefPathStr<'tcx> {
 /// First, it doesn't have overridable `fn visit_trait_ref`, so we have to catch trait `DefId`s
 /// manually. Second, it doesn't visit some type components like signatures of fn types, or traits
 /// in `impl Trait`, see individual comments in `DefIdVisitorSkeleton::visit_ty`.
-trait DefIdVisitor<'tcx> {
+pub trait DefIdVisitor<'tcx> {
     type Result: VisitorResult = ();
     const SHALLOW: bool = false;
     const SKIP_ASSOC_TYS: bool = false;
@@ -98,7 +98,7 @@ trait DefIdVisitor<'tcx> {
     }
 }
 
-struct DefIdVisitorSkeleton<'v, 'tcx, V: ?Sized> {
+pub struct DefIdVisitorSkeleton<'v, 'tcx, V: ?Sized> {
     def_id_visitor: &'v mut V,
     visited_opaque_tys: FxHashSet<DefId>,
     dummy: PhantomData<TyCtxt<'tcx>>,
diff --git a/tests/ui/cross-crate/auxiliary/static_init_aux.rs b/tests/ui/cross-crate/auxiliary/static_init_aux.rs
index 5e172ef3198..dca708733b9 100644
--- a/tests/ui/cross-crate/auxiliary/static_init_aux.rs
+++ b/tests/ui/cross-crate/auxiliary/static_init_aux.rs
@@ -1,6 +1,8 @@
 pub static V: &u32 = &X;
 pub static F: fn() = f;
 pub static G: fn() = G0;
+pub static H: &(dyn Fn() + Sync) = &h;
+pub static I: fn() = Helper(j).mk();
 
 static X: u32 = 42;
 static G0: fn() = g;
@@ -12,3 +14,22 @@ pub fn v() -> *const u32 {
 fn f() {}
 
 fn g() {}
+
+fn h() {}
+
+#[derive(Copy, Clone)]
+struct Helper<T: Copy>(T);
+
+impl<T: Copy + FnOnce()> Helper<T> {
+    const fn mk(self) -> fn() {
+        i::<T>
+    }
+}
+
+fn i<T: FnOnce()>() {
+    assert_eq!(std::mem::size_of::<T>(), 0);
+    // unsafe to work around the lack of a `Default` impl for function items
+    unsafe { (std::mem::transmute_copy::<(), T>(&()))() }
+}
+
+fn j() {}
diff --git a/tests/ui/cross-crate/static-init.rs b/tests/ui/cross-crate/static-init.rs
index 090ad5f810e..c4697a1d010 100644
--- a/tests/ui/cross-crate/static-init.rs
+++ b/tests/ui/cross-crate/static-init.rs
@@ -6,6 +6,8 @@ extern crate static_init_aux as aux;
 static V: &u32 = aux::V;
 static F: fn() = aux::F;
 static G: fn() = aux::G;
+static H: &(dyn Fn() + Sync) = aux::H;
+static I: fn() = aux::I;
 
 fn v() -> *const u32 {
     V
@@ -15,4 +17,6 @@ fn main() {
     assert_eq!(aux::v(), crate::v());
     F();
     G();
+    H();
+    I();
 }