diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index deb2d6ac630ac..16832f68c9855 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -783,6 +783,11 @@ rustc_queries! { } query upstream_monomorphizations_for(_: DefId) -> Option<&'tcx FxHashMap, CrateNum>> {} + + query upstream_drop_glue_for(substs: SubstsRef<'tcx>) -> Option { + desc { "available upstream drop-glue for `{:?}`", substs } + no_force + } } Other { diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs index c4770184612cb..142654a03a1d6 100644 --- a/src/librustc/ty/instance.rs +++ b/src/librustc/ty/instance.rs @@ -4,7 +4,7 @@ use crate::traits; use crate::ty::print::{FmtPrinter, Printer}; use crate::ty::{self, SubstsRef, Ty, TyCtxt, TypeFoldable}; use rustc_hir::def::Namespace; -use rustc_hir::def_id::DefId; +use rustc_hir::def_id::{CrateNum, DefId}; use rustc_macros::HashStable; use rustc_target::spec::abi::Abi; @@ -91,6 +91,38 @@ impl<'tcx> Instance<'tcx> { let ty = tcx.type_of(self.def.def_id()); tcx.subst_and_normalize_erasing_regions(self.substs, param_env, &ty) } + + pub fn upstream_monomorphization(&self, tcx: TyCtxt<'tcx>) -> Option { + // If we are not in share generics mode, we don't link to upstream + // monomorphizations but always instantiate our own internal versions + // instead. + if !tcx.sess.opts.share_generics() { + return None; + } + + // If this instance has non-erasable parameters, it cannot be a shared + // monomorphization. Non-generic instances are already handled above + // by `is_reachable_non_generic()`. + if self.substs.non_erasable_generics().next().is_none() { + return None; + } + + if self.def_id().is_local() { + return None; + } + + match self.def { + InstanceDef::Item(def_id) => { + tcx + .upstream_monomorphizations_for(def_id) + .and_then(|monos| monos.get(&self.substs).cloned()) + } + InstanceDef::DropGlue(_, Some(_)) => { + tcx.upstream_drop_glue_for(self.substs) + } + _ => None, + } + } } impl<'tcx> InstanceDef<'tcx> { diff --git a/src/librustc/ty/query/keys.rs b/src/librustc/ty/query/keys.rs index cbf335ad607ef..c1c88e96f94b5 100644 --- a/src/librustc/ty/query/keys.rs +++ b/src/librustc/ty/query/keys.rs @@ -116,6 +116,15 @@ impl Key for (DefId, SimplifiedType) { } } +impl<'tcx> Key for SubstsRef<'tcx> { + fn query_crate(&self) -> CrateNum { + LOCAL_CRATE + } + fn default_span(&self, _: TyCtxt<'_>) -> Span { + DUMMY_SP + } +} + impl<'tcx> Key for (DefId, SubstsRef<'tcx>) { fn query_crate(&self) -> CrateNum { self.0.krate diff --git a/src/librustc_codegen_llvm/callee.rs b/src/librustc_codegen_llvm/callee.rs index 78dd6fc8ffe75..04d92142266ee 100644 --- a/src/librustc_codegen_llvm/callee.rs +++ b/src/librustc_codegen_llvm/callee.rs @@ -130,12 +130,7 @@ pub fn get_fn(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'tcx>) -> &'ll Value } else { // This is a monomorphization of a generic function // defined in an upstream crate. - if cx - .tcx - .upstream_monomorphizations_for(instance_def_id) - .map(|set| set.contains_key(instance.substs)) - .unwrap_or(false) - { + if instance.upstream_monomorphization(tcx).is_some() { // This is instantiated in another crate. It cannot // be `hidden`. } else { diff --git a/src/librustc_codegen_ssa/back/symbol_export.rs b/src/librustc_codegen_ssa/back/symbol_export.rs index 03b4fa82316e6..4bdfd7356a3ef 100644 --- a/src/librustc_codegen_ssa/back/symbol_export.rs +++ b/src/librustc_codegen_ssa/back/symbol_export.rs @@ -321,6 +321,17 @@ fn upstream_monomorphizations_for_provider( tcx.upstream_monomorphizations(LOCAL_CRATE).get(&def_id) } +fn upstream_drop_glue_for_provider<'tcx>( + tcx: TyCtxt<'tcx>, + substs: SubstsRef<'tcx>, +) -> Option { + if let Some(def_id) = tcx.lang_items().drop_in_place_fn() { + tcx.upstream_monomorphizations(LOCAL_CRATE).get(&def_id).and_then(|monos| monos.get(&substs).cloned()) + } else { + None + } +} + fn is_unreachable_local_definition_provider(tcx: TyCtxt<'_>, def_id: DefId) -> bool { if let Some(hir_id) = tcx.hir().as_local_hir_id(def_id) { !tcx.reachable_set(LOCAL_CRATE).contains(&hir_id) @@ -335,6 +346,7 @@ pub fn provide(providers: &mut Providers<'_>) { providers.exported_symbols = exported_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; } pub fn provide_extern(providers: &mut Providers<'_>) { diff --git a/src/librustc_codegen_utils/symbol_names.rs b/src/librustc_codegen_utils/symbol_names.rs index 96a74f96fcf60..af4eff8baf4e8 100644 --- a/src/librustc_codegen_utils/symbol_names.rs +++ b/src/librustc_codegen_utils/symbol_names.rs @@ -129,26 +129,8 @@ fn symbol_name_provider(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> ty::Symb // // For generics we might find re-usable upstream instances. For anything // else we rely on their being a local copy available. - if is_generic(instance.substs) { - let def_id = instance.def_id(); - - if !def_id.is_local() && tcx.sess.opts.share_generics() { - // If we are re-using a monomorphization from another crate, - // we have to compute the symbol hash accordingly. - let upstream_monomorphizations = tcx.upstream_monomorphizations_for(def_id); - - upstream_monomorphizations - .and_then(|monos| monos.get(&instance.substs).cloned()) - // If there is no instance available upstream, there'll be - // one in the current crate. - .unwrap_or(LOCAL_CRATE) - } else { - // For generic functions defined in the current crate, there - // can be no upstream instances. Also, if we don't share - // generics, we'll instantiate a local copy too. - LOCAL_CRATE - } + instance.upstream_monomorphization(tcx).unwrap_or(LOCAL_CRATE) } else { // For non-generic things that need to avoid naming conflicts, we // always instantiate a copy in the local crate. diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index 91e685babbcdd..8c98d4d58fcc0 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -737,8 +737,8 @@ fn should_monomorphize_locally<'tcx>(tcx: TyCtxt<'tcx>, instance: &Instance<'tcx return true; } - if tcx.is_reachable_non_generic(def_id) - || is_available_upstream_generic(tcx, def_id, instance.substs) + if tcx.is_reachable_non_generic(def_id) || + instance.upstream_monomorphization(tcx).is_some() { // We can link to the item in question, no instance needed // in this crate. @@ -750,34 +750,6 @@ fn should_monomorphize_locally<'tcx>(tcx: TyCtxt<'tcx>, instance: &Instance<'tcx } return true; - - fn is_available_upstream_generic<'tcx>( - tcx: TyCtxt<'tcx>, - def_id: DefId, - substs: SubstsRef<'tcx>, - ) -> bool { - debug_assert!(!def_id.is_local()); - - // If we are not in share generics mode, we don't link to upstream - // monomorphizations but always instantiate our own internal versions - // instead. - if !tcx.sess.opts.share_generics() { - return false; - } - - // If this instance has non-erasable parameters, it cannot be a shared - // monomorphization. Non-generic instances are already handled above - // by `is_reachable_non_generic()`. - if substs.non_erasable_generics().next().is_none() { - return false; - } - - // Take a look at the available monomorphizations listed in the metadata - // of upstream crates. - tcx.upstream_monomorphizations_for(def_id) - .map(|set| set.contains_key(substs)) - .unwrap_or(false) - } } /// For a given pair of source and target type that occur in an unsizing coercion,