diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index cd08c0fc30fb8..e726c0f8b5bb4 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -1794,7 +1794,10 @@ fn for_each_exported_symbols_include_dep<'tcx>( for (cnum, dep_format) in deps.iter_enumerated() { // For each dependency that we are linking to statically ... if *dep_format == Linkage::Static { - for &(symbol, info) in tcx.exported_symbols(cnum).iter() { + for &(symbol, info) in tcx.exported_non_generic_symbols(cnum).iter() { + callback(symbol, info, cnum); + } + for &(symbol, info) in tcx.exported_generic_symbols(cnum).iter() { callback(symbol, info, cnum); } } diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs index 19c005d418e89..85c4530fd651c 100644 --- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs +++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs @@ -164,7 +164,7 @@ fn is_reachable_non_generic_provider_extern(tcx: TyCtxt<'_>, def_id: DefId) -> b tcx.reachable_non_generics(def_id.krate).contains_key(&def_id) } -fn exported_symbols_provider_local<'tcx>( +fn exported_non_generic_symbols_provider_local<'tcx>( tcx: TyCtxt<'tcx>, _: LocalCrate, ) -> &'tcx [(ExportedSymbol<'tcx>, SymbolExportInfo)] { @@ -296,6 +296,22 @@ fn exported_symbols_provider_local<'tcx>( )); } + // Sort so we get a stable incr. comp. hash. + symbols.sort_by_cached_key(|s| s.0.symbol_name_for_local_instance(tcx)); + + tcx.arena.alloc_from_iter(symbols) +} + +fn exported_generic_symbols_provider_local<'tcx>( + tcx: TyCtxt<'tcx>, + _: LocalCrate, +) -> &'tcx [(ExportedSymbol<'tcx>, SymbolExportInfo)] { + if !tcx.sess.opts.output_types.should_codegen() && !tcx.is_sdylib_interface_build() { + return &[]; + } + + let mut symbols: Vec<_> = vec![]; + if tcx.local_crate_exports_generics() { use rustc_middle::mir::mono::{Linkage, MonoItem, Visibility}; use rustc_middle::ty::InstanceKind; @@ -458,7 +474,7 @@ fn upstream_monomorphizations_provider( 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_symbols(cnum).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) => { @@ -480,10 +496,7 @@ fn upstream_monomorphizations_provider( ExportedSymbol::AsyncDropGlue(def_id, ty) => (def_id, tcx.mk_args(&[ty.into()])), ExportedSymbol::NonGeneric(..) | ExportedSymbol::ThreadLocalShim(..) - | ExportedSymbol::NoDefId(..) => { - // These are no monomorphizations - continue; - } + | ExportedSymbol::NoDefId(..) => unreachable!("{exported_symbol:?}"), }; let args_map = instances.entry(def_id).or_default(); @@ -538,7 +551,8 @@ fn is_unreachable_local_definition_provider(tcx: TyCtxt<'_>, def_id: LocalDefId) pub(crate) fn provide(providers: &mut Providers) { providers.reachable_non_generics = reachable_non_generics_provider; providers.is_reachable_non_generic = is_reachable_non_generic_provider_local; - providers.exported_symbols = exported_symbols_provider_local; + providers.exported_non_generic_symbols = exported_non_generic_symbols_provider_local; + 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; diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index c3bfe4c13cdf7..8330e4f7af0c7 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -1124,8 +1124,9 @@ fn start_executing_work( let copy_symbols = |cnum| { let symbols = tcx - .exported_symbols(cnum) + .exported_non_generic_symbols(cnum) .iter() + .chain(tcx.exported_generic_symbols(cnum)) .map(|&(s, lvl)| (symbol_name_for_instance_in_crate(tcx, s, cnum), lvl)) .collect(); Arc::new(symbols) diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index d886f25247f2d..0ae750598fd20 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -1496,11 +1496,18 @@ impl<'a> CrateMetadataRef<'a> { .map(move |v| (self.local_def_id(v.0), v.1)) } - fn exported_symbols<'tcx>( + fn exported_non_generic_symbols<'tcx>( self, tcx: TyCtxt<'tcx>, ) -> &'tcx [(ExportedSymbol<'tcx>, SymbolExportInfo)] { - tcx.arena.alloc_from_iter(self.root.exported_symbols.decode((self, tcx))) + tcx.arena.alloc_from_iter(self.root.exported_non_generic_symbols.decode((self, tcx))) + } + + fn exported_generic_symbols<'tcx>( + self, + tcx: TyCtxt<'tcx>, + ) -> &'tcx [(ExportedSymbol<'tcx>, SymbolExportInfo)] { + tcx.arena.alloc_from_iter(self.root.exported_generic_symbols.decode((self, tcx))) } fn get_macro(self, id: DefIndex, sess: &Session) -> ast::MacroDef { diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 375928c22459f..6943d4198df43 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -358,7 +358,7 @@ provide! { tcx, def_id, other, cdata, specialization_enabled_in => { cdata.root.specialization_enabled_in } reachable_non_generics => { let reachable_non_generics = tcx - .exported_symbols(cdata.cnum) + .exported_non_generic_symbols(cdata.cnum) .iter() .filter_map(|&(exported_symbol, export_info)| { if let ExportedSymbol::NonGeneric(def_id) = exported_symbol { @@ -408,15 +408,8 @@ provide! { tcx, def_id, other, cdata, exportable_items => { tcx.arena.alloc_from_iter(cdata.get_exportable_items()) } stable_order_of_exportable_impls => { tcx.arena.alloc(cdata.get_stable_order_of_exportable_impls().collect()) } - exported_symbols => { - let syms = cdata.exported_symbols(tcx); - - // FIXME rust-lang/rust#64319, rust-lang/rust#64872: We want - // to block export of generics from dylibs, but we must fix - // rust-lang/rust#65890 before we can do that robustly. - - syms - } + exported_non_generic_symbols => { cdata.exported_non_generic_symbols(tcx) } + exported_generic_symbols => { cdata.exported_generic_symbols(tcx) } crate_extern_paths => { cdata.source().paths().cloned().collect() } expn_that_defined => { cdata.get_expn_that_defined(def_id.index, tcx.sess) } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index ed3c18a02a692..eb2090b43302c 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -677,9 +677,13 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { stat!("exportable-items", || self.encode_stable_order_of_exportable_impls()); // Encode exported symbols info. This is prefetched in `encode_metadata`. - let exported_symbols = stat!("exported-symbols", || { - self.encode_exported_symbols(tcx.exported_symbols(LOCAL_CRATE)) - }); + let (exported_non_generic_symbols, exported_generic_symbols) = + stat!("exported-symbols", || { + ( + self.encode_exported_symbols(tcx.exported_non_generic_symbols(LOCAL_CRATE)), + self.encode_exported_symbols(tcx.exported_generic_symbols(LOCAL_CRATE)), + ) + }); // Encode the hygiene data. // IMPORTANT: this *must* be the last thing that we encode (other than `SourceMap`). The @@ -745,7 +749,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { incoherent_impls, exportable_items, stable_order_of_exportable_impls, - exported_symbols, + exported_non_generic_symbols, + exported_generic_symbols, interpret_alloc_index, tables, syntax_contexts, @@ -2356,7 +2361,13 @@ pub fn encode_metadata(tcx: TyCtxt<'_>, path: &Path, ref_path: Option<&Path>) { // Prefetch some queries used by metadata encoding. // This is not necessary for correctness, but is only done for performance reasons. // It can be removed if it turns out to cause trouble or be detrimental to performance. - join(|| prefetch_mir(tcx), || tcx.exported_symbols(LOCAL_CRATE)); + join( + || prefetch_mir(tcx), + || { + let _ = tcx.exported_non_generic_symbols(LOCAL_CRATE); + let _ = tcx.exported_generic_symbols(LOCAL_CRATE); + }, + ); } with_encode_metadata_header(tcx, path, |ecx| { diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 077835283e968..a962a787a4287 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -282,7 +282,8 @@ pub(crate) struct CrateRoot { exportable_items: LazyArray, stable_order_of_exportable_impls: LazyArray<(DefIndex, usize)>, - exported_symbols: LazyArray<(ExportedSymbol<'static>, SymbolExportInfo)>, + exported_non_generic_symbols: LazyArray<(ExportedSymbol<'static>, SymbolExportInfo)>, + exported_generic_symbols: LazyArray<(ExportedSymbol<'static>, SymbolExportInfo)>, syntax_contexts: SyntaxContextTable, expn_data: ExpnDataTable, diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 3668f4e12f5d9..0b2610846b6d3 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -2312,13 +2312,32 @@ rustc_queries! { separate_provide_extern } - /// The list of symbols exported from the given crate. + /// The list of non-generic symbols exported from the given crate. + /// + /// This is separate from exported_generic_symbols to avoid having + /// to deserialize all non-generic symbols too for upstream crates + /// in the upstream_monomorphizations query. + /// + /// - All names contained in `exported_non_generic_symbols(cnum)` are + /// guaranteed to correspond to a publicly visible symbol in `cnum` + /// machine code. + /// - The `exported_non_generic_symbols` and `exported_generic_symbols` + /// sets of different crates do not intersect. + query exported_non_generic_symbols(cnum: CrateNum) -> &'tcx [(ExportedSymbol<'tcx>, SymbolExportInfo)] { + desc { "collecting exported non-generic symbols for crate `{}`", cnum} + cache_on_disk_if { *cnum == LOCAL_CRATE } + separate_provide_extern + } + + /// The list of generic symbols exported from the given crate. /// - /// - All names contained in `exported_symbols(cnum)` are guaranteed to - /// correspond to a publicly visible symbol in `cnum` machine code. - /// - The `exported_symbols` sets of different crates do not intersect. - query exported_symbols(cnum: CrateNum) -> &'tcx [(ExportedSymbol<'tcx>, SymbolExportInfo)] { - desc { "collecting exported symbols for crate `{}`", cnum} + /// - All names contained in `exported_generic_symbols(cnum)` are + /// guaranteed to correspond to a publicly visible symbol in `cnum` + /// machine code. + /// - The `exported_non_generic_symbols` and `exported_generic_symbols` + /// sets of different crates do not intersect. + query exported_generic_symbols(cnum: CrateNum) -> &'tcx [(ExportedSymbol<'tcx>, SymbolExportInfo)] { + desc { "collecting exported generic symbols for crate `{}`", cnum} cache_on_disk_if { *cnum == LOCAL_CRATE } separate_provide_extern } diff --git a/src/tools/miri/src/bin/miri.rs b/src/tools/miri/src/bin/miri.rs index d4ba7fbd6a479..27360387ebf85 100644 --- a/src/tools/miri/src/bin/miri.rs +++ b/src/tools/miri/src/bin/miri.rs @@ -85,7 +85,7 @@ fn entry_fn(tcx: TyCtxt<'_>) -> (DefId, MiriEntryFnType) { return (def_id, MiriEntryFnType::Rustc(entry_type)); } // Look for a symbol in the local crate named `miri_start`, and treat that as the entry point. - let sym = tcx.exported_symbols(LOCAL_CRATE).iter().find_map(|(sym, _)| { + let sym = tcx.exported_non_generic_symbols(LOCAL_CRATE).iter().find_map(|(sym, _)| { if sym.symbol_name_for_local_instance(tcx).name == "miri_start" { Some(sym) } else { None } }); if let Some(ExportedSymbol::NonGeneric(id)) = sym { @@ -249,10 +249,10 @@ impl rustc_driver::Callbacks for MiriBeRustCompilerCalls { // Queries overridden here affect the data stored in `rmeta` files of dependencies, // which will be used later in non-`MIRI_BE_RUSTC` mode. config.override_queries = Some(|_, local_providers| { - // `exported_symbols` and `reachable_non_generics` provided by rustc always returns + // `exported_non_generic_symbols` and `reachable_non_generics` provided by rustc always returns // an empty result if `tcx.sess.opts.output_types.should_codegen()` is false. // In addition we need to add #[used] symbols to exported_symbols for `lookup_link_section`. - local_providers.exported_symbols = |tcx, LocalCrate| { + local_providers.exported_non_generic_symbols = |tcx, LocalCrate| { let reachable_set = tcx.with_stable_hashing_context(|hcx| { tcx.reachable_set(()).to_sorted(&hcx, true) }); diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs index 4edecc864dd42..b2d04378658c4 100644 --- a/src/tools/miri/src/helpers.rs +++ b/src/tools/miri/src/helpers.rs @@ -162,7 +162,7 @@ pub fn iter_exported_symbols<'tcx>( // We can ignore `_export_info` here: we are a Rust crate, and everything is exported // from a Rust crate. - for &(symbol, _export_info) in tcx.exported_symbols(cnum) { + for &(symbol, _export_info) in tcx.exported_non_generic_symbols(cnum) { if let ExportedSymbol::NonGeneric(def_id) = symbol { f(cnum, def_id)?; }