diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs index a80976fad02a4..6f7a32d234eba 100644 --- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs +++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs @@ -1,10 +1,9 @@ -use std::collections::hash_map::Entry::*; - use rustc_abi::{CanonAbi, X86Call}; use rustc_ast::expand::allocator::{ ALLOC_ERROR_HANDLER, ALLOCATOR_METHODS, NO_ALLOC_SHIM_IS_UNSTABLE, global_fn_name, }; -use rustc_data_structures::unord::UnordMap; +use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; +use rustc_hashes::Hash128; use rustc_hir::def::DefKind; use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LOCAL_CRATE, LocalDefId}; use rustc_middle::bug; @@ -384,86 +383,75 @@ fn exported_generic_symbols_provider_local<'tcx>( tcx.arena.alloc_from_iter(symbols) } -fn upstream_monomorphizations_provider( +fn upstream_monomorphizations_of_crate_provider( tcx: TyCtxt<'_>, - (): (), -) -> DefIdMap, CrateNum>> { - let cnums = tcx.crates(()); - - let mut instances: DefIdMap> = Default::default(); - + cnum: CrateNum, +) -> FxIndexSet { + use rustc_data_structures::stable_hasher::HashStable; let drop_in_place_fn_def_id = tcx.lang_items().drop_in_place_fn(); let async_drop_in_place_fn_def_id = tcx.lang_items().async_drop_in_place_fn(); - - for &cnum in cnums.iter() { - for (exported_symbol, _) in tcx.exported_generic_symbols(cnum).iter() { - let (def_id, args) = match *exported_symbol { - ExportedSymbol::Generic(def_id, args) => (def_id, args), - ExportedSymbol::DropGlue(ty) => { - if let Some(drop_in_place_fn_def_id) = drop_in_place_fn_def_id { - (drop_in_place_fn_def_id, tcx.mk_args(&[ty.into()])) - } else { - // `drop_in_place` in place does not exist, don't try - // to use it. - continue; - } - } - ExportedSymbol::AsyncDropGlueCtorShim(ty) => { - if let Some(async_drop_in_place_fn_def_id) = async_drop_in_place_fn_def_id { - (async_drop_in_place_fn_def_id, tcx.mk_args(&[ty.into()])) - } else { - continue; - } - } - ExportedSymbol::AsyncDropGlue(def_id, ty) => (def_id, tcx.mk_args(&[ty.into()])), - ExportedSymbol::NonGeneric(..) - | ExportedSymbol::ThreadLocalShim(..) - | ExportedSymbol::NoDefId(..) => unreachable!("{exported_symbol:?}"), - }; - - let args_map = instances.entry(def_id).or_default(); - - match args_map.entry(args) { - Occupied(mut e) => { - // If there are multiple monomorphizations available, - // we select one deterministically. - let other_cnum = *e.get(); - if tcx.stable_crate_id(other_cnum) > tcx.stable_crate_id(cnum) { - e.insert(cnum); - } + let mut instances = FxIndexSet::default(); + for (exported_symbol, _) in tcx.exported_generic_symbols(cnum).iter() { + let instance = match *exported_symbol { + ExportedSymbol::Generic(def_id, args) => rustc_middle::ty::Instance { + args, + def: rustc_middle::ty::InstanceKind::Item(def_id), + }, + ExportedSymbol::DropGlue(ty) => { + let Some(drop_in_place_fn_def_id) = drop_in_place_fn_def_id else { + // `drop_in_place` in place does not exist, don't try + // to use it. + continue; + }; + let args = tcx.mk_args(&[ty.clone().into()]); + rustc_middle::ty::Instance { + args, + def: rustc_middle::ty::InstanceKind::DropGlue( + drop_in_place_fn_def_id, + Some(ty), + ), } - Vacant(e) => { - e.insert(cnum); + } + ExportedSymbol::AsyncDropGlueCtorShim(ty) => { + let Some(drop_in_place) = async_drop_in_place_fn_def_id else { + continue; + }; + let args = tcx.mk_args(&[ty.clone().into()]); + rustc_middle::ty::Instance { + args, + def: rustc_middle::ty::InstanceKind::AsyncDropGlueCtorShim(drop_in_place, ty), } } - } - } + ExportedSymbol::AsyncDropGlue(def_id, ty) => rustc_middle::ty::Instance { + args: tcx.mk_args(&[ty.clone().into()]), + def: rustc_middle::ty::InstanceKind::AsyncDropGlue(def_id, ty), + }, + ExportedSymbol::NonGeneric(..) + | ExportedSymbol::ThreadLocalShim(..) + | ExportedSymbol::NoDefId(..) => unreachable!("{exported_symbol:?}"), + }; + tcx.with_stable_hashing_context(|mut tcx| { + let mut hasher = rustc_data_structures::stable_hasher::StableHasher::new(); + instance.hash_stable(&mut tcx, &mut hasher); + instances.insert(hasher.finish()); + }); + } instances } -fn upstream_monomorphizations_for_provider( - tcx: TyCtxt<'_>, - def_id: DefId, -) -> Option<&UnordMap, CrateNum>> { - assert!(!def_id.is_local()); - tcx.upstream_monomorphizations(()).get(&def_id) -} +fn upstream_monomorphizations_provider(tcx: TyCtxt<'_>, _: ()) -> FxIndexMap { + let cnums = tcx.crates(()); + let mut instances: FxIndexMap = Default::default(); -fn upstream_drop_glue_for_provider<'tcx>( - tcx: TyCtxt<'tcx>, - args: GenericArgsRef<'tcx>, -) -> Option { - let def_id = tcx.lang_items().drop_in_place_fn()?; - tcx.upstream_monomorphizations_for(def_id)?.get(&args).cloned() -} + for cnum in cnums.iter() { + let hashes = tcx.upstream_monomorphizations_of_crate(*cnum); + for hash in hashes { + instances.entry(*hash).or_insert(*cnum); + } + } -fn upstream_async_drop_glue_for_provider<'tcx>( - tcx: TyCtxt<'tcx>, - args: GenericArgsRef<'tcx>, -) -> Option { - let def_id = tcx.lang_items().async_drop_in_place_fn()?; - tcx.upstream_monomorphizations_for(def_id)?.get(&args).cloned() + instances } fn is_unreachable_local_definition_provider(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { @@ -477,12 +465,9 @@ pub(crate) fn provide(providers: &mut Providers) { providers.exported_generic_symbols = exported_generic_symbols_provider_local; providers.upstream_monomorphizations = upstream_monomorphizations_provider; providers.is_unreachable_local_definition = is_unreachable_local_definition_provider; - providers.upstream_drop_glue_for = upstream_drop_glue_for_provider; - providers.upstream_async_drop_glue_for = upstream_async_drop_glue_for_provider; providers.wasm_import_module_map = wasm_import_module_map; providers.extern_queries.is_reachable_non_generic = is_reachable_non_generic_provider_extern; - providers.extern_queries.upstream_monomorphizations_for = - upstream_monomorphizations_for_provider; + providers.upstream_monomorphizations_of_crate = upstream_monomorphizations_of_crate_provider; } pub(crate) fn allocator_shim_symbols( diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 15c84a5b01fb2..466f7303e15fe 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -76,6 +76,7 @@ use rustc_data_structures::steal::Steal; use rustc_data_structures::svh::Svh; use rustc_data_structures::unord::{UnordMap, UnordSet}; use rustc_errors::ErrorGuaranteed; +use rustc_hashes::Hash128; use rustc_hir::attrs::StrippedCfgItem; use rustc_hir::def::{DefKind, DocLinkResMap}; use rustc_hir::def_id::{ @@ -1960,65 +1961,15 @@ rustc_queries! { /// crate. Instead use the narrower `upstream_monomorphizations_for`, /// `upstream_drop_glue_for`, `upstream_async_drop_glue_for`, or, /// even better, `Instance::upstream_monomorphization()`. - query upstream_monomorphizations(_: ()) -> &'tcx DefIdMap, CrateNum>> { + query upstream_monomorphizations(_: ()) -> &'tcx FxIndexMap { arena_cache desc { "collecting available upstream monomorphizations" } } - /// Returns the set of upstream monomorphizations available for the - /// generic function identified by the given `def_id`. The query makes - /// sure to make a stable selection if the same monomorphization is - /// available in multiple upstream crates. - /// - /// You likely want to call `Instance::upstream_monomorphization()` - /// instead of invoking this query directly. - query upstream_monomorphizations_for(def_id: DefId) - -> Option<&'tcx UnordMap, CrateNum>> - { - desc { |tcx| - "collecting available upstream monomorphizations for `{}`", - tcx.def_path_str(def_id), - } - separate_provide_extern - } - - /// Returns the upstream crate that exports drop-glue for the given - /// type (`args` is expected to be a single-item list containing the - /// type one wants drop-glue for). - /// - /// This is a subset of `upstream_monomorphizations_for` in order to - /// increase dep-tracking granularity. Otherwise adding or removing any - /// type with drop-glue in any upstream crate would invalidate all - /// functions calling drop-glue of an upstream type. - /// - /// You likely want to call `Instance::upstream_monomorphization()` - /// instead of invoking this query directly. - /// - /// NOTE: This query could easily be extended to also support other - /// common functions that have are large set of monomorphizations - /// (like `Clone::clone` for example). - query upstream_drop_glue_for(args: GenericArgsRef<'tcx>) -> Option { - desc { "available upstream drop-glue for `{:?}`", args } - } - - /// Returns the upstream crate that exports async-drop-glue for - /// the given type (`args` is expected to be a single-item list - /// containing the type one wants async-drop-glue for). - /// - /// This is a subset of `upstream_monomorphizations_for` in order - /// to increase dep-tracking granularity. Otherwise adding or - /// removing any type with async-drop-glue in any upstream crate - /// would invalidate all functions calling async-drop-glue of an - /// upstream type. - /// - /// You likely want to call `Instance::upstream_monomorphization()` - /// instead of invoking this query directly. - /// - /// NOTE: This query could easily be extended to also support other - /// common functions that have are large set of monomorphizations - /// (like `Clone::clone` for example). - query upstream_async_drop_glue_for(args: GenericArgsRef<'tcx>) -> Option { - desc { "available upstream async-drop-glue for `{:?}`", args } + query upstream_monomorphizations_of_crate(_: CrateNum) -> &'tcx FxIndexSet { + arena_cache + cache_on_disk_if { true } + desc { "collecting available upstream monomorphizations for crate" } } /// Returns a list of all `extern` blocks of a crate. diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index c27d47fcc0d8d..819aa61be971b 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -2,7 +2,9 @@ use std::assert_matches::assert_matches; use std::fmt; use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_errors::ErrorGuaranteed; +use rustc_hashes::Hash128; use rustc_hir as hir; use rustc_hir::def::{CtorKind, DefKind, Namespace}; use rustc_hir::def_id::{CrateNum, DefId}; @@ -224,18 +226,25 @@ impl<'tcx> Instance<'tcx> { return None; } - match self.def { - InstanceKind::Item(def) => tcx - .upstream_monomorphizations_for(def) - .and_then(|monos| monos.get(&self.args).cloned()), - InstanceKind::DropGlue(_, Some(_)) => tcx.upstream_drop_glue_for(self.args), + let defining_crates = match self.def { + InstanceKind::Item(_) + | InstanceKind::DropGlue(_, Some(_)) + | InstanceKind::AsyncDropGlueCtorShim(_, _) => { + let hash: Hash128 = tcx.with_stable_hashing_context(|mut hcx| { + let mut hasher = StableHasher::new(); + self.hash_stable(&mut hcx, &mut hasher); + hasher.finish() + }); + tcx.upstream_monomorphizations(()).get(&hash) + } + InstanceKind::AsyncDropGlue(_, _) => None, InstanceKind::FutureDropPollShim(_, _, _) => None, - InstanceKind::AsyncDropGlueCtorShim(_, _) => { - tcx.upstream_async_drop_glue_for(self.args) - } + _ => None, - } + }?; + + Some(*defining_crates) } }