diff --git a/compiler/rustc_incremental/src/assert_dep_graph.rs b/compiler/rustc_incremental/src/assert_dep_graph.rs index 5e7ae3ecdb8..1b160eca92d 100644 --- a/compiler/rustc_incremental/src/assert_dep_graph.rs +++ b/compiler/rustc_incremental/src/assert_dep_graph.rs @@ -42,7 +42,7 @@ use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID}; use rustc_hir::intravisit::{self, Visitor}; use rustc_middle::dep_graph::{ - DepGraphQuery, DepKind, DepNode, DepNodeExt, DepNodeFilter, EdgeFilter, + dep_kinds, DepGraphQuery, DepKind, DepNode, DepNodeExt, DepNodeFilter, EdgeFilter, }; use rustc_middle::hir::nested_filter; use rustc_middle::ty::TyCtxt; @@ -129,7 +129,7 @@ impl<'tcx> IfThisChanged<'tcx> { let dep_node_interned = self.argument(attr); let dep_node = match dep_node_interned { None => { - DepNode::from_def_path_hash(self.tcx, def_path_hash, DepKind::hir_owner) + DepNode::from_def_path_hash(self.tcx, def_path_hash, dep_kinds::hir_owner) } Some(n) => { match DepNode::from_label_string(self.tcx, n.as_str(), def_path_hash) { diff --git a/compiler/rustc_incremental/src/persist/load.rs b/compiler/rustc_incremental/src/persist/load.rs index 8d67f692568..25e694fa1c1 100644 --- a/compiler/rustc_incremental/src/persist/load.rs +++ b/compiler/rustc_incremental/src/persist/load.rs @@ -3,7 +3,7 @@ use crate::errors; use rustc_data_structures::memmap::Mmap; use rustc_data_structures::unord::UnordMap; -use rustc_middle::dep_graph::{SerializedDepGraph, WorkProductMap}; +use rustc_middle::dep_graph::{DepsType, SerializedDepGraph, WorkProductMap}; use rustc_middle::query::on_disk_cache::OnDiskCache; use rustc_serialize::opaque::MemDecoder; use rustc_serialize::Decodable; @@ -208,7 +208,7 @@ pub fn load_dep_graph(sess: &Session) -> DepGraphFuture { 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_interface/src/callbacks.rs b/compiler/rustc_interface/src/callbacks.rs index bc6d7c20997..45b1aeb4a5c 100644 --- a/compiler/rustc_interface/src/callbacks.rs +++ b/compiler/rustc_interface/src/callbacks.rs @@ -10,8 +10,10 @@ //! origin crate when the `TyCtxt` is not present in TLS. use rustc_errors::{Diagnostic, TRACK_DIAGNOSTICS}; -use rustc_middle::dep_graph::TaskDepsRef; +use rustc_middle::dep_graph::{DepNodeExt, TaskDepsRef}; use rustc_middle::ty::tls; +use rustc_query_system::dep_graph::dep_node::default_dep_kind_debug; +use rustc_query_system::dep_graph::{DepContext, DepKind, DepNode}; use std::fmt; fn track_span_parent(def_id: rustc_span::def_id::LocalDefId) { @@ -59,10 +61,49 @@ fn def_id_debug(def_id: rustc_hir::def_id::DefId, f: &mut fmt::Formatter<'_>) -> write!(f, ")") } +/// This is a callback from `rustc_query_system` as it cannot access the implicit state +/// in `rustc_middle` otherwise. +pub fn dep_kind_debug(kind: DepKind, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + tls::with_opt(|opt_tcx| { + if let Some(tcx) = opt_tcx { + write!(f, "{}", tcx.dep_kind_info(kind).name) + } else { + default_dep_kind_debug(kind, f) + } + }) +} + +/// This is a callback from `rustc_query_system` as it cannot access the implicit state +/// in `rustc_middle` otherwise. +pub fn dep_node_debug(node: DepNode, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{:?}(", node.kind)?; + + tls::with_opt(|opt_tcx| { + if let Some(tcx) = opt_tcx { + if let Some(def_id) = node.extract_def_id(tcx) { + write!(f, "{}", tcx.def_path_debug_str(def_id))?; + } else if let Some(ref s) = tcx.dep_graph.dep_node_debug_str(node) { + write!(f, "{s}")?; + } else { + write!(f, "{}", node.hash)?; + } + } else { + write!(f, "{}", node.hash)?; + } + Ok(()) + })?; + + write!(f, ")") +} + /// Sets up the callbacks in prior crates which we want to refer to the /// TyCtxt in. pub fn setup_callbacks() { rustc_span::SPAN_TRACK.swap(&(track_span_parent as fn(_))); rustc_hir::def_id::DEF_ID_DEBUG.swap(&(def_id_debug as fn(_, &mut fmt::Formatter<'_>) -> _)); + rustc_query_system::dep_graph::dep_node::DEP_KIND_DEBUG + .swap(&(dep_kind_debug as fn(_, &mut fmt::Formatter<'_>) -> _)); + rustc_query_system::dep_graph::dep_node::DEP_NODE_DEBUG + .swap(&(dep_node_debug as fn(_, &mut fmt::Formatter<'_>) -> _)); TRACK_DIAGNOSTICS.swap(&(track_diagnostic as _)); } diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index f964a8c76c0..e8c2fe5d178 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -126,8 +126,8 @@ macro_rules! provide_one { // External query providers call `crate_hash` in order to register a dependency // on the crate metadata. The exception is `crate_hash` itself, which obviously // doesn't need to do this (and can't, as it would cause a query cycle). - use rustc_middle::dep_graph::DepKind; - if DepKind::$name != DepKind::crate_hash && $tcx.dep_graph.is_fully_enabled() { + use rustc_middle::dep_graph::dep_kinds; + if dep_kinds::$name != dep_kinds::crate_hash && $tcx.dep_graph.is_fully_enabled() { $tcx.ensure().crate_hash($def_id.krate); } diff --git a/compiler/rustc_middle/src/dep_graph/dep_node.rs b/compiler/rustc_middle/src/dep_graph/dep_node.rs index 78a0f82db13..39d82c489d5 100644 --- a/compiler/rustc_middle/src/dep_graph/dep_node.rs +++ b/compiler/rustc_middle/src/dep_graph/dep_node.rs @@ -65,9 +65,9 @@ use rustc_hir::definitions::DefPathHash; use rustc_hir::{HirId, ItemLocalId, OwnerId}; use rustc_query_system::dep_graph::FingerprintStyle; use rustc_span::symbol::Symbol; -use std::hash::Hash; -pub use rustc_query_system::dep_graph::{DepContext, DepNodeParams}; +pub use rustc_query_system::dep_graph::dep_node::DepKind; +pub use rustc_query_system::dep_graph::{DepContext, DepNode, DepNodeParams}; macro_rules! define_dep_nodes { ( @@ -84,55 +84,39 @@ macro_rules! define_dep_nodes { // encoding. The derived Encodable/Decodable uses leb128 encoding which is // dense when only considering this enum. But DepKind is encoded in a larger // struct, and there we can take advantage of the unused bits in the u16. - #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] #[allow(non_camel_case_types)] - #[repr(u16)] - pub enum DepKind { + #[repr(u16)] // Must be kept in sync with the inner type of `DepKind`. + enum DepKindDefs { $( $( #[$attr] )* $variant),* } - impl DepKind { - // This const implements two things: A bounds check so that we can decode - // a DepKind from a u16 with just one check, and a const check that the - // discriminants of the variants have been assigned consecutively from 0 - // so that just the one comparison suffices to check that the u16 can be - // transmuted to a DepKind. - pub const VARIANTS: u16 = { - let deps: &[DepKind] = &[$(DepKind::$variant,)*]; - let mut i = 0; - while i < deps.len() { - if i as u16 != deps[i] as u16 { - panic!(); - } - i += 1; - } - deps.len() as u16 - }; + #[allow(non_upper_case_globals)] + pub mod dep_kinds { + use super::*; + + $( + // The `as u16` cast must be kept in sync with the inner type of `DepKind`. + pub const $variant: DepKind = DepKind::new(DepKindDefs::$variant as u16); + )* } - impl rustc_serialize::Encodable for DepKind { - #[inline] - fn encode(&self, s: &mut S) { - s.emit_u16(*self as u16); - } - } - - impl rustc_serialize::Decodable for DepKind { - #[inline] - fn decode(d: &mut D) -> DepKind { - let discrim = d.read_u16(); - assert!(discrim < DepKind::VARIANTS); - // SAFETY: DepKind::VARIANTS checks that the discriminant values permit - // this one check to soundly guard the transmute. - unsafe { - std::mem::transmute::(discrim) + // This checks that the discriminants of the variants have been assigned consecutively + // from 0 so that they can be used as a dense index. + pub const DEP_KIND_VARIANTS: u16 = { + let deps = &[$(dep_kinds::$variant,)*]; + let mut i = 0; + while i < deps.len() { + if i != deps[i].as_usize() { + panic!(); } + i += 1; } - } + deps.len() as u16 + }; pub(super) fn dep_kind_from_label_string(label: &str) -> Result { match label { - $(stringify!($variant) => Ok(DepKind::$variant),)* + $(stringify!($variant) => Ok(dep_kinds::$variant),)* _ => Err(()), } } @@ -158,12 +142,10 @@ rustc_query_append!(define_dep_nodes![ [] fn CompileMonoItem() -> (), ]); -static_assert_size!(DepKind, 2); - // WARNING: `construct` is generic and does not know that `CompileCodegenUnit` takes `Symbol`s as keys. // Be very careful changing this type signature! pub(crate) fn make_compile_codegen_unit(tcx: TyCtxt<'_>, name: Symbol) -> DepNode { - DepNode::construct(tcx, DepKind::CompileCodegenUnit, &name) + DepNode::construct(tcx, dep_kinds::CompileCodegenUnit, &name) } // WARNING: `construct` is generic and does not know that `CompileMonoItem` takes `MonoItem`s as keys. @@ -172,20 +154,9 @@ pub(crate) fn make_compile_mono_item<'tcx>( tcx: TyCtxt<'tcx>, mono_item: &MonoItem<'tcx>, ) -> DepNode { - DepNode::construct(tcx, DepKind::CompileMonoItem, mono_item) + DepNode::construct(tcx, dep_kinds::CompileMonoItem, mono_item) } -pub type DepNode = rustc_query_system::dep_graph::DepNode; - -// We keep a lot of `DepNode`s in memory during compilation. It's not -// required that their size stay the same, but we don't want to change -// it inadvertently. This assert just ensures we're aware of any change. -#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] -static_assert_size!(DepNode, 18); - -#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] -static_assert_size!(DepNode, 24); - pub trait DepNodeExt: Sized { /// Extracts the DefId corresponding to this DepNode. This will work /// if two conditions are met: diff --git a/compiler/rustc_middle/src/dep_graph/mod.rs b/compiler/rustc_middle/src/dep_graph/mod.rs index 87436f9eeed..76ef62f9f27 100644 --- a/compiler/rustc_middle/src/dep_graph/mod.rs +++ b/compiler/rustc_middle/src/dep_graph/mod.rs @@ -6,49 +6,24 @@ use rustc_session::Session; #[macro_use] mod dep_node; +pub use rustc_query_system::dep_graph::debug::EdgeFilter; pub use rustc_query_system::dep_graph::{ - debug::DepNodeFilter, hash_result, DepContext, DepNodeColor, DepNodeIndex, - SerializedDepNodeIndex, WorkProduct, WorkProductId, WorkProductMap, + debug::DepNodeFilter, hash_result, DepContext, DepGraphQuery, DepNodeColor, DepNodeIndex, Deps, + SerializedDepGraph, SerializedDepNodeIndex, TaskDeps, TaskDepsRef, WorkProduct, WorkProductId, + WorkProductMap, }; -pub use dep_node::{label_strs, DepKind, DepNode, DepNodeExt}; +pub use dep_node::{dep_kinds, label_strs, DepKind, DepNode, DepNodeExt}; pub(crate) use dep_node::{make_compile_codegen_unit, make_compile_mono_item}; -pub type DepGraph = rustc_query_system::dep_graph::DepGraph; +pub type DepGraph = rustc_query_system::dep_graph::DepGraph; -pub type TaskDeps = rustc_query_system::dep_graph::TaskDeps; -pub type TaskDepsRef<'a> = rustc_query_system::dep_graph::TaskDepsRef<'a, DepKind>; -pub type DepGraphQuery = rustc_query_system::dep_graph::DepGraphQuery; -pub type SerializedDepGraph = rustc_query_system::dep_graph::SerializedDepGraph; -pub type EdgeFilter = rustc_query_system::dep_graph::debug::EdgeFilter; pub type DepKindStruct<'tcx> = rustc_query_system::dep_graph::DepKindStruct>; -impl rustc_query_system::dep_graph::DepKind for DepKind { - const NULL: Self = DepKind::Null; - const RED: Self = DepKind::Red; - const MAX: u16 = DepKind::VARIANTS - 1; - - fn debug_node(node: &DepNode, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{:?}(", node.kind)?; - - ty::tls::with_opt(|opt_tcx| { - if let Some(tcx) = opt_tcx { - if let Some(def_id) = node.extract_def_id(tcx) { - write!(f, "{}", tcx.def_path_debug_str(def_id))?; - } else if let Some(ref s) = tcx.dep_graph.dep_node_debug_str(*node) { - write!(f, "{s}")?; - } else { - write!(f, "{}", node.hash)?; - } - } else { - write!(f, "{}", node.hash)?; - } - Ok(()) - })?; - - write!(f, ")") - } +#[derive(Clone)] +pub struct DepsType; +impl Deps for DepsType { fn with_deps(task_deps: TaskDepsRef<'_>, op: OP) -> R where OP: FnOnce() -> R, @@ -70,24 +45,13 @@ impl rustc_query_system::dep_graph::DepKind for DepKind { }) } - #[track_caller] - #[inline] - fn from_u16(u: u16) -> Self { - if u > Self::MAX { - panic!("Invalid DepKind {u}"); - } - // SAFETY: See comment on DepKind::VARIANTS - unsafe { std::mem::transmute(u) } - } - - #[inline] - fn to_u16(self) -> u16 { - self as u16 - } + const DEP_KIND_NULL: DepKind = dep_kinds::Null; + const DEP_KIND_RED: DepKind = dep_kinds::Red; + const DEP_KIND_MAX: u16 = dep_node::DEP_KIND_VARIANTS - 1; } impl<'tcx> DepContext for TyCtxt<'tcx> { - type DepKind = DepKind; + type Deps = DepsType; #[inline] fn with_stable_hashing_context(self, f: impl FnOnce(StableHashingContext<'_>) -> R) -> R { @@ -111,6 +75,6 @@ impl<'tcx> DepContext for TyCtxt<'tcx> { #[inline] fn dep_kind_info(&self, dk: DepKind) -> &DepKindStruct<'tcx> { - &self.query_kinds[dk as usize] + &self.query_kinds[dk.as_usize()] } } diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 0241820ab72..0238d27e9d8 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -7,7 +7,6 @@ #![allow(unused_parens)] use crate::dep_graph; -use crate::dep_graph::DepKind; use crate::infer::canonical::{self, Canonical}; use crate::lint::LintExpectation; use crate::metadata::ModChild; diff --git a/compiler/rustc_middle/src/query/plumbing.rs b/compiler/rustc_middle/src/query/plumbing.rs index a342b5231e9..34e5b02ba5b 100644 --- a/compiler/rustc_middle/src/query/plumbing.rs +++ b/compiler/rustc_middle/src/query/plumbing.rs @@ -37,7 +37,7 @@ pub struct DynamicQuery<'tcx, C: QueryCache> { pub eval_always: bool, pub dep_kind: DepKind, pub handle_cycle_error: HandleCycleError, - pub query_state: FieldOffset, QueryState>, + pub query_state: FieldOffset, QueryState>, pub query_cache: FieldOffset, C>, pub cache_on_disk: fn(tcx: TyCtxt<'tcx>, key: &C::Key) -> bool, pub execute_query: fn(tcx: TyCtxt<'tcx>, k: C::Key) -> C::Value, @@ -53,7 +53,7 @@ pub struct DynamicQuery<'tcx, C: QueryCache> { fn(tcx: TyCtxt<'tcx>, key: &C::Key, index: SerializedDepNodeIndex) -> bool, pub hash_result: HashResult, pub value_from_cycle_error: - fn(tcx: TyCtxt<'tcx>, cycle: &[QueryInfo], guar: ErrorGuaranteed) -> C::Value, + fn(tcx: TyCtxt<'tcx>, cycle: &[QueryInfo], guar: ErrorGuaranteed) -> C::Value, pub format_value: fn(&C::Value) -> String, } @@ -402,7 +402,7 @@ macro_rules! define_callbacks { #[derive(Default)] pub struct QueryStates<'tcx> { $( - pub $name: QueryState<$($K)*, DepKind>, + pub $name: QueryState<$($K)*>, )* } @@ -516,7 +516,7 @@ macro_rules! define_feedable { } } None => { - let dep_node = dep_graph::DepNode::construct(tcx, dep_graph::DepKind::$name, &key); + let dep_node = dep_graph::DepNode::construct(tcx, dep_graph::dep_kinds::$name, &key); let dep_node_index = tcx.dep_graph.with_feed_task( dep_node, tcx, diff --git a/compiler/rustc_middle/src/values.rs b/compiler/rustc_middle/src/values.rs index 962faf56cb8..dec06363380 100644 --- a/compiler/rustc_middle/src/values.rs +++ b/compiler/rustc_middle/src/values.rs @@ -1,4 +1,4 @@ -use crate::dep_graph::DepKind; +use crate::dep_graph::dep_kinds; use crate::query::plumbing::CyclePlaceholder; use rustc_data_structures::fx::FxHashSet; use rustc_errors::{pluralize, struct_span_err, Applicability, MultiSpan}; @@ -13,34 +13,22 @@ use rustc_span::{ErrorGuaranteed, Span}; use std::fmt::Write; -impl<'tcx> Value, DepKind> for Ty<'_> { - fn from_cycle_error( - tcx: TyCtxt<'tcx>, - _: &[QueryInfo], - guar: ErrorGuaranteed, - ) -> Self { +impl<'tcx> Value> for Ty<'_> { + fn from_cycle_error(tcx: TyCtxt<'tcx>, _: &[QueryInfo], guar: ErrorGuaranteed) -> Self { // SAFETY: This is never called when `Self` is not `Ty<'tcx>`. // FIXME: Represent the above fact in the trait system somehow. unsafe { std::mem::transmute::, Ty<'_>>(Ty::new_error(tcx, guar)) } } } -impl<'tcx> Value, DepKind> for Result>, CyclePlaceholder> { - fn from_cycle_error( - _tcx: TyCtxt<'tcx>, - _: &[QueryInfo], - guar: ErrorGuaranteed, - ) -> Self { +impl<'tcx> Value> for Result>, CyclePlaceholder> { + fn from_cycle_error(_tcx: TyCtxt<'tcx>, _: &[QueryInfo], guar: ErrorGuaranteed) -> Self { Err(CyclePlaceholder(guar)) } } -impl<'tcx> Value, DepKind> for ty::SymbolName<'_> { - fn from_cycle_error( - tcx: TyCtxt<'tcx>, - _: &[QueryInfo], - _guar: ErrorGuaranteed, - ) -> Self { +impl<'tcx> Value> for ty::SymbolName<'_> { + fn from_cycle_error(tcx: TyCtxt<'tcx>, _: &[QueryInfo], _guar: ErrorGuaranteed) -> Self { // SAFETY: This is never called when `Self` is not `SymbolName<'tcx>`. // FIXME: Represent the above fact in the trait system somehow. unsafe { @@ -51,16 +39,12 @@ impl<'tcx> Value, DepKind> for ty::SymbolName<'_> { } } -impl<'tcx> Value, DepKind> for ty::Binder<'_, ty::FnSig<'_>> { - fn from_cycle_error( - tcx: TyCtxt<'tcx>, - stack: &[QueryInfo], - guar: ErrorGuaranteed, - ) -> Self { +impl<'tcx> Value> for ty::Binder<'_, ty::FnSig<'_>> { + fn from_cycle_error(tcx: TyCtxt<'tcx>, stack: &[QueryInfo], guar: ErrorGuaranteed) -> Self { let err = Ty::new_error(tcx, guar); let arity = if let Some(frame) = stack.get(0) - && frame.query.dep_kind == DepKind::fn_sig + && frame.query.dep_kind == dep_kinds::fn_sig && let Some(def_id) = frame.query.def_id && let Some(node) = tcx.hir().get_if_local(def_id) && let Some(sig) = node.fn_sig() @@ -85,16 +69,12 @@ impl<'tcx> Value, DepKind> for ty::Binder<'_, ty::FnSig<'_>> { } } -impl<'tcx> Value, DepKind> for Representability { - fn from_cycle_error( - tcx: TyCtxt<'tcx>, - cycle: &[QueryInfo], - _guar: ErrorGuaranteed, - ) -> Self { +impl<'tcx> Value> for Representability { + fn from_cycle_error(tcx: TyCtxt<'tcx>, cycle: &[QueryInfo], _guar: ErrorGuaranteed) -> Self { let mut item_and_field_ids = Vec::new(); let mut representable_ids = FxHashSet::default(); for info in cycle { - if info.query.dep_kind == DepKind::representability + if info.query.dep_kind == dep_kinds::representability && let Some(field_id) = info.query.def_id && let Some(field_id) = field_id.as_local() && let Some(DefKind::Field) = info.query.def_kind @@ -108,7 +88,7 @@ impl<'tcx> Value, DepKind> for Representability { } } for info in cycle { - if info.query.dep_kind == DepKind::representability_adt_ty + if info.query.dep_kind == dep_kinds::representability_adt_ty && let Some(def_id) = info.query.ty_adt_id && let Some(def_id) = def_id.as_local() && !item_and_field_ids.iter().any(|&(id, _)| id == def_id) @@ -121,32 +101,20 @@ impl<'tcx> Value, DepKind> for Representability { } } -impl<'tcx> Value, DepKind> for ty::EarlyBinder> { - fn from_cycle_error( - tcx: TyCtxt<'tcx>, - cycle: &[QueryInfo], - guar: ErrorGuaranteed, - ) -> Self { +impl<'tcx> Value> for ty::EarlyBinder> { + fn from_cycle_error(tcx: TyCtxt<'tcx>, cycle: &[QueryInfo], guar: ErrorGuaranteed) -> Self { ty::EarlyBinder::bind(Ty::from_cycle_error(tcx, cycle, guar)) } } -impl<'tcx> Value, DepKind> for ty::EarlyBinder>> { - fn from_cycle_error( - tcx: TyCtxt<'tcx>, - cycle: &[QueryInfo], - guar: ErrorGuaranteed, - ) -> Self { +impl<'tcx> Value> for ty::EarlyBinder>> { + fn from_cycle_error(tcx: TyCtxt<'tcx>, cycle: &[QueryInfo], guar: ErrorGuaranteed) -> Self { ty::EarlyBinder::bind(ty::Binder::from_cycle_error(tcx, cycle, guar)) } } -impl<'tcx, T> Value, DepKind> for Result> { - fn from_cycle_error( - _tcx: TyCtxt<'tcx>, - _cycle: &[QueryInfo], - _guar: ErrorGuaranteed, - ) -> Self { +impl<'tcx, T> Value> for Result> { + fn from_cycle_error(_tcx: TyCtxt<'tcx>, _cycle: &[QueryInfo], _guar: ErrorGuaranteed) -> Self { // tcx.arena.alloc cannot be used because we are not allowed to use &'tcx LayoutError under // min_specialization. Since this is an error path anyways, leaking doesn't matter (and really, // tcx.arena.alloc is pretty much equal to leaking). diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs index 9a0fcbb37a7..30621a135eb 100644 --- a/compiler/rustc_query_impl/src/lib.rs +++ b/compiler/rustc_query_impl/src/lib.rs @@ -92,7 +92,7 @@ where } #[inline(always)] - fn query_state<'a>(self, qcx: QueryCtxt<'tcx>) -> &'a QueryState + fn query_state<'a>(self, qcx: QueryCtxt<'tcx>) -> &'a QueryState where QueryCtxt<'tcx>: 'a, { @@ -145,7 +145,7 @@ where fn value_from_cycle_error( self, tcx: TyCtxt<'tcx>, - cycle: &[QueryInfo], + cycle: &[QueryInfo], guar: ErrorGuaranteed, ) -> Self::Value { (self.dynamic.value_from_cycle_error)(tcx, cycle, guar) @@ -198,6 +198,8 @@ trait QueryConfigRestored<'tcx> { type RestoredValue; type Config: QueryConfig>; + const NAME: &'static &'static str; + fn config(tcx: TyCtxt<'tcx>) -> Self::Config; fn restore(value: >>::Value) -> Self::RestoredValue; diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index f2fdf066d15..4516708ce17 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -8,7 +8,9 @@ use crate::QueryConfigRestored; use rustc_data_structures::stable_hasher::{Hash64, HashStable, StableHasher}; use rustc_data_structures::sync::Lock; use rustc_errors::Diagnostic; + use rustc_index::Idx; +use rustc_middle::dep_graph::dep_kinds; use rustc_middle::dep_graph::{ self, DepKind, DepKindStruct, DepNode, DepNodeIndex, SerializedDepNodeIndex, }; @@ -53,7 +55,7 @@ impl<'tcx> std::ops::Deref for QueryCtxt<'tcx> { } impl<'tcx> HasDepContext for QueryCtxt<'tcx> { - type DepKind = rustc_middle::dep_graph::DepKind; + type Deps = rustc_middle::dep_graph::DepsType; type DepContext = TyCtxt<'tcx>; #[inline] @@ -78,7 +80,7 @@ impl QueryContext for QueryCtxt<'_> { tls::with_related_context(self.tcx, |icx| icx.query) } - fn try_collect_active_jobs(self) -> Option> { + fn try_collect_active_jobs(self) -> Option { let mut jobs = QueryMap::default(); for collect in super::TRY_COLLECT_ACTIVE_JOBS.iter() { @@ -154,7 +156,7 @@ impl QueryContext for QueryCtxt<'_> { let mut span = None; let mut layout_of_depth = None; if let Some(map) = self.try_collect_active_jobs() { - if let Some((info, depth)) = job.try_find_layout_root(map) { + if let Some((info, depth)) = job.try_find_layout_root(map, dep_kinds::layout_of) { span = Some(info.job.span); layout_of_depth = Some(LayoutOfDepth { desc: info.query.description, depth }); } @@ -300,7 +302,7 @@ pub(crate) fn create_query_frame< key: K, kind: DepKind, name: &'static str, -) -> QueryStackFrame { +) -> QueryStackFrame { // Avoid calling queries while formatting the description let description = ty::print::with_no_queries!( // Disable visible paths printing for performance reasons. @@ -312,7 +314,7 @@ pub(crate) fn create_query_frame< ); let description = if tcx.sess.verbose() { format!("{description} [{name:?}]") } else { description }; - let span = if kind == dep_graph::DepKind::def_span || with_no_queries() { + let span = if kind == dep_graph::dep_kinds::def_span || with_no_queries() { // The `def_span` query is used to calculate `default_span`, // so exit to avoid infinite recursion. None @@ -320,7 +322,7 @@ pub(crate) fn create_query_frame< Some(key.default_span(tcx)) }; let def_id = key.key_as_def_id(); - let def_kind = if kind == dep_graph::DepKind::opt_def_kind || with_no_queries() { + let def_kind = if kind == dep_graph::dep_kinds::opt_def_kind || with_no_queries() { // Try to avoid infinite recursion. None } else { @@ -329,7 +331,7 @@ pub(crate) fn create_query_frame< let hash = || { tcx.with_stable_hashing_context(|mut hcx| { let mut hasher = StableHasher::new(); - std::mem::discriminant(&kind).hash_stable(&mut hcx, &mut hasher); + kind.as_usize().hash_stable(&mut hcx, &mut hasher); key.hash_stable(&mut hcx, &mut hasher); hasher.finish::() }) @@ -430,8 +432,8 @@ where // hit the cache instead of having to go through `force_from_dep_node`. // This assertion makes sure, we actually keep applying the solution above. debug_assert!( - dep_node.kind != DepKind::codegen_unit, - "calling force_from_dep_node() on DepKind::codegen_unit" + dep_node.kind != dep_kinds::codegen_unit, + "calling force_from_dep_node() on dep_kinds::codegen_unit" ); if let Some(key) = Q::Key::recover(tcx, &dep_node) { @@ -457,6 +459,7 @@ where fingerprint_style, force_from_dep_node: None, try_load_from_on_disk_cache: None, + name: Q::NAME, }; } @@ -470,6 +473,7 @@ where try_load_from_on_disk_cache: Some(|tcx, dep_node| { try_load_from_on_disk_cache(Q::config(tcx), tcx, dep_node) }), + name: Q::NAME, } } @@ -565,7 +569,7 @@ macro_rules! define_queries { DynamicQuery { name: stringify!($name), eval_always: is_eval_always!([$($modifiers)*]), - dep_kind: dep_graph::DepKind::$name, + dep_kind: dep_graph::dep_kinds::$name, handle_cycle_error: handle_cycle_error!([$($modifiers)*]), query_state: offset_of!(QueryStates<'tcx> => $name), query_cache: offset_of!(QueryCaches<'tcx> => $name), @@ -636,6 +640,8 @@ macro_rules! define_queries { { feedable!([$($modifiers)*]) }, >; + const NAME: &'static &'static str = &stringify!($name); + #[inline(always)] fn config(tcx: TyCtxt<'tcx>) -> Self::Config { DynamicConfig { @@ -649,9 +655,9 @@ macro_rules! define_queries { } } - pub fn try_collect_active_jobs<'tcx>(tcx: TyCtxt<'tcx>, qmap: &mut QueryMap) { + pub fn try_collect_active_jobs<'tcx>(tcx: TyCtxt<'tcx>, qmap: &mut QueryMap) { let make_query = |tcx, key| { - let kind = rustc_middle::dep_graph::DepKind::$name; + let kind = rustc_middle::dep_graph::dep_kinds::$name; let name = stringify!($name); $crate::plumbing::create_query_frame(tcx, rustc_middle::query::descs::$name, key, kind, name) }; @@ -709,7 +715,7 @@ macro_rules! define_queries { // These arrays are used for iteration and can't be indexed by `DepKind`. - const TRY_COLLECT_ACTIVE_JOBS: &[for<'tcx> fn(TyCtxt<'tcx>, &mut QueryMap)] = + const TRY_COLLECT_ACTIVE_JOBS: &[for<'tcx> fn(TyCtxt<'tcx>, &mut QueryMap)] = &[$(query_impl::$name::try_collect_active_jobs),*]; const ALLOC_SELF_PROFILE_QUERY_STRINGS: &[ @@ -737,6 +743,7 @@ macro_rules! define_queries { fingerprint_style: FingerprintStyle::Unit, force_from_dep_node: Some(|_, dep_node| bug!("force_from_dep_node: encountered {:?}", dep_node)), try_load_from_on_disk_cache: None, + name: &"Null", } } @@ -748,6 +755,7 @@ macro_rules! define_queries { fingerprint_style: FingerprintStyle::Unit, force_from_dep_node: Some(|_, dep_node| bug!("force_from_dep_node: encountered {:?}", dep_node)), try_load_from_on_disk_cache: None, + name: &"Red", } } @@ -758,6 +766,7 @@ macro_rules! define_queries { fingerprint_style: FingerprintStyle::Unit, force_from_dep_node: None, try_load_from_on_disk_cache: None, + name: &"TraitSelect", } } @@ -768,6 +777,7 @@ macro_rules! define_queries { fingerprint_style: FingerprintStyle::Opaque, force_from_dep_node: None, try_load_from_on_disk_cache: None, + name: &"CompileCodegenUnit", } } @@ -778,6 +788,7 @@ macro_rules! define_queries { fingerprint_style: FingerprintStyle::Opaque, force_from_dep_node: None, try_load_from_on_disk_cache: None, + name: &"CompileMonoItem", } } diff --git a/compiler/rustc_query_system/src/dep_graph/debug.rs b/compiler/rustc_query_system/src/dep_graph/debug.rs index c2c9600f555..103a6c01bd2 100644 --- a/compiler/rustc_query_system/src/dep_graph/debug.rs +++ b/compiler/rustc_query_system/src/dep_graph/debug.rs @@ -1,6 +1,6 @@ //! Code for debugging the dep-graph. -use super::{DepKind, DepNode, DepNodeIndex}; +use super::{DepNode, DepNodeIndex}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::Lock; use std::error::Error; @@ -28,7 +28,7 @@ impl DepNodeFilter { } /// Tests whether `node` meets the filter, returning true if so. - pub fn test(&self, node: &DepNode) -> bool { + pub fn test(&self, node: &DepNode) -> bool { let debug_str = format!("{node:?}"); self.text.split('&').map(|s| s.trim()).all(|f| debug_str.contains(f)) } @@ -36,14 +36,14 @@ impl DepNodeFilter { /// A filter like `F -> G` where `F` and `G` are valid dep-node /// filters. This can be used to test the source/target independently. -pub struct EdgeFilter { +pub struct EdgeFilter { pub source: DepNodeFilter, pub target: DepNodeFilter, - pub index_to_node: Lock>>, + pub index_to_node: Lock>, } -impl EdgeFilter { - pub fn new(test: &str) -> Result, Box> { +impl EdgeFilter { + pub fn new(test: &str) -> Result> { let parts: Vec<_> = test.split("->").collect(); if parts.len() != 2 { Err(format!("expected a filter like `a&b -> c&d`, not `{test}`").into()) @@ -57,7 +57,7 @@ impl EdgeFilter { } #[cfg(debug_assertions)] - pub fn test(&self, source: &DepNode, target: &DepNode) -> bool { + pub fn test(&self, source: &DepNode, target: &DepNode) -> bool { self.source.test(source) && self.target.test(target) } } diff --git a/compiler/rustc_query_system/src/dep_graph/dep_node.rs b/compiler/rustc_query_system/src/dep_graph/dep_node.rs index 39a4cb1b179..17f96896a50 100644 --- a/compiler/rustc_query_system/src/dep_graph/dep_node.rs +++ b/compiler/rustc_query_system/src/dep_graph/dep_node.rs @@ -42,36 +42,84 @@ //! `DefId` it was computed from. In other cases, too much information gets //! lost during fingerprint computation. -use super::{DepContext, DepKind, FingerprintStyle}; +use super::{DepContext, FingerprintStyle}; use crate::ich::StableHashingContext; use rustc_data_structures::fingerprint::{Fingerprint, PackedFingerprint}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableOrd, ToStableHashKey}; +use rustc_data_structures::AtomicRef; use rustc_hir::definitions::DefPathHash; use std::fmt; use std::hash::Hash; -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable)] -pub struct DepNode { - pub kind: K, +/// This serves as an index into arrays built by `make_dep_kind_array`. +#[derive(Clone, Copy, PartialEq, Eq, Hash)] +pub struct DepKind { + variant: u16, +} + +impl DepKind { + #[inline] + pub const fn new(variant: u16) -> Self { + Self { variant } + } + + #[inline] + pub const fn as_inner(&self) -> u16 { + self.variant + } + + #[inline] + pub const fn as_usize(&self) -> usize { + self.variant as usize + } +} + +static_assert_size!(DepKind, 2); + +pub fn default_dep_kind_debug(kind: DepKind, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("DepKind").field("variant", &kind.variant).finish() +} + +pub static DEP_KIND_DEBUG: AtomicRef) -> fmt::Result> = + AtomicRef::new(&(default_dep_kind_debug as fn(_, &mut fmt::Formatter<'_>) -> _)); + +impl fmt::Debug for DepKind { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + (*DEP_KIND_DEBUG)(*self, f) + } +} + +#[derive(Clone, Copy, PartialEq, Eq, Hash)] +pub struct DepNode { + pub kind: DepKind, pub hash: PackedFingerprint, } -impl DepNode { +// We keep a lot of `DepNode`s in memory during compilation. It's not +// required that their size stay the same, but we don't want to change +// it inadvertently. This assert just ensures we're aware of any change. +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +static_assert_size!(DepNode, 18); + +#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] +static_assert_size!(DepNode, 24); + +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: K) -> DepNode + pub fn new_no_params(tcx: Tcx, kind: DepKind) -> DepNode where - Tcx: super::DepContext, + Tcx: super::DepContext, { debug_assert_eq!(tcx.fingerprint_style(kind), FingerprintStyle::Unit); DepNode { kind, hash: Fingerprint::ZERO.into() } } - pub fn construct(tcx: Tcx, kind: K, arg: &Key) -> DepNode + pub fn construct(tcx: Tcx, kind: DepKind, arg: &Key) -> DepNode where - Tcx: super::DepContext, + Tcx: super::DepContext, Key: DepNodeParams, { let hash = arg.to_fingerprint(tcx); @@ -93,18 +141,25 @@ 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: K) -> Self + pub fn from_def_path_hash(tcx: Tcx, def_path_hash: DefPathHash, kind: DepKind) -> Self where - Tcx: super::DepContext, + Tcx: super::DepContext, { debug_assert!(tcx.fingerprint_style(kind) == FingerprintStyle::DefPathHash); DepNode { kind, hash: def_path_hash.0.into() } } } -impl fmt::Debug for DepNode { +pub fn default_dep_node_debug(node: DepNode, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("DepNode").field("kind", &node.kind).field("hash", &node.hash).finish() +} + +pub static DEP_NODE_DEBUG: AtomicRef) -> fmt::Result> = + AtomicRef::new(&(default_dep_node_debug as fn(_, &mut fmt::Formatter<'_>) -> _)); + +impl fmt::Debug for DepNode { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - K::debug_node(self, f) + (*DEP_NODE_DEBUG)(*self, f) } } @@ -129,7 +184,7 @@ pub trait DepNodeParams: 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: Tcx, dep_node: &DepNode) -> Option; } impl DepNodeParams for T @@ -156,7 +211,7 @@ where } #[inline(always)] - default fn recover(_: Tcx, _: &DepNode) -> Option { + default fn recover(_: Tcx, _: &DepNode) -> Option { None } } @@ -216,10 +271,13 @@ pub struct DepKindStruct { /// 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 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, + + /// The name of this dep kind. + pub name: &'static &'static str, } /// A "work product" corresponds to a `.o` (or other) file that we diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs index fa54e1a2e6a..c7e92d7b2b2 100644 --- a/compiler/rustc_query_system/src/dep_graph/graph.rs +++ b/compiler/rustc_query_system/src/dep_graph/graph.rs @@ -17,7 +17,7 @@ use std::sync::atomic::Ordering::Relaxed; use super::query::DepGraphQuery; use super::serialized::{GraphEncoder, SerializedDepGraph, SerializedDepNodeIndex}; -use super::{DepContext, DepKind, DepNode, HasDepContext, WorkProductId}; +use super::{DepContext, DepKind, DepNode, Deps, HasDepContext, WorkProductId}; use crate::dep_graph::EdgesVec; use crate::ich::StableHashingContext; use crate::query::{QueryContext, QuerySideEffects}; @@ -26,8 +26,8 @@ use crate::query::{QueryContext, QuerySideEffects}; use {super::debug::EdgeFilter, std::env}; #[derive(Clone)] -pub struct DepGraph { - data: Option>>, +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 @@ -74,16 +74,16 @@ impl DepNodeColor { } } -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. - previous: SerializedDepGraph, + previous: SerializedDepGraph, colors: DepNodeColorMap, @@ -95,12 +95,12 @@ pub struct DepGraphData { /// this map. We can later look for and extract that data. previous_work_products: WorkProductMap, - dep_node_debug: Lock, String>>, + dep_node_debug: Lock>, /// Used by incremental compilation tests to assert that /// a particular query result was decoded from disk /// (not just marked green) - debug_loaded_from_disk: Lock>>, + debug_loaded_from_disk: Lock>, } pub fn hash_result(hcx: &mut StableHashingContext<'_>, result: &R) -> Fingerprint @@ -112,15 +112,15 @@ where stable_hasher.finish() } -impl DepGraph { +impl DepGraph { pub fn new( profiler: &SelfProfilerRef, - prev_graph: SerializedDepGraph, + prev_graph: SerializedDepGraph, prev_work_products: WorkProductMap, encoder: FileEncoder, record_graph: bool, record_stats: bool, - ) -> DepGraph { + ) -> DepGraph { let prev_graph_node_count = prev_graph.node_count(); let current = CurrentDepGraph::new( @@ -136,7 +136,7 @@ impl DepGraph { // Instantiate a dependy-less node only once for anonymous queries. let _green_node_index = current.intern_new_node( profiler, - DepNode { kind: DepKind::NULL, hash: current.anon_id_seed.into() }, + DepNode { kind: D::DEP_KIND_NULL, hash: current.anon_id_seed.into() }, EdgesVec::new(), Fingerprint::ZERO, ); @@ -146,7 +146,7 @@ impl DepGraph { let (red_node_index, red_node_prev_index_and_color) = current.intern_node( profiler, &prev_graph, - DepNode { kind: DepKind::RED, hash: Fingerprint::ZERO.into() }, + DepNode { kind: D::DEP_KIND_RED, hash: Fingerprint::ZERO.into() }, EdgesVec::new(), None, false, @@ -181,12 +181,12 @@ impl DepGraph { } } - pub fn new_disabled() -> DepGraph { + pub fn new_disabled() -> DepGraph { DepGraph { data: None, virtual_dep_node_index: Lrc::new(AtomicU32::new(0)) } } #[inline] - pub fn data(&self) -> Option<&DepGraphData> { + pub fn data(&self) -> Option<&DepGraphData> { self.data.as_deref() } @@ -196,7 +196,7 @@ impl DepGraph { self.data.is_some() } - pub fn with_query(&self, f: impl Fn(&DepGraphQuery)) { + pub fn with_query(&self, f: impl Fn(&DepGraphQuery)) { if let Some(data) = &self.data { data.current.encoder.borrow().with_query(f) } @@ -204,7 +204,7 @@ impl DepGraph { pub fn assert_ignored(&self) { if let Some(..) = self.data { - K::read_deps(|task_deps| { + D::read_deps(|task_deps| { assert_matches!( task_deps, TaskDepsRef::Ignore, @@ -218,7 +218,7 @@ impl DepGraph { where OP: FnOnce() -> R, { - K::with_deps(TaskDepsRef::Ignore, op) + D::with_deps(TaskDepsRef::Ignore, op) } /// Used to wrap the deserialization of a query result from disk, @@ -271,13 +271,13 @@ impl DepGraph { where OP: FnOnce() -> R, { - K::with_deps(TaskDepsRef::Forbid, op) + D::with_deps(TaskDepsRef::Forbid, op) } #[inline(always)] - pub fn with_task, A: Debug, R>( + pub fn with_task, A: Debug, R>( &self, - key: DepNode, + key: DepNode, cx: Ctxt, arg: A, task: fn(Ctxt, A) -> R, @@ -289,10 +289,10 @@ impl DepGraph { } } - pub fn with_anon_task, OP, R>( + pub fn with_anon_task, OP, R>( &self, cx: Tcx, - dep_kind: K, + dep_kind: DepKind, op: OP, ) -> (R, DepNodeIndex) where @@ -305,7 +305,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 @@ -334,9 +334,9 @@ impl DepGraphData { /// /// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/incremental-compilation.html #[inline(always)] - pub fn with_task, A: Debug, R>( + pub fn with_task, A: Debug, R>( &self, - key: DepNode, + key: DepNode, cx: Ctxt, arg: A, task: fn(Ctxt, A) -> R, @@ -354,7 +354,7 @@ impl DepGraphData { - dep-node: {key:?}" ); - let with_deps = |task_deps| K::with_deps(task_deps, || task(cx, arg)); + let with_deps = |task_deps| D::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 { @@ -402,10 +402,10 @@ impl DepGraphData { /// Executes something within an "anonymous" task, that is, a task the /// `DepNode` of which is determined by the list of inputs it read from. - pub fn with_anon_task, OP, R>( + pub fn with_anon_task, OP, R>( &self, cx: Tcx, - dep_kind: K, + dep_kind: DepKind, op: OP, ) -> (R, DepNodeIndex) where @@ -414,7 +414,7 @@ impl DepGraphData { debug_assert!(!cx.is_eval_always(dep_kind)); let task_deps = Lock::new(TaskDeps::default()); - let result = K::with_deps(TaskDepsRef::Allow(&task_deps), op); + let result = D::with_deps(TaskDepsRef::Allow(&task_deps), op); let task_deps = task_deps.into_inner(); let task_deps = task_deps.reads; @@ -461,11 +461,11 @@ impl DepGraphData { } } -impl DepGraph { +impl DepGraph { #[inline] pub fn read_index(&self, dep_node_index: DepNodeIndex) { if let Some(ref data) = self.data { - K::read_deps(|task_deps| { + D::read_deps(|task_deps| { let mut task_deps = match task_deps { TaskDepsRef::Allow(deps) => deps.lock(), TaskDepsRef::EvalAlways => { @@ -532,9 +532,9 @@ 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, A: Debug, R: Debug>( + pub fn with_feed_task, A: Debug, R: Debug>( &self, - node: DepNode, + node: DepNode, cx: Ctxt, key: A, result: &R, @@ -573,7 +573,7 @@ impl DepGraph { } let mut edges = EdgesVec::new(); - K::read_deps(|task_deps| match task_deps { + D::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); @@ -623,9 +623,9 @@ impl DepGraph { } } -impl DepGraphData { +impl DepGraphData { #[inline] - pub fn dep_node_index_of_opt(&self, dep_node: &DepNode) -> Option { + pub fn dep_node_index_of_opt(&self, dep_node: &DepNode) -> Option { if let Some(prev_index) = self.previous.node_to_index_opt(dep_node) { self.current.prev_index_to_index.lock()[prev_index] } else { @@ -634,11 +634,11 @@ impl DepGraphData { } #[inline] - pub fn dep_node_exists(&self, dep_node: &DepNode) -> bool { + pub fn dep_node_exists(&self, dep_node: &DepNode) -> bool { self.dep_node_index_of_opt(dep_node).is_some() } - fn node_color(&self, dep_node: &DepNode) -> Option { + fn node_color(&self, dep_node: &DepNode) -> Option { if let Some(prev_index) = self.previous.node_to_index_opt(dep_node) { self.colors.get(prev_index) } else { @@ -660,18 +660,18 @@ impl DepGraphData { } #[inline] - pub fn prev_node_of(&self, prev_index: SerializedDepNodeIndex) -> DepNode { + pub fn prev_node_of(&self, prev_index: SerializedDepNodeIndex) -> DepNode { self.previous.index_to_node(prev_index) } - pub fn mark_debug_loaded_from_disk(&self, dep_node: DepNode) { + pub fn mark_debug_loaded_from_disk(&self, dep_node: DepNode) { self.debug_loaded_from_disk.lock().insert(dep_node); } } -impl DepGraph { +impl DepGraph { #[inline] - pub fn dep_node_exists(&self, dep_node: &DepNode) -> bool { + pub fn dep_node_exists(&self, dep_node: &DepNode) -> bool { self.data.as_ref().is_some_and(|data| data.dep_node_exists(dep_node)) } @@ -687,12 +687,12 @@ impl DepGraph { &self.data.as_ref().unwrap().previous_work_products } - pub fn debug_was_loaded_from_disk(&self, dep_node: DepNode) -> bool { + pub fn debug_was_loaded_from_disk(&self, dep_node: DepNode) -> bool { self.data.as_ref().unwrap().debug_loaded_from_disk.lock().contains(&dep_node) } #[inline(always)] - pub fn register_dep_node_debug_str(&self, dep_node: DepNode, debug_str_gen: F) + pub fn register_dep_node_debug_str(&self, dep_node: DepNode, debug_str_gen: F) where F: FnOnce() -> String, { @@ -705,11 +705,11 @@ impl DepGraph { dep_node_debug.borrow_mut().insert(dep_node, debug_str); } - pub fn dep_node_debug_str(&self, dep_node: DepNode) -> Option { + pub fn dep_node_debug_str(&self, dep_node: DepNode) -> Option { self.data.as_ref()?.dep_node_debug.borrow().get(&dep_node).cloned() } - fn node_color(&self, dep_node: &DepNode) -> Option { + fn node_color(&self, dep_node: &DepNode) -> Option { if let Some(ref data) = self.data { return data.node_color(dep_node); } @@ -717,25 +717,25 @@ impl DepGraph { None } - pub fn try_mark_green>( + pub fn try_mark_green>( &self, qcx: Qcx, - dep_node: &DepNode, + dep_node: &DepNode, ) -> Option<(SerializedDepNodeIndex, DepNodeIndex)> { self.data().and_then(|data| data.try_mark_green(qcx, dep_node)) } } -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 /// 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>( + pub fn try_mark_green>( &self, qcx: Qcx, - dep_node: &DepNode, + dep_node: &DepNode, ) -> Option<(SerializedDepNodeIndex, DepNodeIndex)> { debug_assert!(!qcx.dep_context().is_eval_always(dep_node.kind)); @@ -757,11 +757,11 @@ impl DepGraphData { } #[instrument(skip(self, qcx, parent_dep_node_index, frame), level = "debug")] - fn try_mark_parent_green>( + fn try_mark_parent_green>( &self, qcx: Qcx, parent_dep_node_index: SerializedDepNodeIndex, - dep_node: &DepNode, + dep_node: &DepNode, frame: Option<&MarkFrame<'_>>, ) -> Option<()> { let dep_dep_node_color = self.colors.get(parent_dep_node_index); @@ -845,11 +845,11 @@ 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>( + fn try_mark_previous_green>( &self, qcx: Qcx, prev_dep_node_index: SerializedDepNodeIndex, - dep_node: &DepNode, + dep_node: &DepNode, frame: Option<&MarkFrame<'_>>, ) -> Option { let frame = MarkFrame { index: prev_dep_node_index, parent: frame }; @@ -916,7 +916,7 @@ impl DepGraphData { /// This may be called concurrently on multiple threads for the same dep node. #[cold] #[inline(never)] - fn emit_side_effects>( + fn emit_side_effects>( &self, qcx: Qcx, dep_node_index: DepNodeIndex, @@ -940,16 +940,16 @@ 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 { + pub fn is_red(&self, dep_node: &DepNode) -> bool { self.node_color(dep_node) == Some(DepNodeColor::Red) } /// Returns true if the given node has been marked as green during the /// current compilation session. Used in various assertions - pub fn is_green(&self, dep_node: &DepNode) -> bool { + pub fn is_green(&self, dep_node: &DepNode) -> bool { self.node_color(dep_node).is_some_and(|c| c.is_green()) } @@ -961,7 +961,7 @@ 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) { + pub fn exec_cache_promotions(&self, tcx: Tcx) { let _prof_timer = tcx.profiler().generic_activity("incr_comp_query_cache_promotion"); let data = self.data.as_ref().unwrap(); @@ -1076,9 +1076,9 @@ rustc_index::newtype_index! { /// `new_node_to_index` and `data`, or `prev_index_to_index` and `data`. When /// manipulating both, we acquire `new_node_to_index` or `prev_index_to_index` /// first, and `data` second. -pub(super) struct CurrentDepGraph { - encoder: Steal>, - new_node_to_index: Sharded, DepNodeIndex>>, +pub(super) struct CurrentDepGraph { + encoder: Steal>, + new_node_to_index: Sharded>, prev_index_to_index: Lock>>, /// This is used to verify that fingerprints do not change between the creation of a node @@ -1089,7 +1089,7 @@ pub(super) struct CurrentDepGraph { /// Used to trap when a specific edge is added to the graph. /// This is used for debug purposes and is only active with `debug_assertions`. #[cfg(debug_assertions)] - forbidden_edge: Option>, + forbidden_edge: Option, /// Anonymous `DepNode`s are nodes whose IDs we compute from the list of /// their edges. This has the beneficial side-effect that multiple anonymous @@ -1116,14 +1116,14 @@ pub(super) struct CurrentDepGraph { node_intern_event_id: Option, } -impl CurrentDepGraph { +impl CurrentDepGraph { fn new( profiler: &SelfProfilerRef, prev_graph_node_count: usize, encoder: FileEncoder, record_graph: bool, record_stats: bool, - ) -> CurrentDepGraph { + ) -> Self { use std::time::{SystemTime, UNIX_EPOCH}; let duration = SystemTime::now().duration_since(UNIX_EPOCH).unwrap(); @@ -1178,7 +1178,7 @@ impl CurrentDepGraph { } #[cfg(debug_assertions)] - fn record_edge(&self, dep_node_index: DepNodeIndex, key: DepNode, fingerprint: Fingerprint) { + fn record_edge(&self, dep_node_index: DepNodeIndex, key: DepNode, fingerprint: Fingerprint) { if let Some(forbidden_edge) = &self.forbidden_edge { forbidden_edge.index_to_node.lock().insert(dep_node_index, key); } @@ -1192,7 +1192,7 @@ impl CurrentDepGraph { fn intern_new_node( &self, profiler: &SelfProfilerRef, - key: DepNode, + key: DepNode, edges: EdgesVec, current_fingerprint: Fingerprint, ) -> DepNodeIndex { @@ -1215,8 +1215,8 @@ impl CurrentDepGraph { fn intern_node( &self, profiler: &SelfProfilerRef, - prev_graph: &SerializedDepGraph, - key: DepNode, + prev_graph: &SerializedDepGraph, + key: DepNode, edges: EdgesVec, fingerprint: Option, print_status: bool, @@ -1289,7 +1289,7 @@ impl CurrentDepGraph { fn promote_node_and_deps_to_current( &self, profiler: &SelfProfilerRef, - prev_graph: &SerializedDepGraph, + prev_graph: &SerializedDepGraph, prev_index: SerializedDepNodeIndex, ) -> DepNodeIndex { self.debug_assert_not_in_new_nodes(prev_graph, prev_index); @@ -1317,7 +1317,7 @@ impl CurrentDepGraph { #[inline] fn debug_assert_not_in_new_nodes( &self, - prev_graph: &SerializedDepGraph, + prev_graph: &SerializedDepGraph, prev_index: SerializedDepNodeIndex, ) { let node = &prev_graph.index_to_node(prev_index); @@ -1329,11 +1329,11 @@ impl CurrentDepGraph { } #[derive(Debug, Clone, Copy)] -pub enum TaskDepsRef<'a, K: DepKind> { +pub enum TaskDepsRef<'a> { /// New dependencies can be added to the /// `TaskDeps`. This is used when executing a 'normal' query /// (no `eval_always` modifier) - Allow(&'a Lock>), + Allow(&'a Lock), /// This is used when executing an `eval_always` query. We don't /// need to track dependencies for a query that's always /// re-executed -- but we need to know that this is an `eval_always` @@ -1350,15 +1350,15 @@ pub enum TaskDepsRef<'a, K: DepKind> { } #[derive(Debug)] -pub struct TaskDeps { +pub struct TaskDeps { #[cfg(debug_assertions)] - node: Option>, + node: Option, reads: EdgesVec, read_set: FxHashSet, - phantom_data: PhantomData>, + phantom_data: PhantomData, } -impl Default for TaskDeps { +impl Default for TaskDeps { fn default() -> Self { Self { #[cfg(debug_assertions)] @@ -1410,10 +1410,7 @@ impl DepNodeColorMap { #[inline(never)] #[cold] -pub(crate) fn print_markframe_trace( - graph: &DepGraph, - frame: Option<&MarkFrame<'_>>, -) { +pub(crate) fn print_markframe_trace(graph: &DepGraph, frame: Option<&MarkFrame<'_>>) { let data = graph.data.as_ref().unwrap(); eprintln!("there was a panic while trying to force a dep node"); diff --git a/compiler/rustc_query_system/src/dep_graph/mod.rs b/compiler/rustc_query_system/src/dep_graph/mod.rs index 272028d35bf..624ae680a8f 100644 --- a/compiler/rustc_query_system/src/dep_graph/mod.rs +++ b/compiler/rustc_query_system/src/dep_graph/mod.rs @@ -1,11 +1,11 @@ pub mod debug; -mod dep_node; +pub mod dep_node; mod edges; mod graph; mod query; mod serialized; -pub use dep_node::{DepKindStruct, DepNode, DepNodeParams, WorkProductId}; +pub use dep_node::{DepKind, DepKindStruct, DepNode, DepNodeParams, WorkProductId}; pub use edges::EdgesVec; pub use graph::{ hash_result, DepGraph, DepGraphData, DepNodeColor, DepNodeIndex, TaskDeps, TaskDepsRef, @@ -16,22 +16,20 @@ pub use serialized::{SerializedDepGraph, SerializedDepNodeIndex}; use crate::ich::StableHashingContext; use rustc_data_structures::profiling::SelfProfilerRef; -use rustc_serialize::{opaque::FileEncoder, Encodable}; use rustc_session::Session; -use std::hash::Hash; -use std::{fmt, panic}; +use std::panic; use self::graph::{print_markframe_trace, MarkFrame}; pub trait DepContext: Copy { - type DepKind: self::DepKind; + type Deps: Deps; /// 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; + fn dep_graph(&self) -> &DepGraph; /// Access the profiler. fn profiler(&self) -> &SelfProfilerRef; @@ -39,10 +37,10 @@ pub trait DepContext: Copy { /// Access the compiler session. fn sess(&self) -> &Session; - fn dep_kind_info(&self, dep_node: Self::DepKind) -> &DepKindStruct; + fn dep_kind_info(&self, dep_node: DepKind) -> &DepKindStruct; #[inline(always)] - fn fingerprint_style(self, kind: Self::DepKind) -> FingerprintStyle { + fn fingerprint_style(self, kind: DepKind) -> FingerprintStyle { let data = self.dep_kind_info(kind); if data.is_anon { return FingerprintStyle::Opaque; @@ -52,18 +50,14 @@ pub trait DepContext: Copy { #[inline(always)] /// Return whether this kind always require evaluation. - fn is_eval_always(self, kind: Self::DepKind) -> bool { + fn is_eval_always(self, kind: DepKind) -> bool { self.dep_kind_info(kind).is_eval_always } /// Try to force a dep node to execute and see if it's green. #[inline] #[instrument(skip(self, frame), level = "debug")] - fn try_force_from_dep_node( - self, - dep_node: DepNode, - frame: Option<&MarkFrame<'_>>, - ) -> bool { + fn try_force_from_dep_node(self, dep_node: DepNode, frame: Option<&MarkFrame<'_>>) -> bool { let cb = self.dep_kind_info(dep_node.kind); if let Some(f) = cb.force_from_dep_node { if let Err(value) = panic::catch_unwind(panic::AssertUnwindSafe(|| { @@ -81,7 +75,7 @@ pub trait DepContext: Copy { } /// Load data from the on-disk cache. - fn try_load_from_on_disk_cache(self, dep_node: DepNode) { + fn try_load_from_on_disk_cache(self, dep_node: DepNode) { let cb = self.dep_kind_info(dep_node.kind); if let Some(f) = cb.try_load_from_on_disk_cache { f(self, dep_node) @@ -89,15 +83,37 @@ pub trait DepContext: Copy { } } +pub trait Deps { + /// 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>); + + /// 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; + + /// 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 DepKind: self::DepKind; - type DepContext: self::DepContext; + type Deps: self::Deps; + type DepContext: self::DepContext; fn dep_context(&self) -> &Self::DepContext; } impl HasDepContext for T { - type DepKind = T::DepKind; + type Deps = T::Deps; type DepContext = Self; fn dep_context(&self) -> &Self::DepContext { @@ -106,7 +122,7 @@ impl HasDepContext for T { } impl HasDepContext for (T, Q) { - type DepKind = T::DepKind; + type Deps = T::Deps; type DepContext = T::DepContext; fn dep_context(&self) -> &Self::DepContext { @@ -138,31 +154,3 @@ impl FingerprintStyle { } } } - -/// Describe the different families of dependency nodes. -pub trait DepKind: Copy + fmt::Debug + Eq + Hash + Send + Encodable + 'static { - /// DepKind to use when incr. comp. is turned off. - const NULL: Self; - - /// DepKind to use to create the initial forever-red node. - const RED: Self; - - /// Implementation of `std::fmt::Debug` for `DepNode`. - fn debug_node(node: &DepNode, f: &mut fmt::Formatter<'_>) -> fmt::Result; - - /// Execute the operation with provided dependencies. - fn with_deps(deps: TaskDepsRef<'_, Self>, 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, Self>); - - fn from_u16(u: u16) -> Self; - - fn to_u16(self) -> u16; - - const MAX: u16; -} diff --git a/compiler/rustc_query_system/src/dep_graph/query.rs b/compiler/rustc_query_system/src/dep_graph/query.rs index 5cbc6bf8f8a..5969e5fbe98 100644 --- a/compiler/rustc_query_system/src/dep_graph/query.rs +++ b/compiler/rustc_query_system/src/dep_graph/query.rs @@ -2,16 +2,16 @@ use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::graph::implementation::{Direction, Graph, NodeIndex, INCOMING}; use rustc_index::IndexVec; -use super::{DepKind, DepNode, DepNodeIndex}; +use super::{DepNode, DepNodeIndex}; -pub struct DepGraphQuery { - pub graph: Graph, ()>, - pub indices: FxHashMap, NodeIndex>, +pub struct DepGraphQuery { + pub graph: Graph, + pub indices: FxHashMap, pub dep_index_to_index: IndexVec>, } -impl DepGraphQuery { - pub fn new(prev_node_count: usize) -> DepGraphQuery { +impl DepGraphQuery { + pub fn new(prev_node_count: usize) -> DepGraphQuery { let node_count = prev_node_count + prev_node_count / 4; let edge_count = 6 * node_count; @@ -22,7 +22,7 @@ impl DepGraphQuery { DepGraphQuery { graph, indices, dep_index_to_index } } - pub fn push(&mut self, index: DepNodeIndex, node: DepNode, edges: &[DepNodeIndex]) { + pub fn push(&mut self, index: DepNodeIndex, node: DepNode, edges: &[DepNodeIndex]) { let source = self.graph.add_node(node); self.dep_index_to_index.insert(index, source); self.indices.insert(node, source); @@ -37,11 +37,11 @@ impl DepGraphQuery { } } - pub fn nodes(&self) -> Vec<&DepNode> { + pub fn nodes(&self) -> Vec<&DepNode> { self.graph.all_nodes().iter().map(|n| &n.data).collect() } - pub fn edges(&self) -> Vec<(&DepNode, &DepNode)> { + pub fn edges(&self) -> Vec<(&DepNode, &DepNode)> { self.graph .all_edges() .iter() @@ -50,7 +50,7 @@ impl DepGraphQuery { .collect() } - fn reachable_nodes(&self, node: &DepNode, direction: Direction) -> Vec<&DepNode> { + fn reachable_nodes(&self, node: &DepNode, direction: Direction) -> Vec<&DepNode> { if let Some(&index) = self.indices.get(node) { self.graph.depth_traverse(index, direction).map(|s| self.graph.node_data(s)).collect() } else { @@ -59,7 +59,7 @@ impl DepGraphQuery { } /// All nodes that can reach `node`. - pub fn transitive_predecessors(&self, node: &DepNode) -> Vec<&DepNode> { + pub fn transitive_predecessors(&self, node: &DepNode) -> Vec<&DepNode> { self.reachable_nodes(node, INCOMING) } } diff --git a/compiler/rustc_query_system/src/dep_graph/serialized.rs b/compiler/rustc_query_system/src/dep_graph/serialized.rs index 07eb10cba02..fcf46be6e6f 100644 --- a/compiler/rustc_query_system/src/dep_graph/serialized.rs +++ b/compiler/rustc_query_system/src/dep_graph/serialized.rs @@ -36,7 +36,7 @@ //! store it directly after the header with leb128. use super::query::DepGraphQuery; -use super::{DepKind, DepNode, DepNodeIndex}; +use super::{DepKind, DepNode, DepNodeIndex, Deps}; use crate::dep_graph::EdgesVec; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fingerprint::PackedFingerprint; @@ -70,9 +70,9 @@ const DEP_NODE_WIDTH_BITS: usize = DEP_NODE_SIZE / 2; /// Data for use when recompiling the **current crate**. #[derive(Debug)] -pub struct SerializedDepGraph { +pub struct SerializedDepGraph { /// The set of all DepNodes in the graph - nodes: IndexVec>, + nodes: IndexVec, /// The set of all Fingerprints in the graph. Each Fingerprint corresponds to /// the DepNode at the same index in the nodes vector. fingerprints: IndexVec, @@ -88,7 +88,7 @@ pub struct SerializedDepGraph { index: Vec>, } -impl Default for SerializedDepGraph { +impl Default for SerializedDepGraph { fn default() -> Self { SerializedDepGraph { nodes: Default::default(), @@ -100,7 +100,7 @@ impl Default for SerializedDepGraph { } } -impl SerializedDepGraph { +impl SerializedDepGraph { #[inline] pub fn edge_targets_from( &self, @@ -134,13 +134,13 @@ impl SerializedDepGraph { } #[inline] - pub fn index_to_node(&self, dep_node_index: SerializedDepNodeIndex) -> DepNode { + pub fn index_to_node(&self, dep_node_index: SerializedDepNodeIndex) -> DepNode { self.nodes[dep_node_index] } #[inline] - pub fn node_to_index_opt(&self, dep_node: &DepNode) -> Option { - self.index.get(dep_node.kind.to_u16() as usize)?.get(&dep_node.hash).cloned() + pub fn node_to_index_opt(&self, dep_node: &DepNode) -> Option { + self.index.get(dep_node.kind.as_usize())?.get(&dep_node.hash).cloned() } #[inline] @@ -184,11 +184,9 @@ fn mask(bits: usize) -> usize { usize::MAX >> ((std::mem::size_of::() * 8) - bits) } -impl<'a, K: DepKind + Decodable>> Decodable> - for SerializedDepGraph -{ +impl SerializedDepGraph { #[instrument(level = "debug", skip(d))] - fn decode(d: &mut MemDecoder<'a>) -> SerializedDepGraph { + pub fn decode(d: &mut MemDecoder<'_>) -> SerializedDepGraph { // The last 16 bytes are the node count and edge count. debug!("position: {:?}", d.position()); let (node_count, edge_count) = @@ -217,14 +215,14 @@ impl<'a, K: DepKind + Decodable>> Decodable> // 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 * std::mem::size_of::>(), + graph_bytes - node_count * std::mem::size_of::>(), ); for _index 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 }; + SerializedNodeHeader:: { bytes: d.read_array(), _marker: PhantomData }; let _i: SerializedDepNodeIndex = nodes.push(node_header.node()); debug_assert_eq!(_i.index(), _index); @@ -256,12 +254,12 @@ impl<'a, K: DepKind + Decodable>> Decodable> 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..(K::MAX as usize + 1)) + let mut index: Vec<_> = (0..(D::DEP_KIND_MAX + 1)) .map(|_| UnhashMap::with_capacity_and_hasher(d.read_u32() as usize, Default::default())) .collect(); for (idx, node) in nodes.iter_enumerated() { - index[node.kind.to_u16() as usize].insert(node.hash, idx); + index[node.kind.as_usize()].insert(node.hash, idx); } SerializedDepGraph { nodes, fingerprints, edge_list_indices, edge_list_data, index } @@ -276,20 +274,20 @@ impl<'a, K: DepKind + Decodable>> Decodable> /// * 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 // 16 for Fingerprint in DepNode // 16 for Fingerprint in NodeInfo bytes: [u8; 34], - _marker: PhantomData, + _marker: PhantomData, } // The fields of a `SerializedNodeHeader`, this struct is an implementation detail and exists only // to make the implementation of `SerializedNodeHeader` simpler. -struct Unpacked { +struct Unpacked { len: Option, bytes_per_index: usize, - kind: K, + kind: DepKind, hash: PackedFingerprint, fingerprint: Fingerprint, } @@ -301,20 +299,20 @@ struct Unpacked { // 0..M length of the edge // M..M+N bytes per index // M+N..16 kind -impl SerializedNodeHeader { - const TOTAL_BITS: usize = std::mem::size_of::() * 8; +impl SerializedNodeHeader { + const TOTAL_BITS: usize = std::mem::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 - K::MAX.leading_zeros() as usize; + const KIND_BITS: usize = Self::TOTAL_BITS - D::DEP_KIND_MAX.leading_zeros() as usize; const MAX_INLINE_LEN: usize = (u16::MAX as usize >> (Self::TOTAL_BITS - Self::LEN_BITS)) - 1; #[inline] - fn new(node_info: &NodeInfo) -> Self { + fn new(node_info: &NodeInfo) -> Self { debug_assert_eq!(Self::TOTAL_BITS, Self::LEN_BITS + Self::WIDTH_BITS + Self::KIND_BITS); let NodeInfo { node, fingerprint, edges } = node_info; - let mut head = node.kind.to_u16(); + let mut head = node.kind.as_inner(); let free_bytes = edges.max_index().leading_zeros() as usize / 8; let bytes_per_index = (DEP_NODE_SIZE - free_bytes).saturating_sub(1); @@ -347,7 +345,7 @@ impl SerializedNodeHeader { } #[inline] - fn unpack(&self) -> Unpacked { + fn unpack(&self) -> Unpacked { let head = u16::from_le_bytes(self.bytes[..2].try_into().unwrap()); let hash = self.bytes[2..18].try_into().unwrap(); let fingerprint = self.bytes[18..].try_into().unwrap(); @@ -359,7 +357,7 @@ impl SerializedNodeHeader { Unpacked { len: len.checked_sub(1), bytes_per_index: bytes_per_index as usize + 1, - kind: DepKind::from_u16(kind), + kind: DepKind::new(kind), hash: Fingerprint::from_le_bytes(hash).into(), fingerprint: Fingerprint::from_le_bytes(fingerprint), } @@ -381,7 +379,7 @@ impl SerializedNodeHeader { } #[inline] - fn node(&self) -> DepNode { + fn node(&self) -> DepNode { let Unpacked { kind, hash, .. } = self.unpack(); DepNode { kind, hash } } @@ -395,15 +393,15 @@ impl SerializedNodeHeader { } #[derive(Debug)] -struct NodeInfo { - node: DepNode, +struct NodeInfo { + node: DepNode, fingerprint: Fingerprint, edges: EdgesVec, } -impl Encodable for NodeInfo { - fn encode(&self, e: &mut FileEncoder) { - let header = SerializedNodeHeader::new(self); +impl NodeInfo { + fn encode(&self, e: &mut FileEncoder) { + let header = SerializedNodeHeader::::new(self); e.write_array(header.bytes); if header.len().is_none() { @@ -420,41 +418,43 @@ impl Encodable for NodeInfo { } } -struct Stat { - kind: K, +struct Stat { + kind: DepKind, node_counter: u64, edge_counter: u64, } -struct EncoderState { +struct EncoderState { encoder: FileEncoder, total_node_count: usize, total_edge_count: usize, - stats: Option>>, + stats: Option>, /// Stores the number of times we've encoded each dep kind. kind_stats: Vec, + marker: PhantomData, } -impl EncoderState { +impl EncoderState { fn new(encoder: FileEncoder, record_stats: bool) -> Self { Self { encoder, total_edge_count: 0, total_node_count: 0, stats: record_stats.then(FxHashMap::default), - kind_stats: iter::repeat(0).take(K::MAX as usize + 1).collect(), + kind_stats: iter::repeat(0).take(D::DEP_KIND_MAX as usize + 1).collect(), + marker: PhantomData, } } fn encode_node( &mut self, - node: &NodeInfo, - record_graph: &Option>>, + node: &NodeInfo, + record_graph: &Option>, ) -> DepNodeIndex { let index = DepNodeIndex::new(self.total_node_count); self.total_node_count += 1; - self.kind_stats[node.node.kind.to_u16() as usize] += 1; + self.kind_stats[node.node.kind.as_usize()] += 1; let edge_count = node.edges.len(); self.total_edge_count += edge_count; @@ -475,12 +475,19 @@ impl EncoderState { } let encoder = &mut self.encoder; - node.encode(encoder); + node.encode::(encoder); index } fn finish(self, profiler: &SelfProfilerRef) -> FileEncodeResult { - let Self { mut encoder, total_node_count, total_edge_count, stats: _, kind_stats } = self; + let Self { + mut encoder, + total_node_count, + total_edge_count, + stats: _, + kind_stats, + marker: _, + } = self; let node_count = total_node_count.try_into().unwrap(); let edge_count = total_edge_count.try_into().unwrap(); @@ -506,12 +513,12 @@ impl EncoderState { } } -pub struct GraphEncoder { - status: Lock>, - record_graph: Option>>, +pub struct GraphEncoder { + status: Lock>, + record_graph: Option>, } -impl> GraphEncoder { +impl GraphEncoder { pub fn new( encoder: FileEncoder, prev_node_count: usize, @@ -523,7 +530,7 @@ impl> GraphEncoder { GraphEncoder { status, record_graph } } - pub(crate) fn with_query(&self, f: impl Fn(&DepGraphQuery)) { + pub(crate) fn with_query(&self, f: impl Fn(&DepGraphQuery)) { if let Some(record_graph) = &self.record_graph { f(&record_graph.lock()) } @@ -584,7 +591,7 @@ impl> GraphEncoder { pub(crate) fn send( &self, profiler: &SelfProfilerRef, - node: DepNode, + node: DepNode, fingerprint: Fingerprint, edges: EdgesVec, ) -> DepNodeIndex { diff --git a/compiler/rustc_query_system/src/query/config.rs b/compiler/rustc_query_system/src/query/config.rs index d14c6315dc1..c025fac2631 100644 --- a/compiler/rustc_query_system/src/query/config.rs +++ b/compiler/rustc_query_system/src/query/config.rs @@ -1,6 +1,6 @@ //! Query configuration and description traits. -use crate::dep_graph::{DepNode, DepNodeParams, SerializedDepNodeIndex}; +use crate::dep_graph::{DepKind, DepNode, DepNodeParams, SerializedDepNodeIndex}; use crate::error::HandleCycleError; use crate::ich::StableHashingContext; use crate::query::caches::QueryCache; @@ -27,7 +27,7 @@ pub trait QueryConfig: Copy { fn format_value(self) -> fn(&Self::Value) -> String; // Don't use this method to access query results, instead use the methods on TyCtxt - fn query_state<'a>(self, tcx: Qcx) -> &'a QueryState + fn query_state<'a>(self, tcx: Qcx) -> &'a QueryState where Qcx: 'a; @@ -57,7 +57,7 @@ pub trait QueryConfig: Copy { fn value_from_cycle_error( self, tcx: Qcx::DepContext, - cycle: &[QueryInfo], + cycle: &[QueryInfo], guar: ErrorGuaranteed, ) -> Self::Value; @@ -66,12 +66,12 @@ pub trait QueryConfig: Copy { fn depth_limit(self) -> bool; fn feedable(self) -> bool; - fn dep_kind(self) -> Qcx::DepKind; + fn dep_kind(self) -> DepKind; fn handle_cycle_error(self) -> HandleCycleError; fn hash_result(self) -> HashResult; // Just here for convenience and checking that the key matches the kind, don't override this. - fn construct_dep_node(self, tcx: Qcx::DepContext, key: &Self::Key) -> DepNode { + fn construct_dep_node(self, tcx: Qcx::DepContext, key: &Self::Key) -> DepNode { DepNode::construct(tcx, self.dep_kind(), key) } } diff --git a/compiler/rustc_query_system/src/query/job.rs b/compiler/rustc_query_system/src/query/job.rs index 6c01dc3c00d..2e9ebde296c 100644 --- a/compiler/rustc_query_system/src/query/job.rs +++ b/compiler/rustc_query_system/src/query/job.rs @@ -1,9 +1,8 @@ -use crate::dep_graph::DepKind; +use crate::dep_graph::DepContext; use crate::error::CycleStack; use crate::query::plumbing::CycleError; +use crate::query::DepKind; use crate::query::{QueryContext, QueryStackFrame}; -use core::marker::PhantomData; - use rustc_data_structures::fx::FxHashMap; use rustc_errors::{ Diagnostic, DiagnosticBuilder, ErrorGuaranteed, Handler, IntoDiagnostic, Level, @@ -30,48 +29,48 @@ use { /// Represents a span and a query key. #[derive(Clone, Debug)] -pub struct QueryInfo { +pub struct QueryInfo { /// The span corresponding to the reason for which this query was required. pub span: Span, - pub query: QueryStackFrame, + pub query: QueryStackFrame, } -pub type QueryMap = FxHashMap>; +pub type QueryMap = FxHashMap; /// A value uniquely identifying an active query job. #[derive(Copy, Clone, Eq, PartialEq, Hash)] pub struct QueryJobId(pub NonZeroU64); impl QueryJobId { - fn query(self, map: &QueryMap) -> QueryStackFrame { + fn query(self, map: &QueryMap) -> QueryStackFrame { map.get(&self).unwrap().query.clone() } #[cfg(parallel_compiler)] - fn span(self, map: &QueryMap) -> Span { + fn span(self, map: &QueryMap) -> Span { map.get(&self).unwrap().job.span } #[cfg(parallel_compiler)] - fn parent(self, map: &QueryMap) -> Option { + fn parent(self, map: &QueryMap) -> Option { map.get(&self).unwrap().job.parent } #[cfg(parallel_compiler)] - fn latch(self, map: &QueryMap) -> Option<&QueryLatch> { + fn latch(self, map: &QueryMap) -> Option<&QueryLatch> { map.get(&self).unwrap().job.latch.as_ref() } } #[derive(Clone)] -pub struct QueryJobInfo { - pub query: QueryStackFrame, - pub job: QueryJob, +pub struct QueryJobInfo { + pub query: QueryStackFrame, + pub job: QueryJob, } /// Represents an active query job. #[derive(Clone)] -pub struct QueryJob { +pub struct QueryJob { pub id: QueryJobId, /// The span corresponding to the reason for which this query was required. @@ -82,11 +81,10 @@ pub struct QueryJob { /// The latch that is used to wait on this job. #[cfg(parallel_compiler)] - latch: Option>, - spooky: core::marker::PhantomData, + latch: Option, } -impl QueryJob { +impl QueryJob { /// Creates a new query job. #[inline] pub fn new(id: QueryJobId, span: Span, parent: Option) -> Self { @@ -96,12 +94,11 @@ impl QueryJob { parent, #[cfg(parallel_compiler)] latch: None, - spooky: PhantomData, } } #[cfg(parallel_compiler)] - pub(super) fn latch(&mut self) -> QueryLatch { + pub(super) fn latch(&mut self) -> QueryLatch { if self.latch.is_none() { self.latch = Some(QueryLatch::new()); } @@ -124,12 +121,12 @@ impl QueryJob { } impl QueryJobId { - pub(super) fn find_cycle_in_stack( + pub(super) fn find_cycle_in_stack( &self, - query_map: QueryMap, + query_map: QueryMap, current_job: &Option, span: Span, - ) -> CycleError { + ) -> CycleError { // Find the waitee amongst `current_job` parents let mut cycle = Vec::new(); let mut current_job = Option::clone(current_job); @@ -163,18 +160,18 @@ impl QueryJobId { #[cold] #[inline(never)] - pub fn try_find_layout_root( + pub fn try_find_layout_root( &self, - query_map: QueryMap, - ) -> Option<(QueryJobInfo, usize)> { + query_map: QueryMap, + layout_of_kind: DepKind, + ) -> Option<(QueryJobInfo, usize)> { let mut last_layout = None; let mut current_id = Some(*self); let mut depth = 0; while let Some(id) = current_id { let info = query_map.get(&id).unwrap(); - // FIXME: This string comparison should probably not be done. - if format!("{:?}", info.query.dep_kind) == "layout_of" { + if info.query.dep_kind == layout_of_kind { depth += 1; last_layout = Some((info.clone(), depth)); } @@ -185,15 +182,15 @@ impl QueryJobId { } #[cfg(parallel_compiler)] -struct QueryWaiter { +struct QueryWaiter { query: Option, condvar: Condvar, span: Span, - cycle: Mutex>>, + cycle: Mutex>, } #[cfg(parallel_compiler)] -impl QueryWaiter { +impl QueryWaiter { fn notify(&self, registry: &rayon_core::Registry) { rayon_core::mark_unblocked(registry); self.condvar.notify_one(); @@ -201,19 +198,19 @@ impl QueryWaiter { } #[cfg(parallel_compiler)] -struct QueryLatchInfo { +struct QueryLatchInfo { complete: bool, - waiters: Vec>>, + waiters: Vec>, } #[cfg(parallel_compiler)] #[derive(Clone)] -pub(super) struct QueryLatch { - info: Arc>>, +pub(super) struct QueryLatch { + info: Arc>, } #[cfg(parallel_compiler)] -impl QueryLatch { +impl QueryLatch { fn new() -> Self { QueryLatch { info: Arc::new(Mutex::new(QueryLatchInfo { complete: false, waiters: Vec::new() })), @@ -221,11 +218,7 @@ impl QueryLatch { } /// Awaits for the query job to complete. - pub(super) fn wait_on( - &self, - query: Option, - span: Span, - ) -> Result<(), CycleError> { + pub(super) fn wait_on(&self, query: Option, span: Span) -> Result<(), CycleError> { let waiter = Arc::new(QueryWaiter { query, span, cycle: Mutex::new(None), condvar: Condvar::new() }); self.wait_on_inner(&waiter); @@ -240,7 +233,7 @@ impl QueryLatch { } /// Awaits the caller on this latch by blocking the current thread. - fn wait_on_inner(&self, waiter: &Arc>) { + fn wait_on_inner(&self, waiter: &Arc) { let mut info = self.info.lock(); if !info.complete { // We push the waiter on to the `waiters` list. It can be accessed inside @@ -274,7 +267,7 @@ impl QueryLatch { /// Removes a single waiter from the list of waiters. /// This is used to break query cycles. - fn extract_waiter(&self, waiter: usize) -> Arc> { + fn extract_waiter(&self, waiter: usize) -> Arc { let mut info = self.info.lock(); debug_assert!(!info.complete); // Remove the waiter from the list of waiters @@ -296,14 +289,9 @@ type Waiter = (QueryJobId, usize); /// required information to resume the waiter. /// If all `visit` calls returns None, this function also returns None. #[cfg(parallel_compiler)] -fn visit_waiters( - query_map: &QueryMap, - query: QueryJobId, - mut visit: F, -) -> Option> +fn visit_waiters(query_map: &QueryMap, query: QueryJobId, mut visit: F) -> Option> where F: FnMut(Span, QueryJobId) -> Option>, - D: DepKind, { // Visit the parent query which is a non-resumable waiter since it's on the same stack if let Some(parent) = query.parent(query_map) { @@ -332,8 +320,8 @@ where /// If a cycle is detected, this initial value is replaced with the span causing /// the cycle. #[cfg(parallel_compiler)] -fn cycle_check( - query_map: &QueryMap, +fn cycle_check( + query_map: &QueryMap, query: QueryJobId, span: Span, stack: &mut Vec<(Span, QueryJobId)>, @@ -373,8 +361,8 @@ fn cycle_check( /// from `query` without going through any of the queries in `visited`. /// This is achieved with a depth first search. #[cfg(parallel_compiler)] -fn connected_to_root( - query_map: &QueryMap, +fn connected_to_root( + query_map: &QueryMap, query: QueryJobId, visited: &mut FxHashSet, ) -> bool { @@ -396,10 +384,9 @@ fn connected_to_root( // Deterministically pick an query from a list #[cfg(parallel_compiler)] -fn pick_query<'a, T, F, D>(query_map: &QueryMap, queries: &'a [T], f: F) -> &'a T +fn pick_query<'a, T, F>(query_map: &QueryMap, queries: &'a [T], f: F) -> &'a T where F: Fn(&T) -> (Span, QueryJobId), - D: DepKind, { // Deterministically pick an entry point // FIXME: Sort this instead @@ -423,10 +410,10 @@ where /// If a cycle was not found, the starting query is removed from `jobs` and /// the function returns false. #[cfg(parallel_compiler)] -fn remove_cycle( - query_map: &QueryMap, +fn remove_cycle( + query_map: &QueryMap, jobs: &mut Vec, - wakelist: &mut Vec>>, + wakelist: &mut Vec>, ) -> bool { let mut visited = FxHashSet::default(); let mut stack = Vec::new(); @@ -528,7 +515,7 @@ fn remove_cycle( /// There may be multiple cycles involved in a deadlock, so this searches /// all active queries for cycles before finally resuming all the waiters at once. #[cfg(parallel_compiler)] -pub fn deadlock(query_map: QueryMap, registry: &rayon_core::Registry) { +pub fn deadlock(query_map: QueryMap, registry: &rayon_core::Registry) { let on_panic = defer(|| { eprintln!("deadlock handler panicked, aborting process"); process::abort(); @@ -566,9 +553,9 @@ pub fn deadlock(query_map: QueryMap, registry: &rayon_core::Regis #[inline(never)] #[cold] -pub(crate) fn report_cycle<'a, D: DepKind>( +pub(crate) fn report_cycle<'a>( sess: &'a Session, - CycleError { usage, cycle: stack }: &CycleError, + CycleError { usage, cycle: stack }: &CycleError, ) -> DiagnosticBuilder<'a, ErrorGuaranteed> { assert!(!stack.is_empty()); @@ -655,8 +642,10 @@ pub fn print_query_stack( if let Some(ref mut file) = file { let _ = writeln!( file, - "#{} [{:?}] {}", - count_total, query_info.query.dep_kind, query_info.query.description + "#{} [{}] {}", + count_total, + qcx.dep_context().dep_kind_info(query_info.query.dep_kind).name, + query_info.query.description ); } diff --git a/compiler/rustc_query_system/src/query/mod.rs b/compiler/rustc_query_system/src/query/mod.rs index f7619d75be7..05dee9f12db 100644 --- a/compiler/rustc_query_system/src/query/mod.rs +++ b/compiler/rustc_query_system/src/query/mod.rs @@ -28,27 +28,27 @@ use thin_vec::ThinVec; /// /// This is mostly used in case of cycles for error reporting. #[derive(Clone, Debug)] -pub struct QueryStackFrame { +pub struct QueryStackFrame { pub description: String, span: Option, pub def_id: Option, pub def_kind: Option, pub ty_adt_id: Option, - pub dep_kind: D, + pub dep_kind: DepKind, /// This hash is used to deterministically pick /// a query to remove cycles in the parallel compiler. #[cfg(parallel_compiler)] hash: Hash64, } -impl QueryStackFrame { +impl QueryStackFrame { #[inline] pub fn new( description: String, span: Option, def_id: Option, def_kind: Option, - dep_kind: D, + dep_kind: DepKind, ty_adt_id: Option, _hash: impl FnOnce() -> Hash64, ) -> Self { @@ -106,7 +106,7 @@ pub trait QueryContext: HasDepContext { /// Get the query information from the TLS context. fn current_query_job(self) -> Option; - fn try_collect_active_jobs(self) -> Option>; + fn try_collect_active_jobs(self) -> Option; /// Load side effects associated to the node in the previous session. fn load_side_effects(self, prev_dep_node_index: SerializedDepNodeIndex) -> QuerySideEffects; diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs index 07db15e6d8b..f93edffca79 100644 --- a/compiler/rustc_query_system/src/query/plumbing.rs +++ b/compiler/rustc_query_system/src/query/plumbing.rs @@ -2,8 +2,8 @@ //! generate the actual methods on tcx which find and execute the provider, //! manage the caches, and so forth. -use crate::dep_graph::{DepContext, DepKind, DepNode, DepNodeIndex, DepNodeParams}; -use crate::dep_graph::{DepGraphData, HasDepContext}; +use crate::dep_graph::DepGraphData; +use crate::dep_graph::{DepContext, DepNode, DepNodeIndex, DepNodeParams}; use crate::ich::StableHashingContext; use crate::query::caches::QueryCache; #[cfg(parallel_compiler)] @@ -30,24 +30,23 @@ use thin_vec::ThinVec; use super::QueryConfig; -pub struct QueryState { - active: Sharded>>, +pub struct QueryState { + active: Sharded>, } /// Indicates the state of a query for a given key in a query map. -enum QueryResult { +enum QueryResult { /// An already executing query. The query job can be used to await for its completion. - Started(QueryJob), + Started(QueryJob), /// The query panicked. Queries trying to wait on this will raise a fatal error which will /// silently panic. Poisoned, } -impl QueryState +impl QueryState where K: Eq + Hash + Copy + Debug, - D: DepKind, { pub fn all_inactive(&self) -> bool { self.active.lock_shards().all(|shard| shard.is_empty()) @@ -56,8 +55,8 @@ where pub fn try_collect_active_jobs( &self, qcx: Qcx, - make_query: fn(Qcx, K) -> QueryStackFrame, - jobs: &mut QueryMap, + make_query: fn(Qcx, K) -> QueryStackFrame, + jobs: &mut QueryMap, ) -> Option<()> { let mut active = Vec::new(); @@ -82,25 +81,25 @@ where } } -impl Default for QueryState { - fn default() -> QueryState { +impl Default for QueryState { + fn default() -> QueryState { QueryState { active: Default::default() } } } /// A type representing the responsibility to execute the job in the `job` field. /// This will poison the relevant query if dropped. -struct JobOwner<'tcx, K, D: DepKind> +struct JobOwner<'tcx, K> where K: Eq + Hash + Copy, { - state: &'tcx QueryState, + state: &'tcx QueryState, key: K, } #[cold] #[inline(never)] -fn mk_cycle(query: Q, qcx: Qcx, cycle_error: CycleError) -> Q::Value +fn mk_cycle(query: Q, qcx: Qcx, cycle_error: CycleError) -> Q::Value where Q: QueryConfig, Qcx: QueryContext, @@ -112,7 +111,7 @@ where fn handle_cycle_error( query: Q, qcx: Qcx, - cycle_error: &CycleError, + cycle_error: &CycleError, mut error: DiagnosticBuilder<'_, ErrorGuaranteed>, ) -> Q::Value where @@ -137,7 +136,7 @@ where } } -impl<'tcx, K, D: DepKind> JobOwner<'tcx, K, D> +impl<'tcx, K> JobOwner<'tcx, K> where K: Eq + Hash + Copy, { @@ -169,10 +168,9 @@ where } } -impl<'tcx, K, D> Drop for JobOwner<'tcx, K, D> +impl<'tcx, K> Drop for JobOwner<'tcx, K> where K: Eq + Hash + Copy, - D: DepKind, { #[inline(never)] #[cold] @@ -195,10 +193,10 @@ where } #[derive(Clone)] -pub(crate) struct CycleError { +pub(crate) struct CycleError { /// The query and related span that uses the cycle. - pub usage: Option<(Span, QueryStackFrame)>, - pub cycle: Vec>, + pub usage: Option<(Span, QueryStackFrame)>, + pub cycle: Vec, } /// Checks if the query is already computed and in the cache. @@ -248,7 +246,7 @@ fn wait_for_query( qcx: Qcx, span: Span, key: Q::Key, - latch: QueryLatch, + latch: QueryLatch, current: Option, ) -> (Q::Value, Option) where @@ -296,7 +294,7 @@ fn try_execute_query( qcx: Qcx, span: Span, key: Q::Key, - dep_node: Option>, + dep_node: Option, ) -> (Q::Value, Option) where Q: QueryConfig, @@ -364,10 +362,10 @@ where fn execute_job( query: Q, qcx: Qcx, - state: &QueryState, + state: &QueryState, key: Q::Key, id: QueryJobId, - dep_node: Option>, + dep_node: Option, ) -> (Q::Value, Option) where Q: QueryConfig, @@ -474,9 +472,9 @@ where fn execute_job_incr( query: Q, qcx: Qcx, - dep_graph_data: &DepGraphData, + dep_graph_data: &DepGraphData, key: Q::Key, - mut dep_node_opt: Option>, + mut dep_node_opt: Option, job_id: QueryJobId, ) -> (Q::Value, DepNodeIndex) where @@ -540,10 +538,10 @@ where #[inline(always)] fn try_load_from_disk_and_cache_in_memory( query: Q, - dep_graph_data: &DepGraphData, + dep_graph_data: &DepGraphData, qcx: Qcx, key: &Q::Key, - dep_node: &DepNode, + dep_node: &DepNode, ) -> Option<(Q::Value, DepNodeIndex)> where Q: QueryConfig, @@ -637,7 +635,7 @@ where #[instrument(skip(tcx, dep_graph_data, result, hash_result, format_value), level = "debug")] pub(crate) fn incremental_verify_ich( tcx: Tcx, - dep_graph_data: &DepGraphData, + dep_graph_data: &DepGraphData, result: &V, prev_index: SerializedDepNodeIndex, hash_result: Option, &V) -> Fingerprint>, @@ -730,7 +728,7 @@ fn ensure_must_run( qcx: Qcx, key: &Q::Key, check_cache: bool, -) -> (bool, Option>) +) -> (bool, Option) where Q: QueryConfig, Qcx: QueryContext, @@ -821,12 +819,8 @@ where Some(result) } -pub fn force_query( - query: Q, - qcx: Qcx, - key: Q::Key, - dep_node: DepNode<::DepKind>, -) where +pub fn force_query(query: Q, qcx: Qcx, key: Q::Key, dep_node: DepNode) +where Q: QueryConfig, Qcx: QueryContext, { diff --git a/compiler/rustc_query_system/src/values.rs b/compiler/rustc_query_system/src/values.rs index 07c28fdb73b..8848fda9da3 100644 --- a/compiler/rustc_query_system/src/values.rs +++ b/compiler/rustc_query_system/src/values.rs @@ -1,14 +1,14 @@ use rustc_span::ErrorGuaranteed; -use crate::dep_graph::{DepContext, DepKind}; +use crate::dep_graph::DepContext; use crate::query::QueryInfo; -pub trait Value: Sized { - fn from_cycle_error(tcx: Tcx, cycle: &[QueryInfo], guar: ErrorGuaranteed) -> Self; +pub trait Value: Sized { + fn from_cycle_error(tcx: Tcx, cycle: &[QueryInfo], guar: ErrorGuaranteed) -> Self; } -impl Value for T { - default fn from_cycle_error(tcx: Tcx, cycle: &[QueryInfo], _guar: ErrorGuaranteed) -> T { +impl Value for T { + default fn from_cycle_error(tcx: Tcx, cycle: &[QueryInfo], _guar: ErrorGuaranteed) -> T { tcx.sess().abort_if_errors(); // Ideally we would use `bug!` here. But bug! is only defined in rustc_middle, and it's // non-trivial to define it earlier. diff --git a/compiler/rustc_trait_selection/src/solve/search_graph/mod.rs b/compiler/rustc_trait_selection/src/solve/search_graph/mod.rs index 16de518e8e0..728d0fc1ae7 100644 --- a/compiler/rustc_trait_selection/src/solve/search_graph/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/search_graph/mod.rs @@ -8,7 +8,7 @@ use cache::ProvisionalCache; use rustc_data_structures::fx::FxHashSet; use rustc_index::Idx; use rustc_index::IndexVec; -use rustc_middle::dep_graph::DepKind; +use rustc_middle::dep_graph::dep_kinds; use rustc_middle::traits::solve::inspect::CacheHit; use rustc_middle::traits::solve::CacheData; use rustc_middle::traits::solve::{CanonicalInput, Certainty, EvaluationCache, QueryResult}; @@ -287,7 +287,7 @@ impl<'tcx> SearchGraph<'tcx> { // Everything that affects the `result` should be performed within this // `with_anon_task` closure. let ((final_entry, result), dep_node) = - tcx.dep_graph.with_anon_task(tcx, DepKind::TraitSelect, || { + tcx.dep_graph.with_anon_task(tcx, dep_kinds::TraitSelect, || { // When we encounter a coinductive cycle, we have to fetch the // result of that cycle while we are still computing it. Because // of this we continuously recompute the cycle until the result diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 24d31633850..dcf41c3774f 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -35,7 +35,8 @@ use rustc_hir::def_id::DefId; use rustc_infer::infer::DefineOpaqueTypes; use rustc_infer::infer::LateBoundRegionConversionTime; use rustc_infer::traits::TraitObligation; -use rustc_middle::dep_graph::{DepKind, DepNodeIndex}; +use rustc_middle::dep_graph::dep_kinds; +use rustc_middle::dep_graph::DepNodeIndex; use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::traits::DefiningAnchor; use rustc_middle::ty::abstract_const::NotConstEvaluatable; @@ -1435,7 +1436,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { OP: FnOnce(&mut Self) -> R, { let (result, dep_node) = - self.tcx().dep_graph.with_anon_task(self.tcx(), DepKind::TraitSelect, || op(self)); + self.tcx().dep_graph.with_anon_task(self.tcx(), dep_kinds::TraitSelect, || op(self)); self.tcx().dep_graph.read_index(dep_node); (result, dep_node) }