diff --git a/compiler/rustc_middle/src/query/plumbing.rs b/compiler/rustc_middle/src/query/plumbing.rs index 3337f7ceee7d7..b66e0d066cbb7 100644 --- a/compiler/rustc_middle/src/query/plumbing.rs +++ b/compiler/rustc_middle/src/query/plumbing.rs @@ -666,3 +666,11 @@ pub(crate) fn default_extern_query(name: &str, key: &dyn std::fmt::Debug) -> ! { perhaps the `{name}` query was never assigned a provider function", ) } + +pub(crate) fn reachable_symbols<'tcx>( + tcx: TyCtxt<'tcx>, + crate_num: CrateNum, +) -> &'tcx [DefId] { + // Call the implementation defined in `context.rs` + tcx.reachable_symbols(crate_num) +} diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 24f10b4fbe784..ba5c80c35d24d 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1793,6 +1793,47 @@ impl<'tcx> TyCtxtAt<'tcx> { } } +impl<'tcx> TyCtxt<'tcx> { + /// Returns all reachable symbols (DefIds) for the given crate. + pub fn reachable_symbols(self, crate_num: CrateNum) -> &'tcx [DefId] { + // Vector to store the DefIds of reachable items + let mut reachable_def_ids = Vec::new(); + let mut visited = FxHashSet::default(); + + // Recursive function to traverse reachable items + fn collect_reachable_items<'tcx>( + tcx: TyCtxt<'tcx>, + module_def_id: DefId, + reachable_def_ids: &mut Vec, + visited: &mut FxHashSet, + ) { + // Avoid revisiting modules + if !visited.insert(module_def_id) { + return; + } + + // Add the current module to the list + reachable_def_ids.push(module_def_id); + + // Fetch module children that are not reexports + if let Some(children) = tcx.module_children_non_reexports(module_def_id) { + for child in children { + // Recursively collect items for each child + collect_reachable_items(tcx, child.def_id, reachable_def_ids, visited); + } + } + } + + // Start traversal from the root module of the given crate + let root_def_id = self.crate_root(crate_num); + collect_reachable_items(self, root_def_id, &mut reachable_def_ids, &mut visited); + + // Cache the results using the query system + self.alloc_slice(reachable_def_ids) + } +} + + impl<'tcx> TyCtxt<'tcx> { /// `tcx`-dependent operations performed for every created definition. pub fn create_def( diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index bf0ccdc0f1013..db140b2a7ce58 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -2235,3 +2235,10 @@ mod size_asserts { static_assert_size!(WithCachedTypeInfo>, 48); // tidy-alphabetical-end } + +define_queries! { + /// Query to return all reachable symbols (DefIds) for a given crate. + query reachable_symbols(key: CrateNum) -> &'tcx [DefId] { + desc { |tcx| format!("computing reachable symbols for crate `{}`", key) } + } +} \ No newline at end of file