Auto merge of #152636 - nnethercote:big-cleanups, r=Zalathar

Big query system cleanups

Recent PRs have moved a lot of code from `rustc_query_system` to `rustc_middle` and `rustc_query_impl`, where this code now has access to `TyCtxt`, e.g. rust-lang/rust#152419, rust-lang/rust#152516. As a result, a lot of abstraction and indirection that existed to work around this limitation is no longer necessary. This PR removes a lot of it.

r? @Zalathar
This commit is contained in:
bors 2026-02-16 04:20:25 +00:00
commit fef627b1eb
19 changed files with 317 additions and 492 deletions

View file

@ -4500,7 +4500,6 @@ dependencies = [
"rustc_index",
"rustc_macros",
"rustc_middle",
"rustc_query_system",
"rustc_serialize",
"rustc_session",
"rustc_span",

View file

@ -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;

View file

@ -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};

View file

@ -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<SerializedDepGraph>, WorkPr
return LoadResult::DataOutOfDate;
}
let dep_graph = SerializedDepGraph::decode::<DepsType>(&mut decoder);
let dep_graph = SerializedDepGraph::decode(&mut decoder);
LoadResult::Ok { data: (dep_graph, prev_work_products) }
}

View file

@ -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::{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<R>(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() };

View file

@ -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;
@ -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 {
@ -117,18 +137,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: 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, Key>(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<Tcx>,
Key: DepNodeKey<'tcx>,
{
let hash = arg.to_fingerprint(tcx);
let dep_node = DepNode { kind, hash: hash.into() };
@ -136,10 +152,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 +165,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: 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 +189,14 @@ impl fmt::Debug for DepNode {
}
/// Trait for query keys as seen by dependency-node tracking.
pub trait DepNodeKey<Tcx: DepContext>: 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 +204,11 @@ pub trait DepNodeKey<Tcx: DepContext>: 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<Self>;
fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self>;
}
// Blanket impl of `DepNodeKey`, which is specialized by other impls elsewhere.
impl<Tcx: DepContext, T> DepNodeKey<Tcx> for T
impl<'tcx, T> DepNodeKey<'tcx> for T
where
T: for<'a> HashStable<StableHashingContext<'a>> + fmt::Debug,
{
@ -201,7 +218,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 +227,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 +235,7 @@ where
}
#[inline(always)]
default fn recover(_: Tcx, _: &DepNode) -> Option<Self> {
default fn recover(_: TyCtxt<'tcx>, _: &DepNode) -> Option<Self> {
None
}
}
@ -228,7 +245,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<Tcx: DepContext> {
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 +296,12 @@ pub struct DepKindVTable<Tcx: DepContext> {
/// 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<fn(tcx: Tcx, dep_node: DepNode, prev_index: SerializedDepNodeIndex) -> 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<fn(Tcx, DepNode)>,
pub try_load_from_on_disk_cache: Option<fn(TyCtxt<'tcx>, DepNode)>,
/// The name of this dep kind.
pub name: &'static &'static str,
@ -434,19 +452,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<DefId>;
fn from_label_string(
tcx: TyCtxt<'_>,
label: &str,
def_path_hash: DefPathHash,
) -> Result<Self, ()>;
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 +463,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<DefId> {
pub fn extract_def_id(&self, tcx: TyCtxt<'_>) -> Option<DefId> {
if tcx.fingerprint_style(self.kind) == FingerprintStyle::DefPathHash {
tcx.def_path_hash_to_def_id(DefPathHash(self.hash.into()))
} else {
@ -465,8 +471,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 +487,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()
}
}

View file

@ -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, DepNodeExt, DepNodeKey, FingerprintStyle};
use crate::dep_graph::{DepNode, DepNodeKey, FingerprintStyle};
use crate::ty::TyCtxt;
impl<'tcx> DepNodeKey<TyCtxt<'tcx>> for () {
impl<'tcx> DepNodeKey<'tcx> for () {
#[inline(always)]
fn fingerprint_style() -> FingerprintStyle {
FingerprintStyle::Unit
@ -23,7 +23,7 @@ impl<'tcx> DepNodeKey<TyCtxt<'tcx>> for () {
}
}
impl<'tcx> DepNodeKey<TyCtxt<'tcx>> for DefId {
impl<'tcx> DepNodeKey<'tcx> for DefId {
#[inline(always)]
fn fingerprint_style() -> FingerprintStyle {
FingerprintStyle::DefPathHash
@ -45,7 +45,7 @@ impl<'tcx> DepNodeKey<TyCtxt<'tcx>> for DefId {
}
}
impl<'tcx> DepNodeKey<TyCtxt<'tcx>> for LocalDefId {
impl<'tcx> DepNodeKey<'tcx> for LocalDefId {
#[inline(always)]
fn fingerprint_style() -> FingerprintStyle {
FingerprintStyle::DefPathHash
@ -67,7 +67,7 @@ impl<'tcx> DepNodeKey<TyCtxt<'tcx>> for LocalDefId {
}
}
impl<'tcx> DepNodeKey<TyCtxt<'tcx>> for OwnerId {
impl<'tcx> DepNodeKey<'tcx> for OwnerId {
#[inline(always)]
fn fingerprint_style() -> FingerprintStyle {
FingerprintStyle::DefPathHash
@ -89,7 +89,7 @@ impl<'tcx> DepNodeKey<TyCtxt<'tcx>> for OwnerId {
}
}
impl<'tcx> DepNodeKey<TyCtxt<'tcx>> for CrateNum {
impl<'tcx> DepNodeKey<'tcx> for CrateNum {
#[inline(always)]
fn fingerprint_style() -> FingerprintStyle {
FingerprintStyle::DefPathHash
@ -112,7 +112,7 @@ impl<'tcx> DepNodeKey<TyCtxt<'tcx>> for CrateNum {
}
}
impl<'tcx> DepNodeKey<TyCtxt<'tcx>> 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<TyCtxt<'tcx>> for (DefId, DefId) {
}
}
impl<'tcx> DepNodeKey<TyCtxt<'tcx>> for HirId {
impl<'tcx> DepNodeKey<'tcx> for HirId {
#[inline(always)]
fn fingerprint_style() -> FingerprintStyle {
FingerprintStyle::HirId
@ -182,7 +182,7 @@ impl<'tcx> DepNodeKey<TyCtxt<'tcx>> for HirId {
}
}
impl<'tcx> DepNodeKey<TyCtxt<'tcx>> for ModDefId {
impl<'tcx> DepNodeKey<'tcx> for ModDefId {
#[inline(always)]
fn fingerprint_style() -> FingerprintStyle {
FingerprintStyle::DefPathHash
@ -204,7 +204,7 @@ impl<'tcx> DepNodeKey<TyCtxt<'tcx>> for ModDefId {
}
}
impl<'tcx> DepNodeKey<TyCtxt<'tcx>> for LocalModDefId {
impl<'tcx> DepNodeKey<'tcx> for LocalModDefId {
#[inline(always)]
fn fingerprint_style() -> FingerprintStyle {
FingerprintStyle::DefPathHash

View file

@ -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::{DepKind, DepNode, HasDepContext, WorkProductId, read_deps, with_deps};
use crate::dep_graph::edges::EdgesVec;
use crate::query::QueryContext;
use crate::ty::TyCtxt;
use crate::verify_ich::incremental_verify_ich;
pub struct DepGraph<D: Deps> {
data: Option<Arc<DepGraphData<D>>>,
#[derive(Clone)]
pub struct DepGraph {
data: Option<Arc<DepGraphData>>,
/// 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<D: Deps> {
virtual_dep_node_index: Arc<AtomicU32>,
}
/// Manual clone impl that does not require `D: Clone`.
impl<D: Deps> Clone for DepGraph<D> {
fn clone(&self) -> Self {
let Self { data, virtual_dep_node_index } = self;
Self {
data: Option::<Arc<_>>::clone(data),
virtual_dep_node_index: Arc::clone(virtual_dep_node_index),
}
}
}
rustc_index::newtype_index! {
pub struct DepNodeIndex {}
}
@ -72,7 +62,7 @@ impl From<DepNodeIndex> for QueryInvocationId {
}
}
pub struct MarkFrame<'a> {
pub(crate) struct MarkFrame<'a> {
index: SerializedDepNodeIndex,
parent: Option<&'a MarkFrame<'a>>,
}
@ -84,12 +74,12 @@ pub(super) enum DepNodeColor {
Unknown,
}
pub struct DepGraphData<D: Deps> {
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<D>,
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<D: Deps> DepGraph<D> {
impl DepGraph {
pub fn new(
session: &Session,
prev_graph: Arc<SerializedDepGraph>,
prev_work_products: WorkProductMap,
encoder: FileEncoder,
) -> DepGraph<D> {
) -> DepGraph {
let prev_graph_node_count = prev_graph.node_count();
let current =
@ -136,7 +126,7 @@ impl<D: Deps> DepGraph<D> {
// 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: DepKind::ANON_ZERO_DEPS, hash: current.anon_id_seed.into() },
EdgesVec::new(),
Fingerprint::ZERO,
);
@ -144,7 +134,7 @@ impl<D: Deps> DepGraph<D> {
// 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: DepKind::RED, hash: Fingerprint::ZERO.into() },
EdgesVec::new(),
Fingerprint::ZERO,
);
@ -168,12 +158,12 @@ impl<D: Deps> DepGraph<D> {
}
}
pub fn new_disabled() -> DepGraph<D> {
pub fn new_disabled() -> DepGraph {
DepGraph { data: None, virtual_dep_node_index: Arc::new(AtomicU32::new(0)) }
}
#[inline]
pub fn data(&self) -> Option<&DepGraphData<D>> {
pub fn data(&self) -> Option<&DepGraphData> {
self.data.as_deref()
}
@ -191,7 +181,7 @@ impl<D: Deps> DepGraph<D> {
pub fn assert_ignored(&self) {
if let Some(..) = self.data {
D::read_deps(|task_deps| {
read_deps(|task_deps| {
assert_matches!(
task_deps,
TaskDepsRef::Ignore,
@ -205,7 +195,7 @@ impl<D: Deps> DepGraph<D> {
where
OP: FnOnce() -> R,
{
D::with_deps(TaskDepsRef::Ignore, op)
with_deps(TaskDepsRef::Ignore, op)
}
/// Used to wrap the deserialization of a query result from disk,
@ -258,11 +248,11 @@ impl<D: Deps> DepGraph<D> {
where
OP: FnOnce() -> R,
{
D::with_deps(TaskDepsRef::Forbid, op)
with_deps(TaskDepsRef::Forbid, op)
}
#[inline(always)]
pub fn with_task<Ctxt: HasDepContext<Deps = D>, A: Debug, R>(
pub fn with_task<'tcx, Ctxt: HasDepContext<'tcx>, A: Debug, R>(
&self,
key: DepNode,
cx: Ctxt,
@ -276,9 +266,9 @@ impl<D: Deps> DepGraph<D> {
}
}
pub fn with_anon_task<Tcx: DepContext<Deps = D>, OP, R>(
pub fn with_anon_task<'tcx, OP, R>(
&self,
cx: Tcx,
cx: TyCtxt<'tcx>,
dep_kind: DepKind,
op: OP,
) -> (R, DepNodeIndex)
@ -296,7 +286,7 @@ impl<D: Deps> DepGraph<D> {
}
}
impl<D: Deps> DepGraphData<D> {
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<D: Deps> DepGraphData<D> {
///
/// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/queries/incremental-compilation.html
#[inline(always)]
pub fn with_task<Ctxt: HasDepContext<Deps = D>, A: Debug, R>(
pub fn with_task<'tcx, Ctxt: HasDepContext<'tcx>, A: Debug, R>(
&self,
key: DepNode,
cx: Ctxt,
@ -339,7 +329,7 @@ impl<D: Deps> DepGraphData<D> {
// 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!(
@ -350,7 +340,7 @@ impl<D: Deps> DepGraphData<D> {
},
);
let with_deps = |task_deps| D::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 {
@ -362,8 +352,8 @@ impl<D: Deps> DepGraphData<D> {
(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)
}
@ -379,9 +369,9 @@ impl<D: Deps> DepGraphData<D> {
/// 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<Tcx: DepContext<Deps = D>, OP, R>(
pub fn with_anon_task_inner<'tcx, OP, R>(
&self,
cx: Tcx,
cx: TyCtxt<'tcx>,
dep_kind: DepKind,
op: OP,
) -> (R, DepNodeIndex)
@ -397,7 +387,7 @@ impl<D: Deps> DepGraphData<D> {
None,
128,
));
let result = D::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;
@ -448,17 +438,17 @@ impl<D: Deps> DepGraphData<D> {
}
/// Intern the new `DepNode` with the dependencies up-to-now.
fn hash_result_and_alloc_node<Ctxt: DepContext<Deps = D>, R>(
fn hash_result_and_alloc_node<'tcx, R>(
&self,
cx: &Ctxt,
tcx: TyCtxt<'tcx>,
node: DepNode,
edges: EdgesVec,
result: &R,
hash_result: Option<fn(&mut StableHashingContext<'_>, &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());
@ -466,11 +456,11 @@ impl<D: Deps> DepGraphData<D> {
}
}
impl<D: Deps> DepGraph<D> {
impl DepGraph {
#[inline]
pub fn read_index(&self, dep_node_index: DepNodeIndex) {
if let Some(ref data) = self.data {
D::read_deps(|task_deps| {
read_deps(|task_deps| {
let mut task_deps = match task_deps {
TaskDepsRef::Allow(deps) => deps.lock(),
TaskDepsRef::EvalAlways => {
@ -525,16 +515,12 @@ impl<D: Deps> DepGraph<D> {
/// 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 {
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 +528,13 @@ impl<D: Deps> DepGraph<D> {
/// 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);
}
}
@ -567,10 +553,10 @@ impl<D: Deps> DepGraph<D> {
/// 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<Ctxt: DepContext<Deps = D>, R>(
pub fn with_feed_task<'tcx, R>(
&self,
node: DepNode,
cx: Ctxt,
tcx: TyCtxt<'tcx>,
result: &R,
hash_result: Option<fn(&mut StableHashingContext<'_>, &R) -> Fingerprint>,
format_value_fn: fn(&R) -> String,
@ -586,7 +572,7 @@ impl<D: Deps> DepGraph<D> {
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,
@ -608,7 +594,7 @@ impl<D: Deps> DepGraph<D> {
}
let mut edges = EdgesVec::new();
D::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);
@ -619,7 +605,7 @@ impl<D: Deps> DepGraph<D> {
}
});
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
@ -630,7 +616,7 @@ impl<D: Deps> DepGraph<D> {
}
}
impl<D: Deps> DepGraphData<D> {
impl DepGraphData {
fn assert_dep_node_not_yet_allocated_in_current_session<S: std::fmt::Display>(
&self,
sess: &Session,
@ -688,15 +674,11 @@ impl<D: Deps> DepGraphData<D> {
/// 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 {
kind: D::DEP_KIND_SIDE_EFFECT,
kind: DepKind::SIDE_EFFECT,
hash: PackedFingerprint::from(Fingerprint::ZERO),
},
Fingerprint::ZERO,
@ -705,24 +687,20 @@ impl<D: Deps> DepGraphData<D> {
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,
) {
D::with_deps(TaskDepsRef::Ignore, || {
let side_effect = qcx.load_side_effect(prev_index).unwrap();
fn force_diagnostic_node<'tcx>(&self, tcx: TyCtxt<'tcx>, prev_index: SerializedDepNodeIndex) {
with_deps(TaskDepsRef::Ignore, || {
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());
}
}
@ -733,7 +711,7 @@ impl<D: Deps> DepGraphData<D> {
prev_index,
&self.colors,
DepNode {
kind: D::DEP_KIND_SIDE_EFFECT,
kind: DepKind::SIDE_EFFECT,
hash: PackedFingerprint::from(Fingerprint::ZERO),
},
Fingerprint::ZERO,
@ -741,7 +719,7 @@ impl<D: Deps> DepGraphData<D> {
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);
})
}
@ -811,7 +789,7 @@ impl<D: Deps> DepGraphData<D> {
}
}
impl<D: Deps> DepGraph<D> {
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<WorkProduct> {
@ -867,27 +845,27 @@ impl<D: Deps> DepGraph<D> {
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))
}
}
impl<D: Deps> DepGraphData<D> {
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
/// 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 +880,16 @@ impl<D: Deps> DepGraphData<D> {
// 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 +922,13 @@ impl<D: Deps> DepGraphData<D> {
// 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 +938,7 @@ impl<D: Deps> DepGraphData<D> {
// 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 +956,7 @@ impl<D: Deps> DepGraphData<D> {
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 +975,10 @@ impl<D: Deps> DepGraphData<D> {
}
/// 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<DepNodeIndex> {
@ -1008,14 +986,14 @@ impl<D: Deps> DepGraphData<D> {
// 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
@ -1041,7 +1019,7 @@ impl<D: Deps> DepGraphData<D> {
}
}
impl<D: Deps> DepGraph<D> {
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 {
@ -1073,8 +1051,8 @@ impl<D: Deps> DepGraph<D> {
///
/// 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<Tcx: DepContext>(&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() {
@ -1175,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<D: Deps> {
encoder: GraphEncoder<D>,
pub(super) struct CurrentDepGraph {
encoder: GraphEncoder,
anon_node_to_index: ShardedHashMap<DepNode, DepNodeIndex>,
/// This is used to verify that fingerprints do not change between the creation of a node
@ -1214,7 +1192,7 @@ pub(super) struct CurrentDepGraph<D: Deps> {
pub(super) total_duplicate_read_count: AtomicU64,
}
impl<D: Deps> CurrentDepGraph<D> {
impl CurrentDepGraph {
fn new(
session: &Session,
prev_graph_node_count: usize,
@ -1448,7 +1426,7 @@ impl DepNodeColorMap {
#[inline(never)]
#[cold]
pub(crate) fn print_markframe_trace<D: Deps>(graph: &DepGraph<D>, 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");
@ -1468,7 +1446,7 @@ pub(crate) fn print_markframe_trace<D: Deps>(graph: &DepGraph<D>, frame: &MarkFr
#[cold]
#[inline(never)]
fn panic_on_forbidden_read<D: Deps>(data: &DepGraphData<D>, 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.
@ -1508,3 +1486,30 @@ fn panic_on_forbidden_read<D: Deps>(data: &DepGraphData<D>, dep_node_index: DepN
See <https://github.com/rust-lang/rust/pull/91919>."
)
}
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<QuerySideEffect> {
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)
}
}
}

View file

@ -1,17 +1,13 @@
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;
pub use self::dep_node::{
DepKind, DepNode, DepNodeExt, DepNodeKey, WorkProductId, dep_kind_from_label, dep_kinds,
DepKind, DepKindVTable, 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;
@ -28,125 +24,18 @@ mod graph;
mod query;
mod serialized;
pub trait DepContext: Copy {
type Deps: Deps;
/// Create a hashing context for hashing new results.
fn with_stable_hashing_context<R>(self, f: impl FnOnce(StableHashingContext<'_>) -> R) -> R;
/// Access the DepGraph.
fn dep_graph(&self) -> &graph::DepGraph<Self::Deps>;
/// 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<Self>;
#[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.
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::<rustc_errors::FatalErrorMarker>() {
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<T>(self, _: impl FnOnce() -> T) -> T;
pub trait HasDepContext<'tcx>: Copy {
fn dep_context(&self) -> TyCtxt<'tcx>;
}
pub trait Deps: DynSync {
/// Execute the operation with provided dependencies.
fn with_deps<OP, R>(deps: TaskDepsRef<'_>, op: OP) -> R
where
OP: FnOnce() -> R;
/// Access dependencies from current implicit context.
fn read_deps<OP>(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<Deps = Self::Deps>;
fn dep_context(&self) -> &Self::DepContext;
}
impl<T: DepContext> HasDepContext for T {
type Deps = T::Deps;
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<T: HasDepContext, Q: Copy> HasDepContext for (T, Q) {
type Deps = T::Deps;
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()
}
}
@ -179,74 +68,77 @@ impl FingerprintStyle {
}
}
pub type DepGraph = graph::DepGraph<DepsType>;
pub type DepKindVTable<'tcx> = dep_node::DepKindVTable<TyCtxt<'tcx>>;
pub struct DepsType;
impl Deps for DepsType {
fn with_deps<OP, R>(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)
})
}
fn read_deps<OP>(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()]
}
const DEP_KIND_NULL: DepKind = dep_kinds::Null;
const DEP_KIND_RED: DepKind = dep_kinds::Red;
const DEP_KIND_SIDE_EFFECT: DepKind = dep_kinds::SideEffect;
const DEP_KIND_ANON_ZERO_DEPS: DepKind = dep_kinds::AnonZeroDeps;
const DEP_KIND_MAX: u16 = dep_node::DEP_KIND_VARIANTS - 1;
/// Execute the operation with provided dependencies.
fn with_deps<OP, R>(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)
})
}
impl<'tcx> DepContext for TyCtxt<'tcx> {
type Deps = DepsType;
/// Access dependencies from current implicit context.
fn read_deps<OP>(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> {
#[inline]
fn with_stable_hashing_context<R>(self, f: impl FnOnce(StableHashingContext<'_>) -> R) -> R {
TyCtxt::with_stable_hashing_context(self, f)
}
#[inline]
fn dep_graph(&self) -> &DepGraph {
&self.dep_graph
}
#[inline(always)]
fn profiler(&self) -> &SelfProfilerRef {
&self.prof
}
#[inline(always)]
fn sess(&self) -> &Session {
self.sess
}
#[inline]
fn dep_kind_vtable(&self, dk: DepKind) -> &DepKindVTable<'tcx> {
pub fn dep_kind_vtable(self, dk: DepKind) -> &'tcx DepKindVTable<'tcx> {
&self.dep_kind_vtables[dk.as_usize()]
}
fn with_reduced_queries<T>(self, f: impl FnOnce() -> T) -> T {
with_reduced_queries!(f())
}
#[inline(always)]
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]
#[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::<rustc_errors::FatalErrorMarker>() {
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)
}
}
}

View file

@ -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};
@ -61,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::edges::EdgesVec;
// The maximum value of `SerializedDepNodeIndex` leaves the upper two bits
@ -192,7 +191,7 @@ fn mask(bits: usize) -> usize {
impl SerializedDepGraph {
#[instrument(level = "debug", skip(d))]
pub fn decode<D: Deps>(d: &mut MemDecoder<'_>) -> Arc<SerializedDepGraph> {
pub fn decode(d: &mut MemDecoder<'_>) -> Arc<SerializedDepGraph> {
// The last 16 bytes are the node count and edge count.
debug!("position: {:?}", d.position());
@ -213,7 +212,7 @@ 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: DepKind::NULL, hash: PackedFingerprint::from(Fingerprint::ZERO) },
node_max,
);
let mut fingerprints = IndexVec::from_elem_n(Fingerprint::ZERO, node_max);
@ -230,19 +229,18 @@ 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::<SerializedNodeHeader<D>>());
Vec::with_capacity(graph_bytes - node_count * size_of::<SerializedNodeHeader>());
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::<D> { 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 != DepKind::NULL && node.kind == DepKind::NULL);
*node = node_header.node();
fingerprints[index] = node_header.fingerprint();
@ -270,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..(D::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();
@ -279,8 +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 != D::DEP_KIND_NULL && node.kind != D::DEP_KIND_SIDE_EFFECT {
let name = D::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` \
@ -310,13 +308,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<D> {
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<D>,
}
// The fields of a `SerializedNodeHeader`, this struct is an implementation detail and exists only
@ -337,11 +334,11 @@ struct Unpacked {
// 0..M length of the edge
// M..M+N bytes per index
// M+N..16 kind
impl<D: Deps> SerializedNodeHeader<D> {
impl SerializedNodeHeader {
const TOTAL_BITS: usize = size_of::<DepKind>() * 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 - DepKind::MAX.leading_zeros() as usize;
const MAX_INLINE_LEN: usize = (u16::MAX as usize >> (Self::TOTAL_BITS - Self::LEN_BITS)) - 1;
#[inline]
@ -377,14 +374,14 @@ impl<D: Deps> SerializedNodeHeader<D> {
#[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 +448,10 @@ struct NodeInfo {
}
impl NodeInfo {
fn encode<D: Deps>(&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::<D>::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 +472,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<D: Deps>(
fn encode_promoted(
e: &mut MemEncoder,
node: &DepNode,
index: DepNodeIndex,
@ -496,7 +488,7 @@ impl NodeInfo {
let edge_max =
edges.clone().map(|i| colors.current(i).unwrap().as_u32()).max().unwrap_or(0);
let header = SerializedNodeHeader::<D>::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 +535,15 @@ struct LocalEncoderResult {
kind_stats: Vec<u32>,
}
struct EncoderState<D: Deps> {
struct EncoderState {
next_node_index: AtomicU64,
previous: Arc<SerializedDepGraph>,
file: Lock<Option<FileEncoder>>,
local: WorkerLocal<RefCell<LocalEncoderState>>,
stats: Option<Lock<FxHashMap<DepKind, Stat>>>,
marker: PhantomData<D>,
}
impl<D: Deps> EncoderState<D> {
impl EncoderState {
fn new(encoder: FileEncoder, record_stats: bool, previous: Arc<SerializedDepGraph>) -> Self {
Self {
previous,
@ -566,10 +557,9 @@ impl<D: Deps> EncoderState<D> {
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, DepKind::MAX as usize + 1).collect(),
})
}),
marker: PhantomData,
}
}
@ -658,7 +648,7 @@ impl<D: Deps> EncoderState<D> {
record_graph: &Option<Lock<DepGraphQuery>>,
local: &mut LocalEncoderState,
) {
node.encode::<D>(&mut local.encoder, index);
node.encode(&mut local.encoder, index);
self.flush_mem_encoder(&mut *local);
self.record(
&node.node,
@ -687,7 +677,7 @@ impl<D: Deps> EncoderState<D> {
) {
let node = self.previous.index_to_node(prev_index);
let fingerprint = self.previous.fingerprint_by_index(prev_index);
let edge_count = NodeInfo::encode_promoted::<D>(
let edge_count = NodeInfo::encode_promoted(
&mut local.encoder,
node,
index,
@ -712,7 +702,7 @@ impl<D: Deps> EncoderState<D> {
);
}
fn finish(&self, profiler: &SelfProfilerRef, current: &CurrentDepGraph<D>) -> 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 +725,7 @@ impl<D: Deps> EncoderState<D> {
let mut encoder = self.file.lock().take().unwrap();
let mut kind_stats: Vec<u32> = iter::repeat_n(0, D::DEP_KIND_MAX as usize + 1).collect();
let mut kind_stats: Vec<u32> = iter::repeat_n(0, DepKind::MAX as usize + 1).collect();
let mut node_max = 0;
let mut node_count = 0;
@ -778,7 +768,7 @@ impl<D: Deps> EncoderState<D> {
fn print_incremental_info(
&self,
current: &CurrentDepGraph<D>,
current: &CurrentDepGraph,
total_node_count: usize,
total_edge_count: usize,
) {
@ -835,13 +825,13 @@ impl<D: Deps> EncoderState<D> {
}
}
pub(crate) struct GraphEncoder<D: Deps> {
pub(crate) struct GraphEncoder {
profiler: SelfProfilerRef,
status: EncoderState<D>,
status: EncoderState,
record_graph: Option<Lock<DepGraphQuery>>,
}
impl<D: Deps> GraphEncoder<D> {
impl GraphEncoder {
pub(crate) fn new(
sess: &Session,
encoder: FileEncoder,
@ -945,7 +935,7 @@ impl<D: Deps> GraphEncoder<D> {
}
}
pub(crate) fn finish(&self, current: &CurrentDepGraph<D>) -> 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)

View file

@ -105,7 +105,7 @@ pub(crate) fn query_feed<'tcx, Cache>(
value: Cache::Value,
) where
Cache: QueryCache,
Cache::Key: DepNodeKey<TyCtxt<'tcx>>,
Cache::Key: DepNodeKey<'tcx>,
{
let format_value = query_vtable.format_value;

View file

@ -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<LocalDefId>, 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<QuerySideEffect>;
/// 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);
}

View file

@ -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, V>(
tcx: Tcx,
dep_graph_data: &DepGraphData<Tcx::Deps>,
pub fn incremental_verify_ich<'tcx, V>(
tcx: TyCtxt<'tcx>,
dep_graph_data: &DepGraphData,
result: &V,
prev_index: SerializedDepNodeIndex,
hash_result: Option<fn(&mut StableHashingContext<'_>, &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<Tcx, V>(
#[cold]
#[inline(never)]
fn incremental_verify_ich_not_green<Tcx>(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: 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<Tcx>(
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:?}"),
});

View file

@ -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" }

View file

@ -1,10 +1,9 @@
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::{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 +44,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,
@ -122,7 +121,7 @@ where
let fingerprint_style = if is_anon {
FingerprintStyle::Opaque
} else {
<Cache::Key as DepNodeKey<TyCtxt<'tcx>>>::fingerprint_style()
<Cache::Key as DepNodeKey<'tcx>>::fingerprint_style()
};
if is_anon || !fingerprint_style.reconstructible() {

View file

@ -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,
@ -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};
@ -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<DepsType>,
dep_graph_data: &DepGraphData,
key: C::Key,
mut dep_node_opt: Option<DepNode>,
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<DepsType>,
dep_graph_data: &DepGraphData,
qcx: QueryCtxt<'tcx>,
key: &C::Key,
dep_node: &DepNode,
@ -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));
@ -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:?}"
);
@ -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.

View file

@ -14,7 +14,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`.

View file

@ -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;
@ -16,22 +15,19 @@ 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, DepNode, DepNodeIndex, DepNodeKey, HasDepContext, SerializedDepNodeIndex, dep_kinds,
};
use rustc_middle::query::on_disk_cache::{
AbsoluteBytePos, CacheDecoder, CacheEncoder, EncodedDepNodeIndex,
};
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 +36,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>,
@ -146,45 +140,15 @@ impl<'tcx> QueryCtxt<'tcx> {
}
}
impl<'tcx> HasDepContext for QueryCtxt<'tcx> {
type Deps = DepsType;
type DepContext = TyCtxt<'tcx>;
impl<'tcx> HasDepContext<'tcx> for QueryCtxt<'tcx> {
#[inline]
fn dep_context(&self) -> &Self::DepContext {
&self.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<QuerySideEffect> {
fn dep_context(&self) -> TyCtxt<'tcx> {
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>(
@ -198,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);

View file

@ -61,7 +61,6 @@ use rustc_hir::{self as hir};
use rustc_infer::infer::DefineOpaqueTypes;
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};
@ -1837,7 +1836,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")
@ -1854,7 +1853,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
{
@ -1867,7 +1866,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("'")
{
@ -2008,7 +2007,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);
@ -2085,7 +2084,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 {