diff --git a/Cargo.lock b/Cargo.lock index 22b3e8280d620..9ba8c1ca909a1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3995,6 +3995,7 @@ dependencies = [ "rustc_fs_util", "rustc_hir", "rustc_hir_pretty", + "rustc_incremental", "rustc_index", "rustc_macros", "rustc_middle", diff --git a/compiler/rustc_codegen_cranelift/src/driver/aot.rs b/compiler/rustc_codegen_cranelift/src/driver/aot.rs index 419efa9060081..6395d47694b01 100644 --- a/compiler/rustc_codegen_cranelift/src/driver/aot.rs +++ b/compiler/rustc_codegen_cranelift/src/driver/aot.rs @@ -65,6 +65,17 @@ impl OngoingCodegen { backend_config: &BackendConfig, ) -> (CodegenResults, FxIndexMap) { let mut work_products = FxIndexMap::default(); + + if let Some(path) = self.metadata.path() { + if let Some((id, product)) = + rustc_incremental::copy_cgu_workproduct_to_incr_comp_cache_dir(sess, "metadata", &[ + ("rmeta", path), + ]) + { + work_products.insert(id, product); + } + } + let mut modules = vec![]; for module_codegen in self.modules { diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index 8445d16befb3a..8dff6c8655ac9 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -520,6 +520,7 @@ pub(crate) fn start_async_codegen( fn copy_all_cgu_workproducts_to_incr_comp_cache_dir( sess: &Session, + metadata: &EncodedMetadata, compiled_modules: &CompiledModules, ) -> FxIndexMap { let mut work_products = FxIndexMap::default(); @@ -530,6 +531,14 @@ fn copy_all_cgu_workproducts_to_incr_comp_cache_dir( let _timer = sess.timer("copy_all_cgu_workproducts_to_incr_comp_cache_dir"); + if let Some(path) = metadata.path() { + if let Some((id, product)) = + copy_cgu_workproduct_to_incr_comp_cache_dir(sess, "metadata", &[("rmeta", path)]) + { + work_products.insert(id, product); + } + } + for module in compiled_modules.modules.iter().filter(|m| m.kind == ModuleKind::Regular) { let mut files = Vec::new(); if let Some(object_file_path) = &module.object { @@ -2059,8 +2068,11 @@ impl OngoingCodegen { sess.dcx().abort_if_errors(); - let work_products = - copy_all_cgu_workproducts_to_incr_comp_cache_dir(sess, &compiled_modules); + let work_products = copy_all_cgu_workproducts_to_incr_comp_cache_dir( + sess, + &self.metadata, + &compiled_modules, + ); produce_final_output_artifacts(sess, &compiled_modules, &self.output_filenames); // FIXME: time_llvm_passes support - does this use a global context or diff --git a/compiler/rustc_metadata/Cargo.toml b/compiler/rustc_metadata/Cargo.toml index 3b0151b1f9444..e9920dcb0d5d5 100644 --- a/compiler/rustc_metadata/Cargo.toml +++ b/compiler/rustc_metadata/Cargo.toml @@ -19,6 +19,7 @@ rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_fs_util = { path = "../rustc_fs_util" } rustc_hir = { path = "../rustc_hir" } rustc_hir_pretty = { path = "../rustc_hir_pretty" } +rustc_incremental = { path = "../rustc_incremental" } rustc_index = { path = "../rustc_index" } rustc_macros = { path = "../rustc_macros" } rustc_middle = { path = "../rustc_middle" } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index b5ac302c597de..a925ebf4a73a6 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1544,6 +1544,10 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let table = tcx.associated_types_for_impl_traits_in_associated_fn(def_id); record_defaulted_array!(self.tables.associated_types_for_impl_traits_in_associated_fn[def_id] <- table); } + if let DefKind::Mod = tcx.def_kind(def_id) { + record!(self.tables.doc_link_resolutions[def_id] <- tcx.doc_link_resolutions(def_id)); + record_array!(self.tables.doc_link_traits_in_scope[def_id] <- tcx.doc_link_traits_in_scope(def_id)); + } } for (def_id, impls) in &tcx.crate_inherent_impls(()).0.inherent_impls { @@ -1552,14 +1556,6 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { def_id.index })); } - - for (def_id, res_map) in &tcx.resolutions(()).doc_link_resolutions { - record!(self.tables.doc_link_resolutions[def_id.to_def_id()] <- res_map); - } - - for (def_id, traits) in &tcx.resolutions(()).doc_link_traits_in_scope { - record_array!(self.tables.doc_link_traits_in_scope[def_id.to_def_id()] <- traits); - } } #[instrument(level = "trace", skip(self))] @@ -2205,6 +2201,8 @@ fn prefetch_mir(tcx: TyCtxt<'_>) { pub struct EncodedMetadata { // The declaration order matters because `mmap` should be dropped before `_temp_dir`. mmap: Option, + // The path containing the metadata, to record as work product. + path: Option>, // We need to carry MaybeTempDir to avoid deleting the temporary // directory while accessing the Mmap. _temp_dir: Option, @@ -2216,16 +2214,21 @@ impl EncodedMetadata { let file = std::fs::File::open(&path)?; let file_metadata = file.metadata()?; if file_metadata.len() == 0 { - return Ok(Self { mmap: None, _temp_dir: None }); + return Ok(Self { mmap: None, path: None, _temp_dir: None }); } let mmap = unsafe { Some(Mmap::map(file)?) }; - Ok(Self { mmap, _temp_dir: temp_dir }) + Ok(Self { mmap, path: Some(path.into()), _temp_dir: temp_dir }) } #[inline] pub fn raw_data(&self) -> &[u8] { self.mmap.as_deref().unwrap_or_default() } + + #[inline] + pub fn path(&self) -> Option<&Path> { + self.path.as_deref() + } } impl Encodable for EncodedMetadata { @@ -2249,11 +2252,32 @@ impl Decodable for EncodedMetadata { None }; - Self { mmap, _temp_dir: None } + Self { mmap, path: None, _temp_dir: None } } } +#[instrument(level = "trace", skip(tcx))] pub fn encode_metadata(tcx: TyCtxt<'_>, path: &Path) { + let dep_node = tcx.metadata_dep_node(); + + if tcx.dep_graph.is_fully_enabled() + && let work_product_id = &rustc_middle::dep_graph::WorkProductId::from_cgu_name("metadata") + && let Some(work_product) = tcx.dep_graph.previous_work_product(work_product_id) + && tcx.try_mark_green(&dep_node) + { + let saved_path = &work_product.saved_files["rmeta"]; + let incr_comp_session_dir = tcx.sess.incr_comp_session_dir_opt().unwrap(); + let source_file = rustc_incremental::in_incr_comp_dir(&incr_comp_session_dir, saved_path); + debug!("copying preexisting metadata from {source_file:?} to {path:?}"); + match rustc_fs_util::link_or_copy(&source_file, path) { + Ok(_) => {} + Err(err) => { + tcx.dcx().emit_fatal(FailCreateFileEncoder { err }); + } + }; + return; + }; + let _prof_timer = tcx.prof.verbose_generic_activity("generate_crate_metadata"); // Since encoding metadata is not in a query, and nothing is cached, @@ -2267,6 +2291,10 @@ pub fn encode_metadata(tcx: TyCtxt<'_>, path: &Path) { join(|| prefetch_mir(tcx), || tcx.exported_symbols(LOCAL_CRATE)); } + tcx.dep_graph.with_task(dep_node, tcx, path, encode_metadata_impl, None); +} + +fn encode_metadata_impl(tcx: TyCtxt<'_>, path: &Path) { let mut encoder = opaque::FileEncoder::new(path) .unwrap_or_else(|err| tcx.dcx().emit_fatal(FailCreateFileEncoder { err })); encoder.emit_raw_bytes(METADATA_HEADER); diff --git a/compiler/rustc_middle/src/dep_graph/dep_node.rs b/compiler/rustc_middle/src/dep_graph/dep_node.rs index 87bbeb178ee19..dda41283dfcdb 100644 --- a/compiler/rustc_middle/src/dep_graph/dep_node.rs +++ b/compiler/rustc_middle/src/dep_graph/dep_node.rs @@ -140,6 +140,7 @@ rustc_query_append!(define_dep_nodes![ [] fn TraitSelect() -> (), [] fn CompileCodegenUnit() -> (), [] fn CompileMonoItem() -> (), + [] fn Metadata() -> (), ]); // WARNING: `construct` is generic and does not know that `CompileCodegenUnit` takes `Symbol`s as keys. @@ -157,6 +158,12 @@ pub(crate) fn make_compile_mono_item<'tcx>( DepNode::construct(tcx, dep_kinds::CompileMonoItem, mono_item) } +// WARNING: `construct` is generic and does not know that `Metadata` takes `()`s as keys. +// Be very careful changing this type signature! +pub(crate) fn make_metadata(tcx: TyCtxt<'_>) -> DepNode { + DepNode::construct(tcx, dep_kinds::Metadata, &()) +} + pub trait DepNodeExt: Sized { /// Extracts the DefId corresponding to this DepNode. This will work /// if two conditions are met: diff --git a/compiler/rustc_middle/src/dep_graph/mod.rs b/compiler/rustc_middle/src/dep_graph/mod.rs index 2090c3e6da6fa..1284015860819 100644 --- a/compiler/rustc_middle/src/dep_graph/mod.rs +++ b/compiler/rustc_middle/src/dep_graph/mod.rs @@ -8,7 +8,7 @@ use crate::ty::{self, TyCtxt}; mod dep_node; pub use dep_node::{DepKind, DepNode, DepNodeExt, dep_kinds, label_strs}; -pub(crate) use dep_node::{make_compile_codegen_unit, make_compile_mono_item}; +pub(crate) use dep_node::{make_compile_codegen_unit, make_compile_mono_item, make_metadata}; pub use rustc_query_system::dep_graph::debug::{DepNodeFilter, EdgeFilter}; pub use rustc_query_system::dep_graph::{ DepContext, DepGraphQuery, DepNodeIndex, Deps, SerializedDepGraph, SerializedDepNodeIndex, diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index d7a60a843b717..0af3ce593cd1d 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -132,6 +132,16 @@ rustc_queries! { desc { "getting the resolver for lowering" } } + /// Named module children from all kinds of items, including imports. + /// In addition to regular items this list also includes struct and variant constructors, and + /// items inside `extern {}` blocks because all of them introduce names into parent module. + /// + /// Module here is understood in name resolution sense - it can be a `mod` item, + /// or a crate root, or an enum, or a trait. + query module_children_local(key: LocalDefId) -> &'tcx [ModChild] { + desc { |tcx| "module exports for `{}`", tcx.def_path_str(key) } + } + /// Return the span for a definition. /// Contrary to `def_span` below, this query returns the full absolute span of the definition. /// This span is meant for dep-tracking rather than diagnostics. It should not be used outside diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 5cbbc80ebfbb6..007562a0a0b42 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -61,7 +61,6 @@ use crate::arena::Arena; use crate::dep_graph::{DepGraph, DepKindStruct}; use crate::infer::canonical::{CanonicalParamEnvCache, CanonicalVarInfo, CanonicalVarInfos}; use crate::lint::lint_level; -use crate::metadata::ModChild; use crate::middle::codegen_fn_attrs::CodegenFnAttrs; use crate::middle::{resolve_bound_vars, stability}; use crate::mir::interpret::{self, Allocation, ConstAllocation}; @@ -1863,9 +1862,8 @@ impl<'tcx> TyCtxt<'tcx> { } pub fn iter_local_def_id(self) -> impl Iterator + 'tcx { - // Create a dependency to the red node to be sure we re-execute this when the amount of - // definitions change. - self.dep_graph.read_index(DepNodeIndex::FOREVER_RED_NODE); + // Depend on the `analysis` query to ensure compilation if finished. + self.ensure().analysis(()); let definitions = &self.untracked.definitions; std::iter::from_coroutine( @@ -1888,9 +1886,8 @@ impl<'tcx> TyCtxt<'tcx> { } pub fn def_path_table(self) -> &'tcx rustc_hir::definitions::DefPathTable { - // Create a dependency to the crate to be sure we re-execute this when the amount of - // definitions change. - self.dep_graph.read_index(DepNodeIndex::FOREVER_RED_NODE); + // Depend on the `analysis` query to ensure compilation if finished. + self.ensure().analysis(()); // Freeze definitions once we start iterating on them, to prevent adding new ones // while iterating. If some query needs to add definitions, it should be `ensure`d above. @@ -3154,23 +3151,14 @@ impl<'tcx> TyCtxt<'tcx> { self.opt_rpitit_info(def_id).is_some() } - /// Named module children from all kinds of items, including imports. - /// In addition to regular items this list also includes struct and variant constructors, and - /// items inside `extern {}` blocks because all of them introduce names into parent module. - /// - /// Module here is understood in name resolution sense - it can be a `mod` item, - /// or a crate root, or an enum, or a trait. - /// - /// This is not a query, making it a query causes perf regressions - /// (probably due to hashing spans in `ModChild`ren). - pub fn module_children_local(self, def_id: LocalDefId) -> &'tcx [ModChild] { - self.resolutions(()).module_children.get(&def_id).map_or(&[], |v| &v[..]) - } - pub fn resolver_for_lowering(self) -> &'tcx Steal<(ty::ResolverAstLowering, Lrc)> { self.resolver_for_lowering_raw(()).0 } + pub fn metadata_dep_node(self) -> crate::dep_graph::DepNode { + crate::dep_graph::make_metadata(self) + } + /// Given an `impl_id`, return the trait it implements. /// Return `None` if this is an inherent impl. pub fn impl_trait_ref( @@ -3218,6 +3206,8 @@ pub struct DeducedParamAttrs { } pub fn provide(providers: &mut Providers) { + providers.module_children_local = + |tcx, def_id| tcx.resolutions(()).module_children.get(&def_id).map_or(&[], |v| &v[..]); providers.maybe_unused_trait_imports = |tcx, ()| &tcx.resolutions(()).maybe_unused_trait_imports; providers.names_imported_by_glob_use = |tcx, id| { diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index f72f656b2f8f9..8c77bc2bbf9ba 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -859,6 +859,17 @@ macro_rules! define_queries { } } + pub(crate) fn Metadata<'tcx>() -> DepKindStruct<'tcx> { + DepKindStruct { + is_anon: false, + is_eval_always: false, + fingerprint_style: FingerprintStyle::Unit, + force_from_dep_node: None, + try_load_from_on_disk_cache: None, + name: &"Metadata", + } + } + $(pub(crate) fn $name<'tcx>()-> DepKindStruct<'tcx> { $crate::plumbing::query_callback::>( is_anon!([$($modifiers)*]), diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index adb0ba7c82036..21ccced4cff0d 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -1473,13 +1473,16 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { } fn with_scope(&mut self, id: NodeId, f: impl FnOnce(&mut Self) -> T) -> T { - if let Some(module) = self.r.get_module(self.r.local_def_id(id).to_def_id()) { + let def_id = self.r.local_def_id(id); + if let Some(module) = self.r.get_module(def_id.to_def_id()) { // Move down in the graph. let orig_module = replace(&mut self.parent_scope.module, module); self.with_rib(ValueNS, RibKind::Module(module), |this| { this.with_rib(TypeNS, RibKind::Module(module), |this| { let ret = f(this); this.parent_scope.module = orig_module; + this.r.doc_link_resolutions.entry(def_id).or_default(); + this.r.doc_link_traits_in_scope.entry(def_id).or_default(); ret }) }) @@ -5054,6 +5057,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { BuiltinLintDiag::UnusedLabel, ); } + self.doc_link_resolutions.entry(CRATE_DEF_ID).or_default(); + self.doc_link_traits_in_scope.entry(CRATE_DEF_ID).or_default(); } }