From 32e6a1a0ab2b53877e0595677a4ca395f18a08e9 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 11 Feb 2026 19:06:33 +1100 Subject: [PATCH 1/5] Remove `QueryContext`. `rustc_query_system` has been reduced so much that it's no longer needed. This avoids a lot of indirection and abstraction. --- Cargo.lock | 1 - .../rustc_incremental/src/assert_dep_graph.rs | 2 +- .../rustc_incremental/src/persist/clean.rs | 2 +- compiler/rustc_interface/src/callbacks.rs | 5 +- .../rustc_middle/src/dep_graph/dep_node.rs | 22 +--- .../src/dep_graph/dep_node_key.rs | 2 +- compiler/rustc_middle/src/dep_graph/graph.rs | 101 ++++++++++-------- compiler/rustc_middle/src/dep_graph/mod.rs | 4 +- compiler/rustc_middle/src/query/mod.rs | 18 ---- compiler/rustc_query_impl/Cargo.toml | 1 - .../rustc_query_impl/src/dep_kind_vtables.rs | 4 +- compiler/rustc_query_impl/src/execution.rs | 4 +- compiler/rustc_query_impl/src/plumbing.rs | 36 +------ 13 files changed, 75 insertions(+), 127 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4e0978a8cf214..f9bd9fe603491 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4500,7 +4500,6 @@ dependencies = [ "rustc_index", "rustc_macros", "rustc_middle", - "rustc_query_system", "rustc_serialize", "rustc_session", "rustc_span", diff --git a/compiler/rustc_incremental/src/assert_dep_graph.rs b/compiler/rustc_incremental/src/assert_dep_graph.rs index 3447836598bf0..a51b86eb72bfc 100644 --- a/compiler/rustc_incremental/src/assert_dep_graph.rs +++ b/compiler/rustc_incremental/src/assert_dep_graph.rs @@ -45,7 +45,7 @@ use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LocalDefId}; use rustc_hir::intravisit::{self, Visitor}; use rustc_middle::bug; use rustc_middle::dep_graph::{ - DepGraphQuery, DepKind, DepNode, DepNodeExt, DepNodeFilter, EdgeFilter, dep_kinds, + DepGraphQuery, DepKind, DepNode, DepNodeFilter, EdgeFilter, dep_kinds, }; use rustc_middle::hir::nested_filter; use rustc_middle::ty::TyCtxt; diff --git a/compiler/rustc_incremental/src/persist/clean.rs b/compiler/rustc_incremental/src/persist/clean.rs index d83ba5a78bed5..0067b38fadc75 100644 --- a/compiler/rustc_incremental/src/persist/clean.rs +++ b/compiler/rustc_incremental/src/persist/clean.rs @@ -27,7 +27,7 @@ use rustc_hir::{ Attribute, ImplItemKind, ItemKind as HirItem, Node as HirNode, TraitItemKind, find_attr, intravisit, }; -use rustc_middle::dep_graph::{DepNode, DepNodeExt, dep_kind_from_label, label_strs}; +use rustc_middle::dep_graph::{DepNode, dep_kind_from_label, label_strs}; use rustc_middle::hir::nested_filter; use rustc_middle::ty::TyCtxt; use rustc_span::{Span, Symbol}; diff --git a/compiler/rustc_interface/src/callbacks.rs b/compiler/rustc_interface/src/callbacks.rs index 5aa1616397f8a..49c682ea93f8d 100644 --- a/compiler/rustc_interface/src/callbacks.rs +++ b/compiler/rustc_interface/src/callbacks.rs @@ -13,9 +13,8 @@ use std::fmt; use rustc_errors::{DiagInner, TRACK_DIAGNOSTIC}; use rustc_middle::dep_graph::dep_node::default_dep_kind_debug; -use rustc_middle::dep_graph::{DepContext, DepKind, DepNode, DepNodeExt, TaskDepsRef}; +use rustc_middle::dep_graph::{DepContext, DepKind, DepNode, TaskDepsRef}; use rustc_middle::ty::tls; -use rustc_query_impl::QueryCtxt; fn track_span_parent(def_id: rustc_span::def_id::LocalDefId) { tls::with_context_opt(|icx| { @@ -41,7 +40,7 @@ fn track_span_parent(def_id: rustc_span::def_id::LocalDefId) { fn track_diagnostic(diagnostic: DiagInner, f: &mut dyn FnMut(DiagInner) -> R) -> R { tls::with_context_opt(|icx| { if let Some(icx) = icx { - icx.tcx.dep_graph.record_diagnostic(QueryCtxt::new(icx.tcx), &diagnostic); + icx.tcx.dep_graph.record_diagnostic(icx.tcx, &diagnostic); // Diagnostics are tracked, we can ignore the dependency. let icx = tls::ImplicitCtxt { task_deps: TaskDepsRef::Ignore, ..icx.clone() }; diff --git a/compiler/rustc_middle/src/dep_graph/dep_node.rs b/compiler/rustc_middle/src/dep_graph/dep_node.rs index 0033a1cd2337b..2d198b65d1285 100644 --- a/compiler/rustc_middle/src/dep_graph/dep_node.rs +++ b/compiler/rustc_middle/src/dep_graph/dep_node.rs @@ -434,19 +434,7 @@ pub(crate) fn make_metadata(tcx: TyCtxt<'_>) -> DepNode { DepNode::construct(tcx, dep_kinds::Metadata, &()) } -pub trait DepNodeExt: Sized { - fn extract_def_id(&self, tcx: TyCtxt<'_>) -> Option; - - fn from_label_string( - tcx: TyCtxt<'_>, - label: &str, - def_path_hash: DefPathHash, - ) -> Result; - - fn has_label_string(label: &str) -> bool; -} - -impl DepNodeExt for DepNode { +impl DepNode { /// Extracts the DefId corresponding to this DepNode. This will work /// if two conditions are met: /// @@ -457,7 +445,7 @@ impl DepNodeExt for DepNode { /// DepNode. Condition (2) might not be fulfilled if a DepNode /// refers to something from the previous compilation session that /// has been removed. - fn extract_def_id(&self, tcx: TyCtxt<'_>) -> Option { + pub fn extract_def_id(&self, tcx: TyCtxt<'_>) -> Option { if tcx.fingerprint_style(self.kind) == FingerprintStyle::DefPathHash { tcx.def_path_hash_to_def_id(DefPathHash(self.hash.into())) } else { @@ -465,8 +453,7 @@ impl DepNodeExt for DepNode { } } - /// Used in testing - fn from_label_string( + pub fn from_label_string( tcx: TyCtxt<'_>, label: &str, def_path_hash: DefPathHash, @@ -482,8 +469,7 @@ impl DepNodeExt for DepNode { } } - /// Used in testing - fn has_label_string(label: &str) -> bool { + pub fn has_label_string(label: &str) -> bool { dep_kind_from_label_string(label).is_ok() } } diff --git a/compiler/rustc_middle/src/dep_graph/dep_node_key.rs b/compiler/rustc_middle/src/dep_graph/dep_node_key.rs index b1dfc15539bf9..1b9b02b67fad2 100644 --- a/compiler/rustc_middle/src/dep_graph/dep_node_key.rs +++ b/compiler/rustc_middle/src/dep_graph/dep_node_key.rs @@ -3,7 +3,7 @@ use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId, LocalModDefId, use rustc_hir::definitions::DefPathHash; use rustc_hir::{HirId, ItemLocalId, OwnerId}; -use crate::dep_graph::{DepContext, DepNode, DepNodeExt, DepNodeKey, FingerprintStyle}; +use crate::dep_graph::{DepContext, DepNode, DepNodeKey, FingerprintStyle}; use crate::ty::TyCtxt; impl<'tcx> DepNodeKey> for () { diff --git a/compiler/rustc_middle/src/dep_graph/graph.rs b/compiler/rustc_middle/src/dep_graph/graph.rs index 3ef0511795b90..734b313f082ef 100644 --- a/compiler/rustc_middle/src/dep_graph/graph.rs +++ b/compiler/rustc_middle/src/dep_graph/graph.rs @@ -27,7 +27,7 @@ use super::query::DepGraphQuery; use super::serialized::{GraphEncoder, SerializedDepGraph, SerializedDepNodeIndex}; use super::{DepContext, DepKind, DepNode, Deps, HasDepContext, WorkProductId}; use crate::dep_graph::edges::EdgesVec; -use crate::query::QueryContext; +use crate::ty::TyCtxt; use crate::verify_ich::incremental_verify_ich; pub struct DepGraph { @@ -525,16 +525,12 @@ impl DepGraph { /// This encodes a diagnostic by creating a node with an unique index and associating /// `diagnostic` with it, for use in the next session. #[inline] - pub fn record_diagnostic<'tcx, Qcx: QueryContext<'tcx>>( - &self, - qcx: Qcx, - diagnostic: &DiagInner, - ) { + pub fn record_diagnostic<'tcx>(&self, tcx: TyCtxt<'tcx>, diagnostic: &DiagInner) { if let Some(ref data) = self.data { D::read_deps(|task_deps| match task_deps { TaskDepsRef::EvalAlways | TaskDepsRef::Ignore => return, TaskDepsRef::Forbid | TaskDepsRef::Allow(..) => { - self.read_index(data.encode_diagnostic(qcx, diagnostic)); + self.read_index(data.encode_diagnostic(tcx, diagnostic)); } }) } @@ -542,13 +538,13 @@ impl DepGraph { /// This forces a diagnostic node green by running its side effect. `prev_index` would /// refer to a node created used `encode_diagnostic` in the previous session. #[inline] - pub fn force_diagnostic_node<'tcx, Qcx: QueryContext<'tcx>>( + pub fn force_diagnostic_node<'tcx>( &self, - qcx: Qcx, + tcx: TyCtxt<'tcx>, prev_index: SerializedDepNodeIndex, ) { if let Some(ref data) = self.data { - data.force_diagnostic_node(qcx, prev_index); + data.force_diagnostic_node(tcx, prev_index); } } @@ -688,11 +684,7 @@ impl DepGraphData { /// This encodes a diagnostic by creating a node with an unique index and associating /// `diagnostic` with it, for use in the next session. #[inline] - fn encode_diagnostic<'tcx, Qcx: QueryContext<'tcx>>( - &self, - qcx: Qcx, - diagnostic: &DiagInner, - ) -> DepNodeIndex { + fn encode_diagnostic<'tcx>(&self, tcx: TyCtxt<'tcx>, diagnostic: &DiagInner) -> DepNodeIndex { // Use `send_new` so we get an unique index, even though the dep node is not. let dep_node_index = self.current.encoder.send_new( DepNode { @@ -705,24 +697,20 @@ impl DepGraphData { std::iter::once(DepNodeIndex::FOREVER_RED_NODE).collect(), ); let side_effect = QuerySideEffect::Diagnostic(diagnostic.clone()); - qcx.store_side_effect(dep_node_index, side_effect); + tcx.store_side_effect(dep_node_index, side_effect); dep_node_index } /// This forces a diagnostic node green by running its side effect. `prev_index` would /// refer to a node created used `encode_diagnostic` in the previous session. #[inline] - fn force_diagnostic_node<'tcx, Qcx: QueryContext<'tcx>>( - &self, - qcx: Qcx, - prev_index: SerializedDepNodeIndex, - ) { + fn force_diagnostic_node<'tcx>(&self, tcx: TyCtxt<'tcx>, prev_index: SerializedDepNodeIndex) { D::with_deps(TaskDepsRef::Ignore, || { - let side_effect = qcx.load_side_effect(prev_index).unwrap(); + let side_effect = tcx.load_side_effect(prev_index).unwrap(); match &side_effect { QuerySideEffect::Diagnostic(diagnostic) => { - qcx.dep_context().sess().dcx().emit_diagnostic(diagnostic.clone()); + tcx.dcx().emit_diagnostic(diagnostic.clone()); } } @@ -741,7 +729,7 @@ impl DepGraphData { true, ); // This will just overwrite the same value for concurrent calls. - qcx.store_side_effect(dep_node_index, side_effect); + tcx.store_side_effect(dep_node_index, side_effect); }) } @@ -867,12 +855,12 @@ impl DepGraph { DepNodeColor::Unknown } - pub fn try_mark_green<'tcx, Qcx: QueryContext<'tcx, Deps = D>>( + pub fn try_mark_green<'tcx>( &self, - qcx: Qcx, + tcx: TyCtxt<'tcx>, dep_node: &DepNode, ) -> Option<(SerializedDepNodeIndex, DepNodeIndex)> { - self.data().and_then(|data| data.try_mark_green(qcx, dep_node)) + self.data().and_then(|data| data.try_mark_green(tcx, dep_node)) } } @@ -882,12 +870,12 @@ impl DepGraphData { /// A node will have an index, when it's already been marked green, or when we can mark it /// green. This function will mark the current task as a reader of the specified node, when /// a node index can be found for that node. - pub fn try_mark_green<'tcx, Qcx: QueryContext<'tcx, Deps = D>>( + pub fn try_mark_green<'tcx>( &self, - qcx: Qcx, + tcx: TyCtxt<'tcx>, dep_node: &DepNode, ) -> Option<(SerializedDepNodeIndex, DepNodeIndex)> { - debug_assert!(!qcx.dep_context().is_eval_always(dep_node.kind)); + debug_assert!(!tcx.is_eval_always(dep_node.kind)); // Return None if the dep node didn't exist in the previous session let prev_index = self.previous.node_to_index_opt(dep_node)?; @@ -902,16 +890,16 @@ impl DepGraphData { // in the previous compilation session too, so we can try to // mark it as green by recursively marking all of its // dependencies green. - self.try_mark_previous_green(qcx, prev_index, None) + self.try_mark_previous_green(tcx, prev_index, None) .map(|dep_node_index| (prev_index, dep_node_index)) } } } - #[instrument(skip(self, qcx, parent_dep_node_index, frame), level = "debug")] - fn try_mark_parent_green<'tcx, Qcx: QueryContext<'tcx, Deps = D>>( + #[instrument(skip(self, tcx, parent_dep_node_index, frame), level = "debug")] + fn try_mark_parent_green<'tcx>( &self, - qcx: Qcx, + tcx: TyCtxt<'tcx>, parent_dep_node_index: SerializedDepNodeIndex, frame: &MarkFrame<'_>, ) -> Option<()> { @@ -944,13 +932,13 @@ impl DepGraphData { // We don't know the state of this dependency. If it isn't // an eval_always node, let's try to mark it green recursively. - if !qcx.dep_context().is_eval_always(dep_dep_node.kind) { + if !tcx.is_eval_always(dep_dep_node.kind) { debug!( "state of dependency {:?} ({}) is unknown, trying to mark it green", dep_dep_node, dep_dep_node.hash, ); - let node_index = self.try_mark_previous_green(qcx, parent_dep_node_index, Some(frame)); + let node_index = self.try_mark_previous_green(tcx, parent_dep_node_index, Some(frame)); if node_index.is_some() { debug!("managed to MARK dependency {dep_dep_node:?} as green"); @@ -960,7 +948,7 @@ impl DepGraphData { // We failed to mark it green, so we try to force the query. debug!("trying to force dependency {dep_dep_node:?}"); - if !qcx.dep_context().try_force_from_dep_node(*dep_dep_node, parent_dep_node_index, frame) { + if !tcx.dep_context().try_force_from_dep_node(*dep_dep_node, parent_dep_node_index, frame) { // The DepNode could not be forced. debug!("dependency {dep_dep_node:?} could not be forced"); return None; @@ -978,7 +966,7 @@ impl DepGraphData { DepNodeColor::Unknown => {} } - if let None = qcx.dep_context().sess().dcx().has_errors_or_delayed_bugs() { + if let None = tcx.dcx().has_errors_or_delayed_bugs() { panic!("try_mark_previous_green() - Forcing the DepNode should have set its color") } @@ -997,10 +985,10 @@ impl DepGraphData { } /// Try to mark a dep-node which existed in the previous compilation session as green. - #[instrument(skip(self, qcx, prev_dep_node_index, frame), level = "debug")] - fn try_mark_previous_green<'tcx, Qcx: QueryContext<'tcx, Deps = D>>( + #[instrument(skip(self, tcx, prev_dep_node_index, frame), level = "debug")] + fn try_mark_previous_green<'tcx>( &self, - qcx: Qcx, + tcx: TyCtxt<'tcx>, prev_dep_node_index: SerializedDepNodeIndex, frame: Option<&MarkFrame<'_>>, ) -> Option { @@ -1008,14 +996,14 @@ impl DepGraphData { // We never try to mark eval_always nodes as green debug_assert!( - !qcx.dep_context() + !tcx.dep_context() .is_eval_always(self.previous.index_to_node(prev_dep_node_index).kind) ); let prev_deps = self.previous.edge_targets_from(prev_dep_node_index); for dep_dep_node_index in prev_deps { - self.try_mark_parent_green(qcx, dep_dep_node_index, &frame)?; + self.try_mark_parent_green(tcx, dep_dep_node_index, &frame)?; } // If we got here without hitting a `return` that means that all @@ -1508,3 +1496,30 @@ fn panic_on_forbidden_read(data: &DepGraphData, dep_node_index: DepN See ." ) } + +impl<'tcx> TyCtxt<'tcx> { + /// Return whether this kind always require evaluation. + #[inline(always)] + fn is_eval_always(self, kind: DepKind) -> bool { + self.dep_kind_vtable(kind).is_eval_always + } + + // Interactions with on_disk_cache + fn load_side_effect( + self, + prev_dep_node_index: SerializedDepNodeIndex, + ) -> Option { + self.query_system + .on_disk_cache + .as_ref() + .and_then(|c| c.load_side_effect(self, prev_dep_node_index)) + } + + #[inline(never)] + #[cold] + fn store_side_effect(self, dep_node_index: DepNodeIndex, side_effect: QuerySideEffect) { + if let Some(c) = self.query_system.on_disk_cache.as_ref() { + c.store_side_effect(dep_node_index, side_effect) + } + } +} diff --git a/compiler/rustc_middle/src/dep_graph/mod.rs b/compiler/rustc_middle/src/dep_graph/mod.rs index 723eed21f211d..611d76ef7e5ee 100644 --- a/compiler/rustc_middle/src/dep_graph/mod.rs +++ b/compiler/rustc_middle/src/dep_graph/mod.rs @@ -7,8 +7,7 @@ use rustc_session::Session; use tracing::instrument; pub use self::dep_node::{ - DepKind, DepNode, DepNodeExt, DepNodeKey, WorkProductId, dep_kind_from_label, dep_kinds, - label_strs, + DepKind, DepNode, DepNodeKey, WorkProductId, dep_kind_from_label, dep_kinds, label_strs, }; pub use self::graph::{ DepGraphData, DepNodeIndex, TaskDepsRef, WorkProduct, WorkProductMap, hash_result, @@ -52,6 +51,7 @@ pub trait DepContext: Copy { #[inline(always)] /// Return whether this kind always require evaluation. + // FIXME: remove this in favour of the version on `TyCtxt`. fn is_eval_always(self, kind: DepKind) -> bool { self.dep_kind_vtable(kind).is_eval_always } diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index d16ca3c401d24..66e4a77ea6a51 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1,6 +1,4 @@ -use rustc_data_structures::jobserver::Proxy; use rustc_hir::def_id::LocalDefId; -use rustc_query_system::query::QuerySideEffect; pub use self::caches::{ DefIdCache, DefaultCache, QueryCache, QueryCacheKey, SingleCache, VecCache, @@ -12,7 +10,6 @@ pub use self::plumbing::{ TyCtxtAt, TyCtxtEnsureDone, TyCtxtEnsureOk, }; pub use self::stack::{QueryStackDeferred, QueryStackFrame, QueryStackFrameExtra}; -use crate::dep_graph::{DepNodeIndex, HasDepContext, SerializedDepNodeIndex}; pub use crate::queries::Providers; use crate::ty::TyCtxt; @@ -36,18 +33,3 @@ pub fn describe_as_module(def_id: impl Into, tcx: TyCtxt<'_>) -> Str format!("module `{}`", tcx.def_path_str(def_id)) } } - -pub trait QueryContext<'tcx>: HasDepContext { - /// Gets a jobserver reference which is used to release then acquire - /// a token while waiting on a query. - fn jobserver_proxy(&self) -> &Proxy; - - /// Load a side effect associated to the node in the previous session. - fn load_side_effect( - self, - prev_dep_node_index: SerializedDepNodeIndex, - ) -> Option; - - /// Register a side effect for the given node, for use in next session. - fn store_side_effect(self, dep_node_index: DepNodeIndex, side_effect: QuerySideEffect); -} diff --git a/compiler/rustc_query_impl/Cargo.toml b/compiler/rustc_query_impl/Cargo.toml index a8edc11294818..5b840cba5a59e 100644 --- a/compiler/rustc_query_impl/Cargo.toml +++ b/compiler/rustc_query_impl/Cargo.toml @@ -14,7 +14,6 @@ rustc_hir = { path = "../rustc_hir" } rustc_index = { path = "../rustc_index" } rustc_macros = { path = "../rustc_macros" } rustc_middle = { path = "../rustc_middle" } -rustc_query_system = { path = "../rustc_query_system" } rustc_serialize = { path = "../rustc_serialize" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } diff --git a/compiler/rustc_query_impl/src/dep_kind_vtables.rs b/compiler/rustc_query_impl/src/dep_kind_vtables.rs index 99feeb86bac93..53fc8034e0229 100644 --- a/compiler/rustc_query_impl/src/dep_kind_vtables.rs +++ b/compiler/rustc_query_impl/src/dep_kind_vtables.rs @@ -4,7 +4,7 @@ use rustc_middle::query::QueryCache; use rustc_middle::ty::TyCtxt; use crate::plumbing::{force_from_dep_node_inner, try_load_from_on_disk_cache_inner}; -use crate::{QueryCtxt, QueryDispatcherUnerased, QueryFlags}; +use crate::{QueryDispatcherUnerased, QueryFlags}; /// [`DepKindVTable`] constructors for special dep kinds that aren't queries. #[expect(non_snake_case, reason = "use non-snake case to avoid collision with query names")] @@ -45,7 +45,7 @@ mod non_query { is_eval_always: false, fingerprint_style: FingerprintStyle::Unit, force_from_dep_node: Some(|tcx, _, prev_index| { - tcx.dep_graph.force_diagnostic_node(QueryCtxt::new(tcx), prev_index); + tcx.dep_graph.force_diagnostic_node(tcx, prev_index); true }), try_load_from_on_disk_cache: None, diff --git a/compiler/rustc_query_impl/src/execution.rs b/compiler/rustc_query_impl/src/execution.rs index 4df55e46e13ec..89ec7ad9012a3 100644 --- a/compiler/rustc_query_impl/src/execution.rs +++ b/compiler/rustc_query_impl/src/execution.rs @@ -495,7 +495,7 @@ fn try_load_from_disk_and_cache_in_memory<'tcx, C: QueryCache, const FLAGS: Quer // Note this function can be called concurrently from the same query // We must ensure that this is handled correctly. - let (prev_dep_node_index, dep_node_index) = dep_graph_data.try_mark_green(qcx, dep_node)?; + let (prev_dep_node_index, dep_node_index) = dep_graph_data.try_mark_green(qcx.tcx, dep_node)?; debug_assert!(dep_graph_data.is_index_green(prev_dep_node_index)); @@ -602,7 +602,7 @@ fn ensure_must_run<'tcx, C: QueryCache, const FLAGS: QueryFlags>( let dep_node = query.construct_dep_node(qcx.tcx, key); let dep_graph = &qcx.tcx.dep_graph; - let serialized_dep_node_index = match dep_graph.try_mark_green(qcx, &dep_node) { + let serialized_dep_node_index = match dep_graph.try_mark_green(qcx.tcx, &dep_node) { None => { // A None return from `try_mark_green` means that this is either // a new dep node or that the dep node has already been marked red. diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index ad782b3150b08..911d38d0993e9 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -4,7 +4,6 @@ use std::num::NonZero; -use rustc_data_structures::jobserver::Proxy; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::sync::{DynSend, DynSync}; use rustc_data_structures::unord::UnordMap; @@ -24,14 +23,12 @@ use rustc_middle::query::on_disk_cache::{ }; use rustc_middle::query::plumbing::QueryVTable; use rustc_middle::query::{ - Key, QueryCache, QueryContext, QueryJobId, QueryStackDeferred, QueryStackFrame, - QueryStackFrameExtra, + Key, QueryCache, QueryJobId, QueryStackDeferred, QueryStackFrame, QueryStackFrameExtra, }; use rustc_middle::ty::codec::TyEncoder; use rustc_middle::ty::print::with_reduced_queries; use rustc_middle::ty::tls::{self, ImplicitCtxt}; use rustc_middle::ty::{self, TyCtxt}; -use rustc_query_system::query::QuerySideEffect; use rustc_serialize::{Decodable, Encodable}; use rustc_span::def_id::LOCAL_CRATE; @@ -40,8 +37,6 @@ use crate::execution::{all_inactive, force_query}; use crate::job::{QueryJobMap, find_dep_kind_root}; use crate::{QueryDispatcherUnerased, QueryFlags, SemiDynamicQueryDispatcher}; -/// Implements [`QueryContext`] for use by [`rustc_query_system`], since that -/// crate does not have direct access to [`TyCtxt`]. #[derive(Copy, Clone)] pub struct QueryCtxt<'tcx> { pub tcx: TyCtxt<'tcx>, @@ -156,35 +151,8 @@ impl<'tcx> HasDepContext for QueryCtxt<'tcx> { } } -impl<'tcx> QueryContext<'tcx> for QueryCtxt<'tcx> { - #[inline] - fn jobserver_proxy(&self) -> &Proxy { - &self.tcx.jobserver_proxy - } - - // Interactions with on_disk_cache - fn load_side_effect( - self, - prev_dep_node_index: SerializedDepNodeIndex, - ) -> Option { - self.tcx - .query_system - .on_disk_cache - .as_ref() - .and_then(|c| c.load_side_effect(self.tcx, prev_dep_node_index)) - } - - #[inline(never)] - #[cold] - fn store_side_effect(self, dep_node_index: DepNodeIndex, side_effect: QuerySideEffect) { - if let Some(c) = self.tcx.query_system.on_disk_cache.as_ref() { - c.store_side_effect(dep_node_index, side_effect) - } - } -} - pub(super) fn try_mark_green<'tcx>(tcx: TyCtxt<'tcx>, dep_node: &dep_graph::DepNode) -> bool { - tcx.dep_graph.try_mark_green(QueryCtxt::new(tcx), dep_node).is_some() + tcx.dep_graph.try_mark_green(tcx, dep_node).is_some() } pub(super) fn encode_all_query_results<'tcx>( From 1d83208683c766f55683336b9b189db24e9bd066 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 12 Feb 2026 09:37:42 +1100 Subject: [PATCH 2/5] De-genericize the dep graph. By removing the generic `D` parameter from `DepGraph`, `DepGraphData`, `CurrentDepGraph`, `SerializedDepGraph`, `SerializedNodeHeader`, and `EncoderState`. --- .../rustc_incremental/src/persist/load.rs | 4 +- compiler/rustc_middle/src/dep_graph/graph.rs | 90 +++++++++---------- compiler/rustc_middle/src/dep_graph/mod.rs | 6 +- .../rustc_middle/src/dep_graph/serialized.rs | 80 ++++++++--------- compiler/rustc_middle/src/verify_ich.rs | 2 +- compiler/rustc_query_impl/src/execution.rs | 6 +- 6 files changed, 88 insertions(+), 100 deletions(-) diff --git a/compiler/rustc_incremental/src/persist/load.rs b/compiler/rustc_incremental/src/persist/load.rs index e93cba2c8d0fc..f7182e3614dc8 100644 --- a/compiler/rustc_incremental/src/persist/load.rs +++ b/compiler/rustc_incremental/src/persist/load.rs @@ -6,7 +6,7 @@ use std::sync::Arc; use rustc_data_structures::memmap::Mmap; use rustc_data_structures::unord::UnordMap; use rustc_hashes::Hash64; -use rustc_middle::dep_graph::{DepGraph, DepsType, SerializedDepGraph, WorkProductMap}; +use rustc_middle::dep_graph::{DepGraph, SerializedDepGraph, WorkProductMap}; use rustc_middle::query::on_disk_cache::OnDiskCache; use rustc_serialize::Decodable; use rustc_serialize::opaque::MemDecoder; @@ -171,7 +171,7 @@ fn load_dep_graph(sess: &Session) -> LoadResult<(Arc, WorkPr return LoadResult::DataOutOfDate; } - let dep_graph = SerializedDepGraph::decode::(&mut decoder); + let dep_graph = SerializedDepGraph::decode(&mut decoder); LoadResult::Ok { data: (dep_graph, prev_work_products) } } diff --git a/compiler/rustc_middle/src/dep_graph/graph.rs b/compiler/rustc_middle/src/dep_graph/graph.rs index 734b313f082ef..0ee1ee44fd1cb 100644 --- a/compiler/rustc_middle/src/dep_graph/graph.rs +++ b/compiler/rustc_middle/src/dep_graph/graph.rs @@ -25,13 +25,14 @@ use {super::debug::EdgeFilter, std::env}; use super::query::DepGraphQuery; use super::serialized::{GraphEncoder, SerializedDepGraph, SerializedDepNodeIndex}; -use super::{DepContext, DepKind, DepNode, Deps, HasDepContext, WorkProductId}; +use super::{DepContext, DepKind, DepNode, Deps, DepsType, HasDepContext, WorkProductId}; use crate::dep_graph::edges::EdgesVec; use crate::ty::TyCtxt; use crate::verify_ich::incremental_verify_ich; -pub struct DepGraph { - data: Option>>, +#[derive(Clone)] +pub struct DepGraph { + data: Option>, /// This field is used for assigning DepNodeIndices when running in /// non-incremental mode. Even in non-incremental mode we make sure that @@ -40,17 +41,6 @@ pub struct DepGraph { virtual_dep_node_index: Arc, } -/// Manual clone impl that does not require `D: Clone`. -impl Clone for DepGraph { - fn clone(&self) -> Self { - let Self { data, virtual_dep_node_index } = self; - Self { - data: Option::>::clone(data), - virtual_dep_node_index: Arc::clone(virtual_dep_node_index), - } - } -} - rustc_index::newtype_index! { pub struct DepNodeIndex {} } @@ -84,12 +74,12 @@ pub(super) enum DepNodeColor { Unknown, } -pub struct DepGraphData { +pub struct DepGraphData { /// The new encoding of the dependency graph, optimized for red/green /// tracking. The `current` field is the dependency graph of only the /// current compilation session: We don't merge the previous dep-graph into /// current one anymore, but we do reference shared data to save space. - current: CurrentDepGraph, + current: CurrentDepGraph, /// The dep-graph from the previous compilation session. It contains all /// nodes and edges as well as all fingerprints of nodes that have them. @@ -120,13 +110,13 @@ where stable_hasher.finish() } -impl DepGraph { +impl DepGraph { pub fn new( session: &Session, prev_graph: Arc, prev_work_products: WorkProductMap, encoder: FileEncoder, - ) -> DepGraph { + ) -> DepGraph { let prev_graph_node_count = prev_graph.node_count(); let current = @@ -136,7 +126,7 @@ impl DepGraph { // Instantiate a node with zero dependencies only once for anonymous queries. let _green_node_index = current.alloc_new_node( - DepNode { kind: D::DEP_KIND_ANON_ZERO_DEPS, hash: current.anon_id_seed.into() }, + DepNode { kind: DepsType::DEP_KIND_ANON_ZERO_DEPS, hash: current.anon_id_seed.into() }, EdgesVec::new(), Fingerprint::ZERO, ); @@ -144,7 +134,7 @@ impl DepGraph { // Instantiate a dependy-less red node only once for anonymous queries. let red_node_index = current.alloc_new_node( - DepNode { kind: D::DEP_KIND_RED, hash: Fingerprint::ZERO.into() }, + DepNode { kind: DepsType::DEP_KIND_RED, hash: Fingerprint::ZERO.into() }, EdgesVec::new(), Fingerprint::ZERO, ); @@ -168,12 +158,12 @@ impl DepGraph { } } - pub fn new_disabled() -> DepGraph { + pub fn new_disabled() -> DepGraph { DepGraph { data: None, virtual_dep_node_index: Arc::new(AtomicU32::new(0)) } } #[inline] - pub fn data(&self) -> Option<&DepGraphData> { + pub fn data(&self) -> Option<&DepGraphData> { self.data.as_deref() } @@ -191,7 +181,7 @@ impl DepGraph { pub fn assert_ignored(&self) { if let Some(..) = self.data { - D::read_deps(|task_deps| { + DepsType::read_deps(|task_deps| { assert_matches!( task_deps, TaskDepsRef::Ignore, @@ -205,7 +195,7 @@ impl DepGraph { where OP: FnOnce() -> R, { - D::with_deps(TaskDepsRef::Ignore, op) + DepsType::with_deps(TaskDepsRef::Ignore, op) } /// Used to wrap the deserialization of a query result from disk, @@ -258,11 +248,11 @@ impl DepGraph { where OP: FnOnce() -> R, { - D::with_deps(TaskDepsRef::Forbid, op) + DepsType::with_deps(TaskDepsRef::Forbid, op) } #[inline(always)] - pub fn with_task, A: Debug, R>( + pub fn with_task, A: Debug, R>( &self, key: DepNode, cx: Ctxt, @@ -276,7 +266,7 @@ impl DepGraph { } } - pub fn with_anon_task, OP, R>( + pub fn with_anon_task, OP, R>( &self, cx: Tcx, dep_kind: DepKind, @@ -296,7 +286,7 @@ impl DepGraph { } } -impl DepGraphData { +impl DepGraphData { /// Starts a new dep-graph task. Dep-graph tasks are specified /// using a free function (`task`) and **not** a closure -- this /// is intentional because we want to exercise tight control over @@ -325,7 +315,7 @@ impl DepGraphData { /// /// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/queries/incremental-compilation.html #[inline(always)] - pub fn with_task, A: Debug, R>( + pub fn with_task, A: Debug, R>( &self, key: DepNode, cx: Ctxt, @@ -350,7 +340,7 @@ impl DepGraphData { }, ); - let with_deps = |task_deps| D::with_deps(task_deps, || task(cx, arg)); + let with_deps = |task_deps| DepsType::with_deps(task_deps, || task(cx, arg)); let (result, edges) = if cx.dep_context().is_eval_always(key.kind) { (with_deps(TaskDepsRef::EvalAlways), EdgesVec::new()) } else { @@ -379,7 +369,7 @@ impl DepGraphData { /// FIXME: This could perhaps return a `WithDepNode` to ensure that the /// user of this function actually performs the read; we'll have to see /// how to make that work with `anon` in `execute_job_incr`, though. - pub fn with_anon_task_inner, OP, R>( + pub fn with_anon_task_inner, OP, R>( &self, cx: Tcx, dep_kind: DepKind, @@ -397,7 +387,7 @@ impl DepGraphData { None, 128, )); - let result = D::with_deps(TaskDepsRef::Allow(&task_deps), op); + let result = DepsType::with_deps(TaskDepsRef::Allow(&task_deps), op); let task_deps = task_deps.into_inner(); let reads = task_deps.reads; @@ -448,7 +438,7 @@ impl DepGraphData { } /// Intern the new `DepNode` with the dependencies up-to-now. - fn hash_result_and_alloc_node, R>( + fn hash_result_and_alloc_node, R>( &self, cx: &Ctxt, node: DepNode, @@ -466,11 +456,11 @@ impl DepGraphData { } } -impl DepGraph { +impl DepGraph { #[inline] pub fn read_index(&self, dep_node_index: DepNodeIndex) { if let Some(ref data) = self.data { - D::read_deps(|task_deps| { + DepsType::read_deps(|task_deps| { let mut task_deps = match task_deps { TaskDepsRef::Allow(deps) => deps.lock(), TaskDepsRef::EvalAlways => { @@ -527,7 +517,7 @@ impl DepGraph { #[inline] pub fn record_diagnostic<'tcx>(&self, tcx: TyCtxt<'tcx>, diagnostic: &DiagInner) { if let Some(ref data) = self.data { - D::read_deps(|task_deps| match task_deps { + DepsType::read_deps(|task_deps| match task_deps { TaskDepsRef::EvalAlways | TaskDepsRef::Ignore => return, TaskDepsRef::Forbid | TaskDepsRef::Allow(..) => { self.read_index(data.encode_diagnostic(tcx, diagnostic)); @@ -563,7 +553,7 @@ impl DepGraph { /// FIXME: If the code is changed enough for this node to be marked before requiring the /// caller's node, we suppose that those changes will be enough to mark this node red and /// force a recomputation using the "normal" way. - pub fn with_feed_task, R>( + pub fn with_feed_task, R>( &self, node: DepNode, cx: Ctxt, @@ -604,7 +594,7 @@ impl DepGraph { } let mut edges = EdgesVec::new(); - D::read_deps(|task_deps| match task_deps { + DepsType::read_deps(|task_deps| match task_deps { TaskDepsRef::Allow(deps) => edges.extend(deps.lock().reads.iter().copied()), TaskDepsRef::EvalAlways => { edges.push(DepNodeIndex::FOREVER_RED_NODE); @@ -626,7 +616,7 @@ impl DepGraph { } } -impl DepGraphData { +impl DepGraphData { fn assert_dep_node_not_yet_allocated_in_current_session( &self, sess: &Session, @@ -688,7 +678,7 @@ impl DepGraphData { // Use `send_new` so we get an unique index, even though the dep node is not. let dep_node_index = self.current.encoder.send_new( DepNode { - kind: D::DEP_KIND_SIDE_EFFECT, + kind: DepsType::DEP_KIND_SIDE_EFFECT, hash: PackedFingerprint::from(Fingerprint::ZERO), }, Fingerprint::ZERO, @@ -705,7 +695,7 @@ impl DepGraphData { /// refer to a node created used `encode_diagnostic` in the previous session. #[inline] fn force_diagnostic_node<'tcx>(&self, tcx: TyCtxt<'tcx>, prev_index: SerializedDepNodeIndex) { - D::with_deps(TaskDepsRef::Ignore, || { + DepsType::with_deps(TaskDepsRef::Ignore, || { let side_effect = tcx.load_side_effect(prev_index).unwrap(); match &side_effect { @@ -721,7 +711,7 @@ impl DepGraphData { prev_index, &self.colors, DepNode { - kind: D::DEP_KIND_SIDE_EFFECT, + kind: DepsType::DEP_KIND_SIDE_EFFECT, hash: PackedFingerprint::from(Fingerprint::ZERO), }, Fingerprint::ZERO, @@ -799,7 +789,7 @@ impl DepGraphData { } } -impl DepGraph { +impl DepGraph { /// Checks whether a previous work product exists for `v` and, if /// so, return the path that leads to it. Used to skip doing work. pub fn previous_work_product(&self, v: &WorkProductId) -> Option { @@ -864,7 +854,7 @@ impl DepGraph { } } -impl DepGraphData { +impl DepGraphData { /// Try to mark a node index for the node dep_node. /// /// A node will have an index, when it's already been marked green, or when we can mark it @@ -1029,7 +1019,7 @@ impl DepGraphData { } } -impl DepGraph { +impl DepGraph { /// Returns true if the given node has been marked as red during the /// current compilation session. Used in various assertions pub fn is_red(&self, dep_node: &DepNode) -> bool { @@ -1163,8 +1153,8 @@ rustc_index::newtype_index! { /// `anon_node_to_index` and `data`, or `prev_index_to_index` and `data`. When /// manipulating both, we acquire `anon_node_to_index` or `prev_index_to_index` /// first, and `data` second. -pub(super) struct CurrentDepGraph { - encoder: GraphEncoder, +pub(super) struct CurrentDepGraph { + encoder: GraphEncoder, anon_node_to_index: ShardedHashMap, /// This is used to verify that fingerprints do not change between the creation of a node @@ -1202,7 +1192,7 @@ pub(super) struct CurrentDepGraph { pub(super) total_duplicate_read_count: AtomicU64, } -impl CurrentDepGraph { +impl CurrentDepGraph { fn new( session: &Session, prev_graph_node_count: usize, @@ -1436,7 +1426,7 @@ impl DepNodeColorMap { #[inline(never)] #[cold] -pub(crate) fn print_markframe_trace(graph: &DepGraph, frame: &MarkFrame<'_>) { +pub(crate) fn print_markframe_trace(graph: &DepGraph, frame: &MarkFrame<'_>) { let data = graph.data.as_ref().unwrap(); eprintln!("there was a panic while trying to force a dep node"); @@ -1456,7 +1446,7 @@ pub(crate) fn print_markframe_trace(graph: &DepGraph, frame: &MarkFr #[cold] #[inline(never)] -fn panic_on_forbidden_read(data: &DepGraphData, dep_node_index: DepNodeIndex) -> ! { +fn panic_on_forbidden_read(data: &DepGraphData, dep_node_index: DepNodeIndex) -> ! { // We have to do an expensive reverse-lookup of the DepNode that // corresponds to `dep_node_index`, but that's OK since we are about // to ICE anyway. diff --git a/compiler/rustc_middle/src/dep_graph/mod.rs b/compiler/rustc_middle/src/dep_graph/mod.rs index 611d76ef7e5ee..0c100b773392c 100644 --- a/compiler/rustc_middle/src/dep_graph/mod.rs +++ b/compiler/rustc_middle/src/dep_graph/mod.rs @@ -10,7 +10,7 @@ pub use self::dep_node::{ DepKind, DepNode, DepNodeKey, WorkProductId, dep_kind_from_label, dep_kinds, label_strs, }; pub use self::graph::{ - DepGraphData, DepNodeIndex, TaskDepsRef, WorkProduct, WorkProductMap, hash_result, + DepGraph, DepGraphData, DepNodeIndex, TaskDepsRef, WorkProduct, WorkProductMap, hash_result, }; use self::graph::{MarkFrame, print_markframe_trace}; pub use self::query::DepGraphQuery; @@ -34,7 +34,7 @@ pub trait DepContext: Copy { fn with_stable_hashing_context(self, f: impl FnOnce(StableHashingContext<'_>) -> R) -> R; /// Access the DepGraph. - fn dep_graph(&self) -> &graph::DepGraph; + fn dep_graph(&self) -> &DepGraph; /// Access the profiler. fn profiler(&self) -> &SelfProfilerRef; @@ -179,8 +179,6 @@ impl FingerprintStyle { } } -pub type DepGraph = graph::DepGraph; - pub type DepKindVTable<'tcx> = dep_node::DepKindVTable>; pub struct DepsType; diff --git a/compiler/rustc_middle/src/dep_graph/serialized.rs b/compiler/rustc_middle/src/dep_graph/serialized.rs index 3b5954fc8f94b..87b85226c9c3e 100644 --- a/compiler/rustc_middle/src/dep_graph/serialized.rs +++ b/compiler/rustc_middle/src/dep_graph/serialized.rs @@ -41,7 +41,6 @@ use std::cell::RefCell; use std::cmp::max; -use std::marker::PhantomData; use std::sync::Arc; use std::sync::atomic::Ordering; use std::{iter, mem, u64}; @@ -62,6 +61,7 @@ use tracing::{debug, instrument}; use super::graph::{CurrentDepGraph, DepNodeColorMap}; use super::query::DepGraphQuery; use super::{DepKind, DepNode, DepNodeIndex, Deps}; +use crate::dep_graph::DepsType; use crate::dep_graph::edges::EdgesVec; // The maximum value of `SerializedDepNodeIndex` leaves the upper two bits @@ -192,7 +192,7 @@ fn mask(bits: usize) -> usize { impl SerializedDepGraph { #[instrument(level = "debug", skip(d))] - pub fn decode(d: &mut MemDecoder<'_>) -> Arc { + pub fn decode(d: &mut MemDecoder<'_>) -> Arc { // The last 16 bytes are the node count and edge count. debug!("position: {:?}", d.position()); @@ -213,7 +213,10 @@ impl SerializedDepGraph { let graph_bytes = d.len() - (3 * IntEncodedWithFixedSize::ENCODED_SIZE) - d.position(); let mut nodes = IndexVec::from_elem_n( - DepNode { kind: D::DEP_KIND_NULL, hash: PackedFingerprint::from(Fingerprint::ZERO) }, + DepNode { + kind: DepsType::DEP_KIND_NULL, + hash: PackedFingerprint::from(Fingerprint::ZERO), + }, node_max, ); let mut fingerprints = IndexVec::from_elem_n(Fingerprint::ZERO, node_max); @@ -230,19 +233,21 @@ impl SerializedDepGraph { // least (34 byte header + 1 byte len + 64 bytes edge data), which is ~1%. A 2-byte leb128 // length is about the same fractional overhead and it amortizes for yet greater lengths. let mut edge_list_data = - Vec::with_capacity(graph_bytes - node_count * size_of::>()); + Vec::with_capacity(graph_bytes - node_count * size_of::()); for _ in 0..node_count { // Decode the header for this edge; the header packs together as many of the fixed-size // fields as possible to limit the number of times we update decoder state. - let node_header = - SerializedNodeHeader:: { bytes: d.read_array(), _marker: PhantomData }; + let node_header = SerializedNodeHeader { bytes: d.read_array() }; let index = node_header.index(); let node = &mut nodes[index]; // Make sure there's no duplicate indices in the dep graph. - assert!(node_header.node().kind != D::DEP_KIND_NULL && node.kind == D::DEP_KIND_NULL); + assert!( + node_header.node().kind != DepsType::DEP_KIND_NULL + && node.kind == DepsType::DEP_KIND_NULL + ); *node = node_header.node(); fingerprints[index] = node_header.fingerprint(); @@ -270,7 +275,7 @@ impl SerializedDepGraph { edge_list_data.extend(&[0u8; DEP_NODE_PAD]); // Read the number of each dep kind and use it to create an hash map with a suitable size. - let mut index: Vec<_> = (0..(D::DEP_KIND_MAX + 1)) + let mut index: Vec<_> = (0..(DepsType::DEP_KIND_MAX + 1)) .map(|_| UnhashMap::with_capacity_and_hasher(d.read_u32() as usize, Default::default())) .collect(); @@ -279,8 +284,10 @@ impl SerializedDepGraph { for (idx, node) in nodes.iter_enumerated() { if index[node.kind.as_usize()].insert(node.hash, idx).is_some() { // Empty nodes and side effect nodes can have duplicates - if node.kind != D::DEP_KIND_NULL && node.kind != D::DEP_KIND_SIDE_EFFECT { - let name = D::name(node.kind); + if node.kind != DepsType::DEP_KIND_NULL + && node.kind != DepsType::DEP_KIND_SIDE_EFFECT + { + let name = DepsType::name(node.kind); panic!( "Error: A dep graph node ({name}) does not have an unique index. \ Running a clean build on a nightly compiler with `-Z incremental-verify-ich` \ @@ -310,13 +317,12 @@ impl SerializedDepGraph { /// * The `DepKind`'s discriminant (a u16, but not all bits are used...) /// * The byte width of the encoded edges for this node /// * In whatever bits remain, the length of the edge list for this node, if it fits -struct SerializedNodeHeader { +struct SerializedNodeHeader { // 2 bytes for the DepNode // 4 bytes for the index // 16 for Fingerprint in DepNode // 16 for Fingerprint in NodeInfo bytes: [u8; 38], - _marker: PhantomData, } // The fields of a `SerializedNodeHeader`, this struct is an implementation detail and exists only @@ -337,11 +343,11 @@ struct Unpacked { // 0..M length of the edge // M..M+N bytes per index // M+N..16 kind -impl SerializedNodeHeader { +impl SerializedNodeHeader { const TOTAL_BITS: usize = size_of::() * 8; const LEN_BITS: usize = Self::TOTAL_BITS - Self::KIND_BITS - Self::WIDTH_BITS; const WIDTH_BITS: usize = DEP_NODE_WIDTH_BITS; - const KIND_BITS: usize = Self::TOTAL_BITS - D::DEP_KIND_MAX.leading_zeros() as usize; + const KIND_BITS: usize = Self::TOTAL_BITS - DepsType::DEP_KIND_MAX.leading_zeros() as usize; const MAX_INLINE_LEN: usize = (u16::MAX as usize >> (Self::TOTAL_BITS - Self::LEN_BITS)) - 1; #[inline] @@ -377,14 +383,14 @@ impl SerializedNodeHeader { #[cfg(debug_assertions)] { - let res = Self { bytes, _marker: PhantomData }; + let res = Self { bytes }; assert_eq!(fingerprint, res.fingerprint()); assert_eq!(*node, res.node()); if let Some(len) = res.len() { assert_eq!(edge_count, len as usize); } } - Self { bytes, _marker: PhantomData } + Self { bytes } } #[inline] @@ -451,15 +457,10 @@ struct NodeInfo { } impl NodeInfo { - fn encode(&self, e: &mut MemEncoder, index: DepNodeIndex) { + fn encode(&self, e: &mut MemEncoder, index: DepNodeIndex) { let NodeInfo { ref node, fingerprint, ref edges } = *self; - let header = SerializedNodeHeader::::new( - node, - index, - fingerprint, - edges.max_index(), - edges.len(), - ); + let header = + SerializedNodeHeader::new(node, index, fingerprint, edges.max_index(), edges.len()); e.write_array(header.bytes); if header.len().is_none() { @@ -480,7 +481,7 @@ impl NodeInfo { /// the previous dep graph and expects all edges to already have a new dep node index assigned. /// This avoids the overhead of constructing `EdgesVec`, which would be needed to call `encode`. #[inline] - fn encode_promoted( + fn encode_promoted( e: &mut MemEncoder, node: &DepNode, index: DepNodeIndex, @@ -496,7 +497,7 @@ impl NodeInfo { let edge_max = edges.clone().map(|i| colors.current(i).unwrap().as_u32()).max().unwrap_or(0); - let header = SerializedNodeHeader::::new(node, index, fingerprint, edge_max, edge_count); + let header = SerializedNodeHeader::new(node, index, fingerprint, edge_max, edge_count); e.write_array(header.bytes); if header.len().is_none() { @@ -543,16 +544,15 @@ struct LocalEncoderResult { kind_stats: Vec, } -struct EncoderState { +struct EncoderState { next_node_index: AtomicU64, previous: Arc, file: Lock>, local: WorkerLocal>, stats: Option>>, - marker: PhantomData, } -impl EncoderState { +impl EncoderState { fn new(encoder: FileEncoder, record_stats: bool, previous: Arc) -> Self { Self { previous, @@ -566,10 +566,9 @@ impl EncoderState { edge_count: 0, node_count: 0, encoder: MemEncoder::new(), - kind_stats: iter::repeat_n(0, D::DEP_KIND_MAX as usize + 1).collect(), + kind_stats: iter::repeat_n(0, DepsType::DEP_KIND_MAX as usize + 1).collect(), }) }), - marker: PhantomData, } } @@ -658,7 +657,7 @@ impl EncoderState { record_graph: &Option>, local: &mut LocalEncoderState, ) { - node.encode::(&mut local.encoder, index); + node.encode(&mut local.encoder, index); self.flush_mem_encoder(&mut *local); self.record( &node.node, @@ -687,7 +686,7 @@ impl EncoderState { ) { let node = self.previous.index_to_node(prev_index); let fingerprint = self.previous.fingerprint_by_index(prev_index); - let edge_count = NodeInfo::encode_promoted::( + let edge_count = NodeInfo::encode_promoted( &mut local.encoder, node, index, @@ -712,7 +711,7 @@ impl EncoderState { ); } - fn finish(&self, profiler: &SelfProfilerRef, current: &CurrentDepGraph) -> FileEncodeResult { + fn finish(&self, profiler: &SelfProfilerRef, current: &CurrentDepGraph) -> FileEncodeResult { // Prevent more indices from being allocated. self.next_node_index.store(u32::MAX as u64 + 1, Ordering::SeqCst); @@ -735,7 +734,8 @@ impl EncoderState { let mut encoder = self.file.lock().take().unwrap(); - let mut kind_stats: Vec = iter::repeat_n(0, D::DEP_KIND_MAX as usize + 1).collect(); + let mut kind_stats: Vec = + iter::repeat_n(0, DepsType::DEP_KIND_MAX as usize + 1).collect(); let mut node_max = 0; let mut node_count = 0; @@ -778,7 +778,7 @@ impl EncoderState { fn print_incremental_info( &self, - current: &CurrentDepGraph, + current: &CurrentDepGraph, total_node_count: usize, total_edge_count: usize, ) { @@ -835,13 +835,13 @@ impl EncoderState { } } -pub(crate) struct GraphEncoder { +pub(crate) struct GraphEncoder { profiler: SelfProfilerRef, - status: EncoderState, + status: EncoderState, record_graph: Option>, } -impl GraphEncoder { +impl GraphEncoder { pub(crate) fn new( sess: &Session, encoder: FileEncoder, @@ -945,7 +945,7 @@ impl GraphEncoder { } } - pub(crate) fn finish(&self, current: &CurrentDepGraph) -> FileEncodeResult { + pub(crate) fn finish(&self, current: &CurrentDepGraph) -> FileEncodeResult { let _prof_timer = self.profiler.generic_activity("incr_comp_encode_dep_graph_finish"); self.status.finish(&self.profiler, current) diff --git a/compiler/rustc_middle/src/verify_ich.rs b/compiler/rustc_middle/src/verify_ich.rs index c5aec73679ec2..9e7f26836521e 100644 --- a/compiler/rustc_middle/src/verify_ich.rs +++ b/compiler/rustc_middle/src/verify_ich.rs @@ -10,7 +10,7 @@ use crate::dep_graph::{DepContext, DepGraphData, SerializedDepNodeIndex}; #[instrument(skip(tcx, dep_graph_data, result, hash_result, format_value), level = "debug")] pub fn incremental_verify_ich( tcx: Tcx, - dep_graph_data: &DepGraphData, + dep_graph_data: &DepGraphData, result: &V, prev_index: SerializedDepNodeIndex, hash_result: Option, &V) -> Fingerprint>, diff --git a/compiler/rustc_query_impl/src/execution.rs b/compiler/rustc_query_impl/src/execution.rs index 89ec7ad9012a3..683e96f4d2571 100644 --- a/compiler/rustc_query_impl/src/execution.rs +++ b/compiler/rustc_query_impl/src/execution.rs @@ -5,7 +5,7 @@ use rustc_data_structures::hash_table::{Entry, HashTable}; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_data_structures::{outline, sharded, sync}; use rustc_errors::{Diag, FatalError, StashKey}; -use rustc_middle::dep_graph::{DepGraphData, DepNodeKey, DepsType, HasDepContext}; +use rustc_middle::dep_graph::{DepGraphData, DepNodeKey, HasDepContext}; use rustc_middle::query::{ ActiveKeyStatus, CycleError, CycleErrorHandling, QueryCache, QueryJob, QueryJobId, QueryLatch, QueryMode, QueryStackDeferred, QueryStackFrame, QueryState, @@ -438,7 +438,7 @@ fn execute_job_non_incr<'tcx, C: QueryCache, const FLAGS: QueryFlags>( fn execute_job_incr<'tcx, C: QueryCache, const FLAGS: QueryFlags>( query: SemiDynamicQueryDispatcher<'tcx, C, FLAGS>, qcx: QueryCtxt<'tcx>, - dep_graph_data: &DepGraphData, + dep_graph_data: &DepGraphData, key: C::Key, mut dep_node_opt: Option, job_id: QueryJobId, @@ -487,7 +487,7 @@ fn execute_job_incr<'tcx, C: QueryCache, const FLAGS: QueryFlags>( #[inline(always)] fn try_load_from_disk_and_cache_in_memory<'tcx, C: QueryCache, const FLAGS: QueryFlags>( query: SemiDynamicQueryDispatcher<'tcx, C, FLAGS>, - dep_graph_data: &DepGraphData, + dep_graph_data: &DepGraphData, qcx: QueryCtxt<'tcx>, key: &C::Key, dep_node: &DepNode, From 414be2e6ff398dd67aea1f6fffb1d335a23322bd Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 12 Feb 2026 10:35:23 +1100 Subject: [PATCH 3/5] Remove `Deps`. It's no longer needed. --- compiler/rustc_middle/src/dep_graph/graph.rs | 14 ++--- compiler/rustc_middle/src/dep_graph/mod.rs | 54 +++++-------------- .../rustc_middle/src/dep_graph/serialized.rs | 2 +- compiler/rustc_query_impl/src/plumbing.rs | 5 +- 4 files changed, 24 insertions(+), 51 deletions(-) diff --git a/compiler/rustc_middle/src/dep_graph/graph.rs b/compiler/rustc_middle/src/dep_graph/graph.rs index 0ee1ee44fd1cb..5d3d09ded2124 100644 --- a/compiler/rustc_middle/src/dep_graph/graph.rs +++ b/compiler/rustc_middle/src/dep_graph/graph.rs @@ -25,7 +25,7 @@ use {super::debug::EdgeFilter, std::env}; use super::query::DepGraphQuery; use super::serialized::{GraphEncoder, SerializedDepGraph, SerializedDepNodeIndex}; -use super::{DepContext, DepKind, DepNode, Deps, DepsType, HasDepContext, WorkProductId}; +use super::{DepContext, DepKind, DepNode, DepsType, HasDepContext, WorkProductId}; use crate::dep_graph::edges::EdgesVec; use crate::ty::TyCtxt; use crate::verify_ich::incremental_verify_ich; @@ -252,7 +252,7 @@ impl DepGraph { } #[inline(always)] - pub fn with_task, A: Debug, R>( + pub fn with_task( &self, key: DepNode, cx: Ctxt, @@ -266,7 +266,7 @@ impl DepGraph { } } - pub fn with_anon_task, OP, R>( + pub fn with_anon_task( &self, cx: Tcx, dep_kind: DepKind, @@ -315,7 +315,7 @@ impl DepGraphData { /// /// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/queries/incremental-compilation.html #[inline(always)] - pub fn with_task, A: Debug, R>( + pub fn with_task( &self, key: DepNode, cx: Ctxt, @@ -369,7 +369,7 @@ impl DepGraphData { /// FIXME: This could perhaps return a `WithDepNode` to ensure that the /// user of this function actually performs the read; we'll have to see /// how to make that work with `anon` in `execute_job_incr`, though. - pub fn with_anon_task_inner, OP, R>( + pub fn with_anon_task_inner( &self, cx: Tcx, dep_kind: DepKind, @@ -438,7 +438,7 @@ impl DepGraphData { } /// Intern the new `DepNode` with the dependencies up-to-now. - fn hash_result_and_alloc_node, R>( + fn hash_result_and_alloc_node( &self, cx: &Ctxt, node: DepNode, @@ -553,7 +553,7 @@ impl DepGraph { /// FIXME: If the code is changed enough for this node to be marked before requiring the /// caller's node, we suppose that those changes will be enough to mark this node red and /// force a recomputation using the "normal" way. - pub fn with_feed_task, R>( + pub fn with_feed_task( &self, node: DepNode, cx: Ctxt, diff --git a/compiler/rustc_middle/src/dep_graph/mod.rs b/compiler/rustc_middle/src/dep_graph/mod.rs index 0c100b773392c..3b04ba4ca2768 100644 --- a/compiler/rustc_middle/src/dep_graph/mod.rs +++ b/compiler/rustc_middle/src/dep_graph/mod.rs @@ -1,7 +1,6 @@ use std::panic; use rustc_data_structures::profiling::SelfProfilerRef; -use rustc_data_structures::sync::DynSync; use rustc_query_system::ich::StableHashingContext; use rustc_session::Session; use tracing::instrument; @@ -28,8 +27,6 @@ mod query; mod serialized; pub trait DepContext: Copy { - type Deps: Deps; - /// Create a hashing context for hashing new results. fn with_stable_hashing_context(self, f: impl FnOnce(StableHashingContext<'_>) -> R) -> R; @@ -96,45 +93,13 @@ pub trait DepContext: Copy { fn with_reduced_queries(self, _: impl FnOnce() -> T) -> T; } -pub trait Deps: DynSync { - /// Execute the operation with provided dependencies. - fn with_deps(deps: TaskDepsRef<'_>, op: OP) -> R - where - OP: FnOnce() -> R; - - /// Access dependencies from current implicit context. - fn read_deps(op: OP) - where - OP: for<'a> FnOnce(TaskDepsRef<'a>); - - fn name(dep_kind: DepKind) -> &'static str; - - /// We use this for most things when incr. comp. is turned off. - const DEP_KIND_NULL: DepKind; - - /// We use this to create a forever-red node. - const DEP_KIND_RED: DepKind; - - /// We use this to create a side effect node. - const DEP_KIND_SIDE_EFFECT: DepKind; - - /// We use this to create the anon node with zero dependencies. - const DEP_KIND_ANON_ZERO_DEPS: DepKind; - - /// This is the highest value a `DepKind` can have. It's used during encoding to - /// pack information into the unused bits. - const DEP_KIND_MAX: u16; -} - pub trait HasDepContext: Copy { - type Deps: self::Deps; - type DepContext: self::DepContext; + type DepContext: self::DepContext; fn dep_context(&self) -> &Self::DepContext; } impl HasDepContext for T { - type Deps = T::Deps; type DepContext = Self; fn dep_context(&self) -> &Self::DepContext { @@ -143,7 +108,6 @@ impl HasDepContext for T { } impl HasDepContext for (T, Q) { - type Deps = T::Deps; type DepContext = T::DepContext; fn dep_context(&self) -> &Self::DepContext { @@ -183,7 +147,8 @@ pub type DepKindVTable<'tcx> = dep_node::DepKindVTable>; pub struct DepsType; -impl Deps for DepsType { +impl DepsType { + /// Execute the operation with provided dependencies. fn with_deps(task_deps: TaskDepsRef<'_>, op: OP) -> R where OP: FnOnce() -> R, @@ -195,6 +160,7 @@ impl Deps for DepsType { }) } + /// Access dependencies from current implicit context. fn read_deps(op: OP) where OP: for<'a> FnOnce(TaskDepsRef<'a>), @@ -209,16 +175,24 @@ impl Deps for DepsType { dep_node::DEP_KIND_NAMES[dep_kind.as_usize()] } + /// We use this for most things when incr. comp. is turned off. const DEP_KIND_NULL: DepKind = dep_kinds::Null; + + /// We use this to create a forever-red node. const DEP_KIND_RED: DepKind = dep_kinds::Red; + + /// We use this to create a side effect node. const DEP_KIND_SIDE_EFFECT: DepKind = dep_kinds::SideEffect; + + /// We use this to create the anon node with zero dependencies. const DEP_KIND_ANON_ZERO_DEPS: DepKind = dep_kinds::AnonZeroDeps; + + /// This is the highest value a `DepKind` can have. It's used during encoding to + /// pack information into the unused bits. const DEP_KIND_MAX: u16 = dep_node::DEP_KIND_VARIANTS - 1; } impl<'tcx> DepContext for TyCtxt<'tcx> { - type Deps = DepsType; - #[inline] fn with_stable_hashing_context(self, f: impl FnOnce(StableHashingContext<'_>) -> R) -> R { TyCtxt::with_stable_hashing_context(self, f) diff --git a/compiler/rustc_middle/src/dep_graph/serialized.rs b/compiler/rustc_middle/src/dep_graph/serialized.rs index 87b85226c9c3e..d2938373f5448 100644 --- a/compiler/rustc_middle/src/dep_graph/serialized.rs +++ b/compiler/rustc_middle/src/dep_graph/serialized.rs @@ -60,7 +60,7 @@ use tracing::{debug, instrument}; use super::graph::{CurrentDepGraph, DepNodeColorMap}; use super::query::DepGraphQuery; -use super::{DepKind, DepNode, DepNodeIndex, Deps}; +use super::{DepKind, DepNode, DepNodeIndex}; use crate::dep_graph::DepsType; use crate::dep_graph::edges::EdgesVec; diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index 911d38d0993e9..50838daf01123 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -15,8 +15,8 @@ use rustc_middle::bug; #[expect(unused_imports, reason = "used by doc comments")] use rustc_middle::dep_graph::DepKindVTable; use rustc_middle::dep_graph::{ - self, DepContext, DepNode, DepNodeIndex, DepNodeKey, DepsType, HasDepContext, - SerializedDepNodeIndex, dep_kinds, + self, DepContext, DepNode, DepNodeIndex, DepNodeKey, HasDepContext, SerializedDepNodeIndex, + dep_kinds, }; use rustc_middle::query::on_disk_cache::{ AbsoluteBytePos, CacheDecoder, CacheEncoder, EncodedDepNodeIndex, @@ -142,7 +142,6 @@ impl<'tcx> QueryCtxt<'tcx> { } impl<'tcx> HasDepContext for QueryCtxt<'tcx> { - type Deps = DepsType; type DepContext = TyCtxt<'tcx>; #[inline] From 7c877d994bc7b062326e8301646a4da045e5e5ba Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 12 Feb 2026 11:25:32 +1100 Subject: [PATCH 4/5] Remove `DepContext`. It's no longer needed now that we can access `TyCtxt` directly. --- compiler/rustc_interface/src/callbacks.rs | 2 +- .../rustc_middle/src/dep_graph/dep_node.rs | 52 +++--- .../src/dep_graph/dep_node_key.rs | 20 +-- compiler/rustc_middle/src/dep_graph/graph.rs | 42 ++--- compiler/rustc_middle/src/dep_graph/mod.rs | 151 ++++++------------ compiler/rustc_middle/src/query/inner.rs | 2 +- compiler/rustc_middle/src/verify_ich.rs | 34 ++-- .../rustc_query_impl/src/dep_kind_vtables.rs | 3 +- compiler/rustc_query_impl/src/execution.rs | 4 +- compiler/rustc_query_impl/src/job.rs | 1 - compiler/rustc_query_impl/src/plumbing.rs | 13 +- .../src/error_reporting/infer/mod.rs | 11 +- 12 files changed, 133 insertions(+), 202 deletions(-) diff --git a/compiler/rustc_interface/src/callbacks.rs b/compiler/rustc_interface/src/callbacks.rs index 49c682ea93f8d..05ddfd1f107a5 100644 --- a/compiler/rustc_interface/src/callbacks.rs +++ b/compiler/rustc_interface/src/callbacks.rs @@ -13,7 +13,7 @@ use std::fmt; use rustc_errors::{DiagInner, TRACK_DIAGNOSTIC}; use rustc_middle::dep_graph::dep_node::default_dep_kind_debug; -use rustc_middle::dep_graph::{DepContext, DepKind, DepNode, TaskDepsRef}; +use rustc_middle::dep_graph::{DepKind, DepNode, TaskDepsRef}; use rustc_middle::ty::tls; fn track_span_parent(def_id: rustc_span::def_id::LocalDefId) { diff --git a/compiler/rustc_middle/src/dep_graph/dep_node.rs b/compiler/rustc_middle/src/dep_graph/dep_node.rs index 2d198b65d1285..14e43e045e82d 100644 --- a/compiler/rustc_middle/src/dep_graph/dep_node.rs +++ b/compiler/rustc_middle/src/dep_graph/dep_node.rs @@ -67,7 +67,7 @@ use rustc_macros::{Decodable, Encodable}; use rustc_query_system::ich::StableHashingContext; use rustc_span::Symbol; -use super::{DepContext, FingerprintStyle, SerializedDepNodeIndex}; +use super::{FingerprintStyle, SerializedDepNodeIndex}; use crate::mir::mono::MonoItem; use crate::ty::TyCtxt; @@ -117,18 +117,14 @@ impl DepNode { /// Creates a new, parameterless DepNode. This method will assert /// that the DepNode corresponding to the given DepKind actually /// does not require any parameters. - pub fn new_no_params(tcx: Tcx, kind: DepKind) -> DepNode - where - Tcx: super::DepContext, - { + pub fn new_no_params<'tcx>(tcx: TyCtxt<'tcx>, kind: DepKind) -> DepNode { debug_assert_eq!(tcx.fingerprint_style(kind), FingerprintStyle::Unit); DepNode { kind, hash: Fingerprint::ZERO.into() } } - pub fn construct(tcx: Tcx, kind: DepKind, arg: &Key) -> DepNode + pub fn construct<'tcx, Key>(tcx: TyCtxt<'tcx>, kind: DepKind, arg: &Key) -> DepNode where - Tcx: super::DepContext, - Key: DepNodeKey, + Key: DepNodeKey<'tcx>, { let hash = arg.to_fingerprint(tcx); let dep_node = DepNode { kind, hash: hash.into() }; @@ -136,10 +132,10 @@ impl DepNode { #[cfg(debug_assertions)] { if !tcx.fingerprint_style(kind).reconstructible() - && (tcx.sess().opts.unstable_opts.incremental_info - || tcx.sess().opts.unstable_opts.query_dep_graph) + && (tcx.sess.opts.unstable_opts.incremental_info + || tcx.sess.opts.unstable_opts.query_dep_graph) { - tcx.dep_graph().register_dep_node_debug_str(dep_node, || arg.to_debug_str(tcx)); + tcx.dep_graph.register_dep_node_debug_str(dep_node, || arg.to_debug_str(tcx)); } } @@ -149,10 +145,11 @@ impl DepNode { /// Construct a DepNode from the given DepKind and DefPathHash. This /// method will assert that the given DepKind actually requires a /// single DefId/DefPathHash parameter. - pub fn from_def_path_hash(tcx: Tcx, def_path_hash: DefPathHash, kind: DepKind) -> Self - where - Tcx: super::DepContext, - { + pub fn from_def_path_hash<'tcx>( + tcx: TyCtxt<'tcx>, + def_path_hash: DefPathHash, + kind: DepKind, + ) -> Self { debug_assert!(tcx.fingerprint_style(kind) == FingerprintStyle::DefPathHash); DepNode { kind, hash: def_path_hash.0.into() } } @@ -172,14 +169,14 @@ impl fmt::Debug for DepNode { } /// Trait for query keys as seen by dependency-node tracking. -pub trait DepNodeKey: fmt::Debug + Sized { +pub trait DepNodeKey<'tcx>: fmt::Debug + Sized { fn fingerprint_style() -> FingerprintStyle; /// This method turns a query key into an opaque `Fingerprint` to be used /// in `DepNode`. - fn to_fingerprint(&self, _: Tcx) -> Fingerprint; + fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint; - fn to_debug_str(&self, tcx: Tcx) -> String; + fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String; /// This method tries to recover the query key from the given `DepNode`, /// something which is needed when forcing `DepNode`s during red-green @@ -187,11 +184,11 @@ pub trait DepNodeKey: fmt::Debug + Sized { /// `fingerprint_style()` is not `FingerprintStyle::Opaque`. /// It is always valid to return `None` here, in which case incremental /// compilation will treat the query as having changed instead of forcing it. - fn recover(tcx: Tcx, dep_node: &DepNode) -> Option; + fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option; } // Blanket impl of `DepNodeKey`, which is specialized by other impls elsewhere. -impl DepNodeKey for T +impl<'tcx, T> DepNodeKey<'tcx> for T where T: for<'a> HashStable> + fmt::Debug, { @@ -201,7 +198,7 @@ where } #[inline(always)] - default fn to_fingerprint(&self, tcx: Tcx) -> Fingerprint { + default fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint { tcx.with_stable_hashing_context(|mut hcx| { let mut hasher = StableHasher::new(); self.hash_stable(&mut hcx, &mut hasher); @@ -210,7 +207,7 @@ where } #[inline(always)] - default fn to_debug_str(&self, tcx: Tcx) -> String { + default fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String { // Make sure to print dep node params with reduced queries since printing // may themselves call queries, which may lead to (possibly untracked!) // query cycles. @@ -218,7 +215,7 @@ where } #[inline(always)] - default fn recover(_: Tcx, _: &DepNode) -> Option { + default fn recover(_: TyCtxt<'tcx>, _: &DepNode) -> Option { None } } @@ -228,7 +225,7 @@ where /// Information is retrieved by indexing the `DEP_KINDS` array using the integer value /// of the `DepKind`. Overall, this allows to implement `DepContext` using this manual /// jump table instead of large matches. -pub struct DepKindVTable { +pub struct DepKindVTable<'tcx> { /// Anonymous queries cannot be replayed from one compiler invocation to the next. /// When their result is needed, it is recomputed. They are useful for fine-grained /// dependency tracking, and caching within one compiler invocation. @@ -279,11 +276,12 @@ pub struct DepKindVTable { /// with kind `MirValidated`, we know that the GUID/fingerprint of the `DepNode` /// is actually a `DefPathHash`, and can therefore just look up the corresponding /// `DefId` in `tcx.def_path_hash_to_def_id`. - pub force_from_dep_node: - Option bool>, + pub force_from_dep_node: Option< + fn(tcx: TyCtxt<'tcx>, dep_node: DepNode, prev_index: SerializedDepNodeIndex) -> bool, + >, /// Invoke a query to put the on-disk cached value in memory. - pub try_load_from_on_disk_cache: Option, + pub try_load_from_on_disk_cache: Option, DepNode)>, /// The name of this dep kind. pub name: &'static &'static str, diff --git a/compiler/rustc_middle/src/dep_graph/dep_node_key.rs b/compiler/rustc_middle/src/dep_graph/dep_node_key.rs index 1b9b02b67fad2..92c135a6e7fde 100644 --- a/compiler/rustc_middle/src/dep_graph/dep_node_key.rs +++ b/compiler/rustc_middle/src/dep_graph/dep_node_key.rs @@ -3,10 +3,10 @@ use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId, LocalModDefId, use rustc_hir::definitions::DefPathHash; use rustc_hir::{HirId, ItemLocalId, OwnerId}; -use crate::dep_graph::{DepContext, DepNode, DepNodeKey, FingerprintStyle}; +use crate::dep_graph::{DepNode, DepNodeKey, FingerprintStyle}; use crate::ty::TyCtxt; -impl<'tcx> DepNodeKey> for () { +impl<'tcx> DepNodeKey<'tcx> for () { #[inline(always)] fn fingerprint_style() -> FingerprintStyle { FingerprintStyle::Unit @@ -23,7 +23,7 @@ impl<'tcx> DepNodeKey> for () { } } -impl<'tcx> DepNodeKey> for DefId { +impl<'tcx> DepNodeKey<'tcx> for DefId { #[inline(always)] fn fingerprint_style() -> FingerprintStyle { FingerprintStyle::DefPathHash @@ -45,7 +45,7 @@ impl<'tcx> DepNodeKey> for DefId { } } -impl<'tcx> DepNodeKey> for LocalDefId { +impl<'tcx> DepNodeKey<'tcx> for LocalDefId { #[inline(always)] fn fingerprint_style() -> FingerprintStyle { FingerprintStyle::DefPathHash @@ -67,7 +67,7 @@ impl<'tcx> DepNodeKey> for LocalDefId { } } -impl<'tcx> DepNodeKey> for OwnerId { +impl<'tcx> DepNodeKey<'tcx> for OwnerId { #[inline(always)] fn fingerprint_style() -> FingerprintStyle { FingerprintStyle::DefPathHash @@ -89,7 +89,7 @@ impl<'tcx> DepNodeKey> for OwnerId { } } -impl<'tcx> DepNodeKey> for CrateNum { +impl<'tcx> DepNodeKey<'tcx> for CrateNum { #[inline(always)] fn fingerprint_style() -> FingerprintStyle { FingerprintStyle::DefPathHash @@ -112,7 +112,7 @@ impl<'tcx> DepNodeKey> for CrateNum { } } -impl<'tcx> DepNodeKey> for (DefId, DefId) { +impl<'tcx> DepNodeKey<'tcx> for (DefId, DefId) { #[inline(always)] fn fingerprint_style() -> FingerprintStyle { FingerprintStyle::Opaque @@ -139,7 +139,7 @@ impl<'tcx> DepNodeKey> for (DefId, DefId) { } } -impl<'tcx> DepNodeKey> for HirId { +impl<'tcx> DepNodeKey<'tcx> for HirId { #[inline(always)] fn fingerprint_style() -> FingerprintStyle { FingerprintStyle::HirId @@ -182,7 +182,7 @@ impl<'tcx> DepNodeKey> for HirId { } } -impl<'tcx> DepNodeKey> for ModDefId { +impl<'tcx> DepNodeKey<'tcx> for ModDefId { #[inline(always)] fn fingerprint_style() -> FingerprintStyle { FingerprintStyle::DefPathHash @@ -204,7 +204,7 @@ impl<'tcx> DepNodeKey> for ModDefId { } } -impl<'tcx> DepNodeKey> for LocalModDefId { +impl<'tcx> DepNodeKey<'tcx> for LocalModDefId { #[inline(always)] fn fingerprint_style() -> FingerprintStyle { FingerprintStyle::DefPathHash diff --git a/compiler/rustc_middle/src/dep_graph/graph.rs b/compiler/rustc_middle/src/dep_graph/graph.rs index 5d3d09ded2124..d0ac398523184 100644 --- a/compiler/rustc_middle/src/dep_graph/graph.rs +++ b/compiler/rustc_middle/src/dep_graph/graph.rs @@ -25,7 +25,7 @@ use {super::debug::EdgeFilter, std::env}; use super::query::DepGraphQuery; use super::serialized::{GraphEncoder, SerializedDepGraph, SerializedDepNodeIndex}; -use super::{DepContext, DepKind, DepNode, DepsType, HasDepContext, WorkProductId}; +use super::{DepKind, DepNode, DepsType, HasDepContext, WorkProductId}; use crate::dep_graph::edges::EdgesVec; use crate::ty::TyCtxt; use crate::verify_ich::incremental_verify_ich; @@ -62,7 +62,7 @@ impl From for QueryInvocationId { } } -pub struct MarkFrame<'a> { +pub(crate) struct MarkFrame<'a> { index: SerializedDepNodeIndex, parent: Option<&'a MarkFrame<'a>>, } @@ -252,7 +252,7 @@ impl DepGraph { } #[inline(always)] - pub fn with_task( + pub fn with_task<'tcx, Ctxt: HasDepContext<'tcx>, A: Debug, R>( &self, key: DepNode, cx: Ctxt, @@ -266,9 +266,9 @@ impl DepGraph { } } - pub fn with_anon_task( + pub fn with_anon_task<'tcx, OP, R>( &self, - cx: Tcx, + cx: TyCtxt<'tcx>, dep_kind: DepKind, op: OP, ) -> (R, DepNodeIndex) @@ -315,7 +315,7 @@ impl DepGraphData { /// /// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/queries/incremental-compilation.html #[inline(always)] - pub fn with_task( + pub fn with_task<'tcx, Ctxt: HasDepContext<'tcx>, A: Debug, R>( &self, key: DepNode, cx: Ctxt, @@ -329,7 +329,7 @@ impl DepGraphData { // 2. Two distinct query keys get mapped to the same `DepNode` // (see for example #48923). self.assert_dep_node_not_yet_allocated_in_current_session( - cx.dep_context().sess(), + cx.dep_context().sess, &key, || { format!( @@ -352,8 +352,8 @@ impl DepGraphData { (with_deps(TaskDepsRef::Allow(&task_deps)), task_deps.into_inner().reads) }; - let dcx = cx.dep_context(); - let dep_node_index = self.hash_result_and_alloc_node(dcx, key, edges, &result, hash_result); + let dep_node_index = + self.hash_result_and_alloc_node(cx.dep_context(), key, edges, &result, hash_result); (result, dep_node_index) } @@ -369,9 +369,9 @@ impl DepGraphData { /// FIXME: This could perhaps return a `WithDepNode` to ensure that the /// user of this function actually performs the read; we'll have to see /// how to make that work with `anon` in `execute_job_incr`, though. - pub fn with_anon_task_inner( + pub fn with_anon_task_inner<'tcx, OP, R>( &self, - cx: Tcx, + cx: TyCtxt<'tcx>, dep_kind: DepKind, op: OP, ) -> (R, DepNodeIndex) @@ -438,17 +438,17 @@ impl DepGraphData { } /// Intern the new `DepNode` with the dependencies up-to-now. - fn hash_result_and_alloc_node( + fn hash_result_and_alloc_node<'tcx, R>( &self, - cx: &Ctxt, + tcx: TyCtxt<'tcx>, node: DepNode, edges: EdgesVec, result: &R, hash_result: Option, &R) -> Fingerprint>, ) -> DepNodeIndex { - let hashing_timer = cx.profiler().incr_result_hashing(); + let hashing_timer = tcx.prof.incr_result_hashing(); let current_fingerprint = hash_result.map(|hash_result| { - cx.with_stable_hashing_context(|mut hcx| hash_result(&mut hcx, result)) + tcx.with_stable_hashing_context(|mut hcx| hash_result(&mut hcx, result)) }); let dep_node_index = self.alloc_and_color_node(node, edges, current_fingerprint); hashing_timer.finish_with_query_invocation_id(dep_node_index.into()); @@ -553,10 +553,10 @@ impl DepGraph { /// FIXME: If the code is changed enough for this node to be marked before requiring the /// caller's node, we suppose that those changes will be enough to mark this node red and /// force a recomputation using the "normal" way. - pub fn with_feed_task( + pub fn with_feed_task<'tcx, R>( &self, node: DepNode, - cx: Ctxt, + tcx: TyCtxt<'tcx>, result: &R, hash_result: Option, &R) -> Fingerprint>, format_value_fn: fn(&R) -> String, @@ -572,7 +572,7 @@ impl DepGraph { let dep_node_index = data.colors.current(prev_index); if let Some(dep_node_index) = dep_node_index { incremental_verify_ich( - cx, + tcx, data, result, prev_index, @@ -605,7 +605,7 @@ impl DepGraph { } }); - data.hash_result_and_alloc_node(&cx, node, edges, result, hash_result) + data.hash_result_and_alloc_node(tcx, node, edges, result, hash_result) } else { // Incremental compilation is turned off. We just execute the task // without tracking. We still provide a dep-node index that uniquely @@ -1051,8 +1051,8 @@ impl DepGraph { /// /// This method will only load queries that will end up in the disk cache. /// Other queries will not be executed. - pub fn exec_cache_promotions(&self, tcx: Tcx) { - let _prof_timer = tcx.profiler().generic_activity("incr_comp_query_cache_promotion"); + pub fn exec_cache_promotions<'tcx>(&self, tcx: TyCtxt<'tcx>) { + let _prof_timer = tcx.prof.generic_activity("incr_comp_query_cache_promotion"); let data = self.data.as_ref().unwrap(); for prev_index in data.colors.values.indices() { diff --git a/compiler/rustc_middle/src/dep_graph/mod.rs b/compiler/rustc_middle/src/dep_graph/mod.rs index 3b04ba4ca2768..ea347f53ac448 100644 --- a/compiler/rustc_middle/src/dep_graph/mod.rs +++ b/compiler/rustc_middle/src/dep_graph/mod.rs @@ -1,12 +1,10 @@ use std::panic; -use rustc_data_structures::profiling::SelfProfilerRef; -use rustc_query_system::ich::StableHashingContext; -use rustc_session::Session; use tracing::instrument; pub use self::dep_node::{ - DepKind, DepNode, DepNodeKey, WorkProductId, dep_kind_from_label, dep_kinds, label_strs, + DepKind, DepKindVTable, DepNode, DepNodeKey, WorkProductId, dep_kind_from_label, dep_kinds, + label_strs, }; pub use self::graph::{ DepGraph, DepGraphData, DepNodeIndex, TaskDepsRef, WorkProduct, WorkProductMap, hash_result, @@ -26,91 +24,18 @@ mod graph; mod query; mod serialized; -pub trait DepContext: Copy { - /// Create a hashing context for hashing new results. - fn with_stable_hashing_context(self, f: impl FnOnce(StableHashingContext<'_>) -> R) -> R; - - /// Access the DepGraph. - fn dep_graph(&self) -> &DepGraph; - - /// Access the profiler. - fn profiler(&self) -> &SelfProfilerRef; - - /// Access the compiler session. - fn sess(&self) -> &Session; - - fn dep_kind_vtable(&self, dep_node: DepKind) -> &dep_node::DepKindVTable; - - #[inline(always)] - fn fingerprint_style(self, kind: DepKind) -> FingerprintStyle { - self.dep_kind_vtable(kind).fingerprint_style - } - - #[inline(always)] - /// Return whether this kind always require evaluation. - // FIXME: remove this in favour of the version on `TyCtxt`. - fn is_eval_always(self, kind: DepKind) -> bool { - self.dep_kind_vtable(kind).is_eval_always - } - - /// Try to force a dep node to execute and see if it's green. - /// - /// Returns true if the query has actually been forced. It is valid that a query - /// fails to be forced, e.g. when the query key cannot be reconstructed from the - /// dep-node or when the query kind outright does not support it. - #[inline] - #[instrument(skip(self, frame), level = "debug")] - fn try_force_from_dep_node( - self, - dep_node: DepNode, - prev_index: SerializedDepNodeIndex, - frame: &MarkFrame<'_>, - ) -> bool { - if let Some(force_fn) = self.dep_kind_vtable(dep_node.kind).force_from_dep_node { - match panic::catch_unwind(panic::AssertUnwindSafe(|| { - force_fn(self, dep_node, prev_index) - })) { - Err(value) => { - if !value.is::() { - print_markframe_trace(self.dep_graph(), frame); - } - panic::resume_unwind(value) - } - Ok(query_has_been_forced) => query_has_been_forced, - } - } else { - false - } - } - - /// Load data from the on-disk cache. - fn try_load_from_on_disk_cache(self, dep_node: &DepNode) { - if let Some(try_load_fn) = self.dep_kind_vtable(dep_node.kind).try_load_from_on_disk_cache { - try_load_fn(self, *dep_node) - } - } - - fn with_reduced_queries(self, _: impl FnOnce() -> T) -> T; +pub trait HasDepContext<'tcx>: Copy { + fn dep_context(&self) -> TyCtxt<'tcx>; } -pub trait HasDepContext: Copy { - type DepContext: self::DepContext; - - fn dep_context(&self) -> &Self::DepContext; -} - -impl HasDepContext for T { - type DepContext = Self; - - fn dep_context(&self) -> &Self::DepContext { - self +impl<'tcx> HasDepContext<'tcx> for TyCtxt<'tcx> { + fn dep_context(&self) -> TyCtxt<'tcx> { + *self } } -impl HasDepContext for (T, Q) { - type DepContext = T::DepContext; - - fn dep_context(&self) -> &Self::DepContext { +impl<'tcx, T: HasDepContext<'tcx>, Q: Copy> HasDepContext<'tcx> for (T, Q) { + fn dep_context(&self) -> TyCtxt<'tcx> { self.0.dep_context() } } @@ -143,8 +68,6 @@ impl FingerprintStyle { } } -pub type DepKindVTable<'tcx> = dep_node::DepKindVTable>; - pub struct DepsType; impl DepsType { @@ -192,33 +115,55 @@ impl DepsType { const DEP_KIND_MAX: u16 = dep_node::DEP_KIND_VARIANTS - 1; } -impl<'tcx> DepContext for TyCtxt<'tcx> { +impl<'tcx> TyCtxt<'tcx> { #[inline] - fn with_stable_hashing_context(self, f: impl FnOnce(StableHashingContext<'_>) -> R) -> R { - TyCtxt::with_stable_hashing_context(self, f) - } - - #[inline] - fn dep_graph(&self) -> &DepGraph { - &self.dep_graph + pub fn dep_kind_vtable(self, dk: DepKind) -> &'tcx DepKindVTable<'tcx> { + &self.dep_kind_vtables[dk.as_usize()] } - #[inline(always)] - fn profiler(&self) -> &SelfProfilerRef { - &self.prof + fn with_reduced_queries(self, f: impl FnOnce() -> T) -> T { + with_reduced_queries!(f()) } #[inline(always)] - fn sess(&self) -> &Session { - self.sess + pub fn fingerprint_style(self, kind: DepKind) -> FingerprintStyle { + self.dep_kind_vtable(kind).fingerprint_style } + /// Try to force a dep node to execute and see if it's green. + /// + /// Returns true if the query has actually been forced. It is valid that a query + /// fails to be forced, e.g. when the query key cannot be reconstructed from the + /// dep-node or when the query kind outright does not support it. #[inline] - fn dep_kind_vtable(&self, dk: DepKind) -> &DepKindVTable<'tcx> { - &self.dep_kind_vtables[dk.as_usize()] + #[instrument(skip(self, frame), level = "debug")] + fn try_force_from_dep_node( + self, + dep_node: DepNode, + prev_index: SerializedDepNodeIndex, + frame: &MarkFrame<'_>, + ) -> bool { + if let Some(force_fn) = self.dep_kind_vtable(dep_node.kind).force_from_dep_node { + match panic::catch_unwind(panic::AssertUnwindSafe(|| { + force_fn(self, dep_node, prev_index) + })) { + Err(value) => { + if !value.is::() { + print_markframe_trace(&self.dep_graph, frame); + } + panic::resume_unwind(value) + } + Ok(query_has_been_forced) => query_has_been_forced, + } + } else { + false + } } - fn with_reduced_queries(self, f: impl FnOnce() -> T) -> T { - with_reduced_queries!(f()) + /// Load data from the on-disk cache. + fn try_load_from_on_disk_cache(self, dep_node: &DepNode) { + if let Some(try_load_fn) = self.dep_kind_vtable(dep_node.kind).try_load_from_on_disk_cache { + try_load_fn(self, *dep_node) + } } } diff --git a/compiler/rustc_middle/src/query/inner.rs b/compiler/rustc_middle/src/query/inner.rs index b977172fcf9d2..0b575b536cb6e 100644 --- a/compiler/rustc_middle/src/query/inner.rs +++ b/compiler/rustc_middle/src/query/inner.rs @@ -105,7 +105,7 @@ pub(crate) fn query_feed<'tcx, Cache>( value: Cache::Value, ) where Cache: QueryCache, - Cache::Key: DepNodeKey>, + Cache::Key: DepNodeKey<'tcx>, { let format_value = query_vtable.format_value; diff --git a/compiler/rustc_middle/src/verify_ich.rs b/compiler/rustc_middle/src/verify_ich.rs index 9e7f26836521e..290786d439d4e 100644 --- a/compiler/rustc_middle/src/verify_ich.rs +++ b/compiler/rustc_middle/src/verify_ich.rs @@ -4,20 +4,19 @@ use rustc_data_structures::fingerprint::Fingerprint; use rustc_query_system::ich::StableHashingContext; use tracing::instrument; -use crate::dep_graph::{DepContext, DepGraphData, SerializedDepNodeIndex}; +use crate::dep_graph::{DepGraphData, SerializedDepNodeIndex}; +use crate::ty::TyCtxt; #[inline] #[instrument(skip(tcx, dep_graph_data, result, hash_result, format_value), level = "debug")] -pub fn incremental_verify_ich( - tcx: Tcx, +pub fn incremental_verify_ich<'tcx, V>( + tcx: TyCtxt<'tcx>, dep_graph_data: &DepGraphData, result: &V, prev_index: SerializedDepNodeIndex, hash_result: Option, &V) -> Fingerprint>, format_value: fn(&V) -> String, -) where - Tcx: DepContext, -{ +) { if !dep_graph_data.is_index_green(prev_index) { incremental_verify_ich_not_green(tcx, prev_index) } @@ -35,13 +34,10 @@ pub fn incremental_verify_ich( #[cold] #[inline(never)] -fn incremental_verify_ich_not_green(tcx: Tcx, prev_index: SerializedDepNodeIndex) -where - Tcx: DepContext, -{ +fn incremental_verify_ich_not_green<'tcx>(tcx: TyCtxt<'tcx>, prev_index: SerializedDepNodeIndex) { panic!( "fingerprint for green query instance not loaded from cache: {:?}", - tcx.dep_graph().data().unwrap().prev_node_of(prev_index) + tcx.dep_graph.data().unwrap().prev_node_of(prev_index) ) } @@ -50,13 +46,11 @@ where // chew on (and filling up the final binary, too). #[cold] #[inline(never)] -fn incremental_verify_ich_failed( - tcx: Tcx, +fn incremental_verify_ich_failed<'tcx>( + tcx: TyCtxt<'tcx>, prev_index: SerializedDepNodeIndex, result: &dyn Fn() -> String, -) where - Tcx: DepContext, -{ +) { // When we emit an error message and panic, we try to debug-print the `DepNode` // and query result. Unfortunately, this can cause us to run additional queries, // which may result in another fingerprint mismatch while we're in the middle @@ -70,16 +64,16 @@ fn incremental_verify_ich_failed( let old_in_panic = INSIDE_VERIFY_PANIC.replace(true); if old_in_panic { - tcx.sess().dcx().emit_err(crate::error::Reentrant); + tcx.dcx().emit_err(crate::error::Reentrant); } else { - let run_cmd = if let Some(crate_name) = &tcx.sess().opts.crate_name { + let run_cmd = if let Some(crate_name) = &tcx.sess.opts.crate_name { format!("`cargo clean -p {crate_name}` or `cargo clean`") } else { "`cargo clean`".to_string() }; - let dep_node = tcx.dep_graph().data().unwrap().prev_node_of(prev_index); - tcx.sess().dcx().emit_err(crate::error::IncrementCompilation { + let dep_node = tcx.dep_graph.data().unwrap().prev_node_of(prev_index); + tcx.dcx().emit_err(crate::error::IncrementCompilation { run_cmd, dep_node: format!("{dep_node:?}"), }); diff --git a/compiler/rustc_query_impl/src/dep_kind_vtables.rs b/compiler/rustc_query_impl/src/dep_kind_vtables.rs index 53fc8034e0229..60d9fdc47ed6f 100644 --- a/compiler/rustc_query_impl/src/dep_kind_vtables.rs +++ b/compiler/rustc_query_impl/src/dep_kind_vtables.rs @@ -1,7 +1,6 @@ use rustc_middle::bug; use rustc_middle::dep_graph::{DepKindVTable, DepNodeKey, FingerprintStyle}; use rustc_middle::query::QueryCache; -use rustc_middle::ty::TyCtxt; use crate::plumbing::{force_from_dep_node_inner, try_load_from_on_disk_cache_inner}; use crate::{QueryDispatcherUnerased, QueryFlags}; @@ -122,7 +121,7 @@ where let fingerprint_style = if is_anon { FingerprintStyle::Opaque } else { - >>::fingerprint_style() + >::fingerprint_style() }; if is_anon || !fingerprint_style.reconstructible() { diff --git a/compiler/rustc_query_impl/src/execution.rs b/compiler/rustc_query_impl/src/execution.rs index 683e96f4d2571..826a794bc8fa6 100644 --- a/compiler/rustc_query_impl/src/execution.rs +++ b/compiler/rustc_query_impl/src/execution.rs @@ -14,7 +14,7 @@ use rustc_middle::ty::TyCtxt; use rustc_middle::verify_ich::incremental_verify_ich; use rustc_span::{DUMMY_SP, Span}; -use crate::dep_graph::{DepContext, DepNode, DepNodeIndex}; +use crate::dep_graph::{DepNode, DepNodeIndex}; use crate::job::{QueryJobInfo, QueryJobMap, find_cycle_in_stack, report_cycle}; use crate::{QueryCtxt, QueryFlags, SemiDynamicQueryDispatcher}; @@ -535,7 +535,7 @@ fn try_load_from_disk_and_cache_in_memory<'tcx, C: QueryCache, const FLAGS: Quer // can be forced from `DepNode`. debug_assert!( !query.will_cache_on_disk_for_key(qcx.tcx, key) - || !qcx.dep_context().fingerprint_style(dep_node.kind).reconstructible(), + || !qcx.tcx.fingerprint_style(dep_node.kind).reconstructible(), "missing on-disk cache entry for {dep_node:?}" ); diff --git a/compiler/rustc_query_impl/src/job.rs b/compiler/rustc_query_impl/src/job.rs index 8e554d4ed4e65..6fda5ab779dc7 100644 --- a/compiler/rustc_query_impl/src/job.rs +++ b/compiler/rustc_query_impl/src/job.rs @@ -13,7 +13,6 @@ use rustc_session::Session; use rustc_span::{DUMMY_SP, Span}; use crate::QueryCtxt; -use crate::dep_graph::DepContext; /// Map from query job IDs to job information collected by /// `collect_active_jobs_from_all_queries`. diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index 50838daf01123..030ea29a2a6bf 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -15,8 +15,7 @@ use rustc_middle::bug; #[expect(unused_imports, reason = "used by doc comments")] use rustc_middle::dep_graph::DepKindVTable; use rustc_middle::dep_graph::{ - self, DepContext, DepNode, DepNodeIndex, DepNodeKey, HasDepContext, SerializedDepNodeIndex, - dep_kinds, + self, DepNode, DepNodeIndex, DepNodeKey, HasDepContext, SerializedDepNodeIndex, dep_kinds, }; use rustc_middle::query::on_disk_cache::{ AbsoluteBytePos, CacheDecoder, CacheEncoder, EncodedDepNodeIndex, @@ -141,12 +140,10 @@ impl<'tcx> QueryCtxt<'tcx> { } } -impl<'tcx> HasDepContext for QueryCtxt<'tcx> { - type DepContext = TyCtxt<'tcx>; - +impl<'tcx> HasDepContext<'tcx> for QueryCtxt<'tcx> { #[inline] - fn dep_context(&self) -> &Self::DepContext { - &self.tcx + fn dep_context(&self) -> TyCtxt<'tcx> { + self.tcx } } @@ -165,7 +162,7 @@ pub(super) fn encode_all_query_results<'tcx>( } pub fn query_key_hash_verify_all<'tcx>(tcx: TyCtxt<'tcx>) { - if tcx.sess().opts.unstable_opts.incremental_verify_ich || cfg!(debug_assertions) { + if tcx.sess.opts.unstable_opts.incremental_verify_ich || cfg!(debug_assertions) { tcx.sess.time("query_key_hash_verify_all", || { for verify in super::QUERY_KEY_HASH_VERIFY.iter() { verify(tcx); diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs index 47810e2578df6..8579320321e17 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs @@ -60,7 +60,6 @@ use rustc_hir::lang_items::LangItem; use rustc_hir::{self as hir}; use rustc_macros::extension; use rustc_middle::bug; -use rustc_middle::dep_graph::DepContext; use rustc_middle::traits::PatternOriginExpr; use rustc_middle::ty::error::{ExpectedFound, TypeError, TypeErrorToStringExt}; use rustc_middle::ty::print::{PrintTraitRefExt as _, WrapBinderMode, with_forced_trimmed_paths}; @@ -1757,7 +1756,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { // containing a single ASCII character, perhaps the user meant to write `b'c'` to // specify a byte literal (ty::Uint(ty::UintTy::U8), ty::Char) => { - if let Ok(code) = self.tcx.sess().source_map().span_to_snippet(span) + if let Ok(code) = self.tcx.sess.source_map().span_to_snippet(span) && let Some(code) = code.strip_circumfix('\'', '\'') // forbid all Unicode escapes && !code.starts_with("\\u") @@ -1774,7 +1773,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { // containing a single character, perhaps the user meant to write `'c'` to // specify a character literal (issue #92479) (ty::Char, ty::Ref(_, r, _)) if r.is_str() => { - if let Ok(code) = self.tcx.sess().source_map().span_to_snippet(span) + if let Ok(code) = self.tcx.sess.source_map().span_to_snippet(span) && let Some(code) = code.strip_circumfix('"', '"') && code.chars().count() == 1 { @@ -1787,7 +1786,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { // If a string was expected and the found expression is a character literal, // perhaps the user meant to write `"s"` to specify a string literal. (ty::Ref(_, r, _), ty::Char) if r.is_str() => { - if let Ok(code) = self.tcx.sess().source_map().span_to_snippet(span) + if let Ok(code) = self.tcx.sess.source_map().span_to_snippet(span) && code.starts_with("'") && code.ends_with("'") { @@ -1928,7 +1927,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { return None; } - let Ok(code) = self.tcx.sess().source_map().span_to_snippet(span) else { return None }; + let Ok(code) = self.tcx.sess.source_map().span_to_snippet(span) else { return None }; let sugg = if code.starts_with('(') && code.ends_with(')') { let before_close = span.hi() - BytePos::from_u32(1); @@ -2005,7 +2004,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { // Use the terminal width as the basis to determine when to compress the printed // out type, but give ourselves some leeway to avoid ending up creating a file for // a type that is somewhat shorter than the path we'd write to. - let len = self.tcx.sess().diagnostic_width() + 40; + let len = self.tcx.sess.diagnostic_width() + 40; let exp_s = exp.content(); let fnd_s = fnd.content(); if exp_s.len() > len { From fcea886c1a6d9d0a5736d097b95a7903e7ab83ce Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 12 Feb 2026 12:14:02 +1100 Subject: [PATCH 5/5] Break up `DepsType`. By moving most of it into `DepKind`, and changing two methods into free functions. --- .../rustc_middle/src/dep_graph/dep_node.rs | 20 ++++++ compiler/rustc_middle/src/dep_graph/graph.rs | 28 ++++----- compiler/rustc_middle/src/dep_graph/mod.rs | 63 ++++++------------- .../rustc_middle/src/dep_graph/serialized.rs | 26 +++----- 4 files changed, 61 insertions(+), 76 deletions(-) diff --git a/compiler/rustc_middle/src/dep_graph/dep_node.rs b/compiler/rustc_middle/src/dep_graph/dep_node.rs index 14e43e045e82d..909638b85906c 100644 --- a/compiler/rustc_middle/src/dep_graph/dep_node.rs +++ b/compiler/rustc_middle/src/dep_graph/dep_node.rs @@ -92,6 +92,26 @@ impl DepKind { pub const fn as_usize(&self) -> usize { self.variant as usize } + + pub(crate) fn name(self) -> &'static str { + DEP_KIND_NAMES[self.as_usize()] + } + + /// We use this for most things when incr. comp. is turned off. + pub(crate) const NULL: DepKind = dep_kinds::Null; + + /// We use this to create a forever-red node. + pub(crate) const RED: DepKind = dep_kinds::Red; + + /// We use this to create a side effect node. + pub(crate) const SIDE_EFFECT: DepKind = dep_kinds::SideEffect; + + /// We use this to create the anon node with zero dependencies. + pub(crate) const ANON_ZERO_DEPS: DepKind = dep_kinds::AnonZeroDeps; + + /// This is the highest value a `DepKind` can have. It's used during encoding to + /// pack information into the unused bits. + pub(crate) const MAX: u16 = DEP_KIND_VARIANTS - 1; } pub fn default_dep_kind_debug(kind: DepKind, f: &mut fmt::Formatter<'_>) -> fmt::Result { diff --git a/compiler/rustc_middle/src/dep_graph/graph.rs b/compiler/rustc_middle/src/dep_graph/graph.rs index d0ac398523184..6b9f18a6bfe1d 100644 --- a/compiler/rustc_middle/src/dep_graph/graph.rs +++ b/compiler/rustc_middle/src/dep_graph/graph.rs @@ -25,7 +25,7 @@ use {super::debug::EdgeFilter, std::env}; use super::query::DepGraphQuery; use super::serialized::{GraphEncoder, SerializedDepGraph, SerializedDepNodeIndex}; -use super::{DepKind, DepNode, DepsType, HasDepContext, WorkProductId}; +use super::{DepKind, DepNode, HasDepContext, WorkProductId, read_deps, with_deps}; use crate::dep_graph::edges::EdgesVec; use crate::ty::TyCtxt; use crate::verify_ich::incremental_verify_ich; @@ -126,7 +126,7 @@ impl DepGraph { // Instantiate a node with zero dependencies only once for anonymous queries. let _green_node_index = current.alloc_new_node( - DepNode { kind: DepsType::DEP_KIND_ANON_ZERO_DEPS, hash: current.anon_id_seed.into() }, + DepNode { kind: DepKind::ANON_ZERO_DEPS, hash: current.anon_id_seed.into() }, EdgesVec::new(), Fingerprint::ZERO, ); @@ -134,7 +134,7 @@ impl DepGraph { // Instantiate a dependy-less red node only once for anonymous queries. let red_node_index = current.alloc_new_node( - DepNode { kind: DepsType::DEP_KIND_RED, hash: Fingerprint::ZERO.into() }, + DepNode { kind: DepKind::RED, hash: Fingerprint::ZERO.into() }, EdgesVec::new(), Fingerprint::ZERO, ); @@ -181,7 +181,7 @@ impl DepGraph { pub fn assert_ignored(&self) { if let Some(..) = self.data { - DepsType::read_deps(|task_deps| { + read_deps(|task_deps| { assert_matches!( task_deps, TaskDepsRef::Ignore, @@ -195,7 +195,7 @@ impl DepGraph { where OP: FnOnce() -> R, { - DepsType::with_deps(TaskDepsRef::Ignore, op) + with_deps(TaskDepsRef::Ignore, op) } /// Used to wrap the deserialization of a query result from disk, @@ -248,7 +248,7 @@ impl DepGraph { where OP: FnOnce() -> R, { - DepsType::with_deps(TaskDepsRef::Forbid, op) + with_deps(TaskDepsRef::Forbid, op) } #[inline(always)] @@ -340,7 +340,7 @@ impl DepGraphData { }, ); - let with_deps = |task_deps| DepsType::with_deps(task_deps, || task(cx, arg)); + let with_deps = |task_deps| with_deps(task_deps, || task(cx, arg)); let (result, edges) = if cx.dep_context().is_eval_always(key.kind) { (with_deps(TaskDepsRef::EvalAlways), EdgesVec::new()) } else { @@ -387,7 +387,7 @@ impl DepGraphData { None, 128, )); - let result = DepsType::with_deps(TaskDepsRef::Allow(&task_deps), op); + let result = with_deps(TaskDepsRef::Allow(&task_deps), op); let task_deps = task_deps.into_inner(); let reads = task_deps.reads; @@ -460,7 +460,7 @@ impl DepGraph { #[inline] pub fn read_index(&self, dep_node_index: DepNodeIndex) { if let Some(ref data) = self.data { - DepsType::read_deps(|task_deps| { + read_deps(|task_deps| { let mut task_deps = match task_deps { TaskDepsRef::Allow(deps) => deps.lock(), TaskDepsRef::EvalAlways => { @@ -517,7 +517,7 @@ impl DepGraph { #[inline] pub fn record_diagnostic<'tcx>(&self, tcx: TyCtxt<'tcx>, diagnostic: &DiagInner) { if let Some(ref data) = self.data { - DepsType::read_deps(|task_deps| match task_deps { + read_deps(|task_deps| match task_deps { TaskDepsRef::EvalAlways | TaskDepsRef::Ignore => return, TaskDepsRef::Forbid | TaskDepsRef::Allow(..) => { self.read_index(data.encode_diagnostic(tcx, diagnostic)); @@ -594,7 +594,7 @@ impl DepGraph { } let mut edges = EdgesVec::new(); - DepsType::read_deps(|task_deps| match task_deps { + read_deps(|task_deps| match task_deps { TaskDepsRef::Allow(deps) => edges.extend(deps.lock().reads.iter().copied()), TaskDepsRef::EvalAlways => { edges.push(DepNodeIndex::FOREVER_RED_NODE); @@ -678,7 +678,7 @@ impl DepGraphData { // Use `send_new` so we get an unique index, even though the dep node is not. let dep_node_index = self.current.encoder.send_new( DepNode { - kind: DepsType::DEP_KIND_SIDE_EFFECT, + kind: DepKind::SIDE_EFFECT, hash: PackedFingerprint::from(Fingerprint::ZERO), }, Fingerprint::ZERO, @@ -695,7 +695,7 @@ impl DepGraphData { /// refer to a node created used `encode_diagnostic` in the previous session. #[inline] fn force_diagnostic_node<'tcx>(&self, tcx: TyCtxt<'tcx>, prev_index: SerializedDepNodeIndex) { - DepsType::with_deps(TaskDepsRef::Ignore, || { + with_deps(TaskDepsRef::Ignore, || { let side_effect = tcx.load_side_effect(prev_index).unwrap(); match &side_effect { @@ -711,7 +711,7 @@ impl DepGraphData { prev_index, &self.colors, DepNode { - kind: DepsType::DEP_KIND_SIDE_EFFECT, + kind: DepKind::SIDE_EFFECT, hash: PackedFingerprint::from(Fingerprint::ZERO), }, Fingerprint::ZERO, diff --git a/compiler/rustc_middle/src/dep_graph/mod.rs b/compiler/rustc_middle/src/dep_graph/mod.rs index ea347f53ac448..b10f341c71a6d 100644 --- a/compiler/rustc_middle/src/dep_graph/mod.rs +++ b/compiler/rustc_middle/src/dep_graph/mod.rs @@ -68,51 +68,26 @@ impl FingerprintStyle { } } -pub struct DepsType; - -impl DepsType { - /// Execute the operation with provided dependencies. - fn with_deps(task_deps: TaskDepsRef<'_>, op: OP) -> R - where - OP: FnOnce() -> R, - { - ty::tls::with_context(|icx| { - let icx = ty::tls::ImplicitCtxt { task_deps, ..icx.clone() }; - - ty::tls::enter_context(&icx, op) - }) - } - - /// Access dependencies from current implicit context. - fn read_deps(op: OP) - where - OP: for<'a> FnOnce(TaskDepsRef<'a>), - { - ty::tls::with_context_opt(|icx| { - let Some(icx) = icx else { return }; - op(icx.task_deps) - }) - } - - fn name(dep_kind: DepKind) -> &'static str { - dep_node::DEP_KIND_NAMES[dep_kind.as_usize()] - } - - /// We use this for most things when incr. comp. is turned off. - const DEP_KIND_NULL: DepKind = dep_kinds::Null; - - /// We use this to create a forever-red node. - const DEP_KIND_RED: DepKind = dep_kinds::Red; - - /// We use this to create a side effect node. - const DEP_KIND_SIDE_EFFECT: DepKind = dep_kinds::SideEffect; - - /// We use this to create the anon node with zero dependencies. - const DEP_KIND_ANON_ZERO_DEPS: DepKind = dep_kinds::AnonZeroDeps; +/// Execute the operation with provided dependencies. +fn with_deps(task_deps: TaskDepsRef<'_>, op: OP) -> R +where + OP: FnOnce() -> R, +{ + ty::tls::with_context(|icx| { + let icx = ty::tls::ImplicitCtxt { task_deps, ..icx.clone() }; + ty::tls::enter_context(&icx, op) + }) +} - /// This is the highest value a `DepKind` can have. It's used during encoding to - /// pack information into the unused bits. - const DEP_KIND_MAX: u16 = dep_node::DEP_KIND_VARIANTS - 1; +/// Access dependencies from current implicit context. +fn read_deps(op: OP) +where + OP: for<'a> FnOnce(TaskDepsRef<'a>), +{ + ty::tls::with_context_opt(|icx| { + let Some(icx) = icx else { return }; + op(icx.task_deps) + }) } impl<'tcx> TyCtxt<'tcx> { diff --git a/compiler/rustc_middle/src/dep_graph/serialized.rs b/compiler/rustc_middle/src/dep_graph/serialized.rs index d2938373f5448..dbcd5ea070887 100644 --- a/compiler/rustc_middle/src/dep_graph/serialized.rs +++ b/compiler/rustc_middle/src/dep_graph/serialized.rs @@ -61,7 +61,6 @@ use tracing::{debug, instrument}; use super::graph::{CurrentDepGraph, DepNodeColorMap}; use super::query::DepGraphQuery; use super::{DepKind, DepNode, DepNodeIndex}; -use crate::dep_graph::DepsType; use crate::dep_graph::edges::EdgesVec; // The maximum value of `SerializedDepNodeIndex` leaves the upper two bits @@ -213,10 +212,7 @@ impl SerializedDepGraph { let graph_bytes = d.len() - (3 * IntEncodedWithFixedSize::ENCODED_SIZE) - d.position(); let mut nodes = IndexVec::from_elem_n( - DepNode { - kind: DepsType::DEP_KIND_NULL, - hash: PackedFingerprint::from(Fingerprint::ZERO), - }, + DepNode { kind: DepKind::NULL, hash: PackedFingerprint::from(Fingerprint::ZERO) }, node_max, ); let mut fingerprints = IndexVec::from_elem_n(Fingerprint::ZERO, node_max); @@ -244,10 +240,7 @@ impl SerializedDepGraph { let node = &mut nodes[index]; // Make sure there's no duplicate indices in the dep graph. - assert!( - node_header.node().kind != DepsType::DEP_KIND_NULL - && node.kind == DepsType::DEP_KIND_NULL - ); + assert!(node_header.node().kind != DepKind::NULL && node.kind == DepKind::NULL); *node = node_header.node(); fingerprints[index] = node_header.fingerprint(); @@ -275,7 +268,7 @@ impl SerializedDepGraph { edge_list_data.extend(&[0u8; DEP_NODE_PAD]); // Read the number of each dep kind and use it to create an hash map with a suitable size. - let mut index: Vec<_> = (0..(DepsType::DEP_KIND_MAX + 1)) + let mut index: Vec<_> = (0..(DepKind::MAX + 1)) .map(|_| UnhashMap::with_capacity_and_hasher(d.read_u32() as usize, Default::default())) .collect(); @@ -284,10 +277,8 @@ impl SerializedDepGraph { for (idx, node) in nodes.iter_enumerated() { if index[node.kind.as_usize()].insert(node.hash, idx).is_some() { // Empty nodes and side effect nodes can have duplicates - if node.kind != DepsType::DEP_KIND_NULL - && node.kind != DepsType::DEP_KIND_SIDE_EFFECT - { - let name = DepsType::name(node.kind); + if node.kind != DepKind::NULL && node.kind != DepKind::SIDE_EFFECT { + let name = node.kind.name(); panic!( "Error: A dep graph node ({name}) does not have an unique index. \ Running a clean build on a nightly compiler with `-Z incremental-verify-ich` \ @@ -347,7 +338,7 @@ impl SerializedNodeHeader { const TOTAL_BITS: usize = size_of::() * 8; const LEN_BITS: usize = Self::TOTAL_BITS - Self::KIND_BITS - Self::WIDTH_BITS; const WIDTH_BITS: usize = DEP_NODE_WIDTH_BITS; - const KIND_BITS: usize = Self::TOTAL_BITS - DepsType::DEP_KIND_MAX.leading_zeros() as usize; + const KIND_BITS: usize = Self::TOTAL_BITS - DepKind::MAX.leading_zeros() as usize; const MAX_INLINE_LEN: usize = (u16::MAX as usize >> (Self::TOTAL_BITS - Self::LEN_BITS)) - 1; #[inline] @@ -566,7 +557,7 @@ impl EncoderState { edge_count: 0, node_count: 0, encoder: MemEncoder::new(), - kind_stats: iter::repeat_n(0, DepsType::DEP_KIND_MAX as usize + 1).collect(), + kind_stats: iter::repeat_n(0, DepKind::MAX as usize + 1).collect(), }) }), } @@ -734,8 +725,7 @@ impl EncoderState { let mut encoder = self.file.lock().take().unwrap(); - let mut kind_stats: Vec = - iter::repeat_n(0, DepsType::DEP_KIND_MAX as usize + 1).collect(); + let mut kind_stats: Vec = iter::repeat_n(0, DepKind::MAX as usize + 1).collect(); let mut node_max = 0; let mut node_count = 0;