Skip to content
5 changes: 0 additions & 5 deletions compiler/rustc_middle/src/dep_graph/dep_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,11 +174,6 @@ impl fmt::Debug for DepNode {
/// of the `DepKind`. Overall, this allows to implement `DepContext` using this manual
/// jump table instead of large matches.
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.
pub is_anon: bool,

/// Eval-always queries do not track their dependencies, and are always recomputed, even if
/// their inputs have not changed since the last compiler invocation. The result is still
/// cached within one compiler invocation.
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_middle/src/queries.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,10 +150,10 @@ use crate::{dep_graph, mir, thir};
// `Providers` that the driver creates (using several `rustc_*` crates).
//
// The result type of each query must implement `Clone`, and additionally
// `ty::query::values::Value`, which produces an appropriate placeholder
// (error) value if the query resulted in a query cycle.
// `ty::query::from_cycle_error::FromCycleError`, which produces an appropriate
// placeholder (error) value if the query resulted in a query cycle.
// Queries marked with `cycle_fatal` do not need the latter implementation,
// as they will raise an fatal error on query cycles instead.
// as they will raise a fatal error on query cycles instead.
rustc_queries! {
/// Caches the expansion of a derive proc macro, e.g. `#[derive(Serialize)]`.
/// The key is:
Expand Down
43 changes: 14 additions & 29 deletions compiler/rustc_middle/src/query/plumbing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,18 +62,6 @@ pub enum CycleErrorHandling {
Stash,
}

pub type WillCacheOnDiskForKeyFn<'tcx, Key> = fn(tcx: TyCtxt<'tcx>, key: &Key) -> bool;

pub type TryLoadFromDiskFn<'tcx, Key, Value> = fn(
tcx: TyCtxt<'tcx>,
key: &Key,
prev_index: SerializedDepNodeIndex,
index: DepNodeIndex,
) -> Option<Value>;

pub type IsLoadableFromDiskFn<'tcx, Key> =
fn(tcx: TyCtxt<'tcx>, key: &Key, index: SerializedDepNodeIndex) -> bool;

#[derive(Clone, Debug)]
pub struct CycleError<I = QueryStackFrameExtra> {
/// The query and related span that uses the cycle.
Expand Down Expand Up @@ -126,7 +114,7 @@ pub struct QueryVTable<'tcx, C: QueryCache> {
pub cycle_error_handling: CycleErrorHandling,
pub state: QueryState<'tcx, C::Key>,
pub cache: C,
pub will_cache_on_disk_for_key_fn: Option<WillCacheOnDiskForKeyFn<'tcx, C::Key>>,
pub will_cache_on_disk_for_key_fn: Option<fn(tcx: TyCtxt<'tcx>, key: &C::Key) -> bool>,

/// Function pointer that calls `tcx.$query(key)` for this query and
/// discards the returned value.
Expand All @@ -142,16 +130,25 @@ pub struct QueryVTable<'tcx, C: QueryCache> {
/// This should be the only code that calls the provider function.
pub invoke_provider_fn: fn(tcx: TyCtxt<'tcx>, key: C::Key) -> C::Value,

pub try_load_from_disk_fn: Option<TryLoadFromDiskFn<'tcx, C::Key, C::Value>>,
pub is_loadable_from_disk_fn: Option<IsLoadableFromDiskFn<'tcx, C::Key>>,
pub try_load_from_disk_fn: Option<
fn(
tcx: TyCtxt<'tcx>,
key: &C::Key,
prev_index: SerializedDepNodeIndex,
index: DepNodeIndex,
) -> Option<C::Value>,
>,

pub is_loadable_from_disk_fn:
Option<fn(tcx: TyCtxt<'tcx>, key: &C::Key, index: SerializedDepNodeIndex) -> bool>,

/// Function pointer that hashes this query's result values.
///
/// For `no_hash` queries, this function pointer is None.
pub hash_value_fn: Option<fn(&mut StableHashingContext<'_>, &C::Value) -> Fingerprint>,

pub value_from_cycle_error:
fn(tcx: TyCtxt<'tcx>, cycle_error: &CycleError, guar: ErrorGuaranteed) -> C::Value,
fn(tcx: TyCtxt<'tcx>, cycle_error: CycleError, guar: ErrorGuaranteed) -> C::Value,
pub format_value: fn(&C::Value) -> String,

/// Formats a human-readable description of this query and its key, as
Expand Down Expand Up @@ -216,7 +213,7 @@ impl<'tcx, C: QueryCache> QueryVTable<'tcx, C> {
pub fn value_from_cycle_error(
&self,
tcx: TyCtxt<'tcx>,
cycle_error: &CycleError,
cycle_error: CycleError,
guar: ErrorGuaranteed,
) -> C::Value {
(self.value_from_cycle_error)(tcx, cycle_error, guar)
Expand Down Expand Up @@ -650,18 +647,6 @@ macro_rules! define_callbacks {
};
}

// Each of these queries corresponds to a function pointer field in the
// `Providers` struct for requesting a value of that type, and a method
// on `tcx: TyCtxt` (and `tcx.at(span)`) for doing that request in a way
// which memoizes and does dep-graph tracking, wrapping around the actual
// `Providers` that the driver creates (using several `rustc_*` crates).
//
// The result type of each query must implement `Clone`, and additionally
// `ty::query::values::Value`, which produces an appropriate placeholder
// (error) value if the query resulted in a query cycle.
// Queries marked with `cycle_fatal` do not need the latter implementation,
// as they will raise an fatal error on query cycles instead.

mod sealed {
use rustc_hir::def_id::{LocalModDefId, ModDefId};

Expand Down
9 changes: 0 additions & 9 deletions compiler/rustc_query_impl/src/dep_kind_vtables.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ mod non_query {
// We use this for most things when incr. comp. is turned off.
pub(crate) fn Null<'tcx>() -> DepKindVTable<'tcx> {
DepKindVTable {
is_anon: false,
is_eval_always: false,
key_fingerprint_style: KeyFingerprintStyle::Unit,
force_from_dep_node_fn: Some(|_, dep_node, _| {
Expand All @@ -26,7 +25,6 @@ mod non_query {
// We use this for the forever-red node.
pub(crate) fn Red<'tcx>() -> DepKindVTable<'tcx> {
DepKindVTable {
is_anon: false,
is_eval_always: false,
key_fingerprint_style: KeyFingerprintStyle::Unit,
force_from_dep_node_fn: Some(|_, dep_node, _| {
Expand All @@ -38,7 +36,6 @@ mod non_query {

pub(crate) fn SideEffect<'tcx>() -> DepKindVTable<'tcx> {
DepKindVTable {
is_anon: false,
is_eval_always: false,
key_fingerprint_style: KeyFingerprintStyle::Unit,
force_from_dep_node_fn: Some(|tcx, _, prev_index| {
Expand All @@ -51,7 +48,6 @@ mod non_query {

pub(crate) fn AnonZeroDeps<'tcx>() -> DepKindVTable<'tcx> {
DepKindVTable {
is_anon: true,
is_eval_always: false,
key_fingerprint_style: KeyFingerprintStyle::Opaque,
force_from_dep_node_fn: Some(|_, _, _| bug!("cannot force an anon node")),
Expand All @@ -61,7 +57,6 @@ mod non_query {

pub(crate) fn TraitSelect<'tcx>() -> DepKindVTable<'tcx> {
DepKindVTable {
is_anon: true,
is_eval_always: false,
key_fingerprint_style: KeyFingerprintStyle::Unit,
force_from_dep_node_fn: None,
Expand All @@ -71,7 +66,6 @@ mod non_query {

pub(crate) fn CompileCodegenUnit<'tcx>() -> DepKindVTable<'tcx> {
DepKindVTable {
is_anon: false,
is_eval_always: false,
key_fingerprint_style: KeyFingerprintStyle::Opaque,
force_from_dep_node_fn: None,
Expand All @@ -81,7 +75,6 @@ mod non_query {

pub(crate) fn CompileMonoItem<'tcx>() -> DepKindVTable<'tcx> {
DepKindVTable {
is_anon: false,
is_eval_always: false,
key_fingerprint_style: KeyFingerprintStyle::Opaque,
force_from_dep_node_fn: None,
Expand All @@ -91,7 +84,6 @@ mod non_query {

pub(crate) fn Metadata<'tcx>() -> DepKindVTable<'tcx> {
DepKindVTable {
is_anon: false,
is_eval_always: false,
key_fingerprint_style: KeyFingerprintStyle::Unit,
force_from_dep_node_fn: None,
Expand Down Expand Up @@ -124,7 +116,6 @@ where
}

DepKindVTable {
is_anon,
is_eval_always,
key_fingerprint_style,
force_from_dep_node_fn: can_recover.then_some(force_from_dep_node_inner::<Q>),
Expand Down
54 changes: 19 additions & 35 deletions compiler/rustc_query_impl/src/execution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use rustc_data_structures::hash_table::{Entry, HashTable};
use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_data_structures::sync::{DynSend, DynSync};
use rustc_data_structures::{outline, sharded, sync};
use rustc_errors::{Diag, FatalError, StashKey};
use rustc_errors::{FatalError, StashKey};
use rustc_middle::dep_graph::{DepGraphData, DepNodeKey, SerializedDepNodeIndex};
use rustc_middle::query::plumbing::QueryVTable;
use rustc_middle::query::{
Expand Down Expand Up @@ -126,24 +126,14 @@ fn mk_cycle<'tcx, C: QueryCache>(
cycle_error: CycleError,
) -> C::Value {
let error = report_cycle(tcx.sess, &cycle_error);
handle_cycle_error(query, tcx, &cycle_error, error)
}

fn handle_cycle_error<'tcx, C: QueryCache>(
query: &'tcx QueryVTable<'tcx, C>,
tcx: TyCtxt<'tcx>,
cycle_error: &CycleError,
error: Diag<'_>,
) -> C::Value {
match query.cycle_error_handling {
CycleErrorHandling::Error => {
let guar = error.emit();
query.value_from_cycle_error(tcx, cycle_error, guar)
}
CycleErrorHandling::Fatal => {
error.emit();
tcx.dcx().abort_if_errors();
unreachable!()
let guar = error.emit();
guar.raise_fatal();
}
CycleErrorHandling::DelayBug => {
let guar = error.delay_as_bug();
Expand Down Expand Up @@ -340,15 +330,15 @@ fn try_execute_query<'tcx, C: QueryCache, const INCR: bool>(

// Only call `wait_for_query` if we're using a Rayon thread pool
// as it will attempt to mark the worker thread as blocked.
return wait_for_query(query, tcx, span, key, latch, current_job_id);
}

let id = job.id;
drop(state_lock);
wait_for_query(query, tcx, span, key, latch, current_job_id)
} else {
let id = job.id;
drop(state_lock);

// If we are single-threaded we know that we have cycle error,
// so we just return the error.
cycle_error(query, tcx, id, span)
// If we are single-threaded we know that we have cycle error,
// so we just return the error.
cycle_error(query, tcx, id, span)
}
}
ActiveKeyStatus::Poisoned => FatalError.raise(),
}
Expand Down Expand Up @@ -430,27 +420,21 @@ fn execute_job_non_incr<'tcx, C: QueryCache>(
) -> (C::Value, DepNodeIndex) {
debug_assert!(!tcx.dep_graph.is_fully_enabled());

// Fingerprint the key, just to assert that it doesn't
// have anything we don't consider hashable
if cfg!(debug_assertions) {
let _ = key.to_fingerprint(tcx);
}

let prof_timer = tcx.prof.query_provider();
// Call the query provider.
let value =
start_query(tcx, job_id, query.depth_limit, || (query.invoke_provider_fn)(tcx, key));
let dep_node_index = tcx.dep_graph.next_virtual_depnode_index();
prof_timer.finish_with_query_invocation_id(dep_node_index.into());

// Similarly, fingerprint the result to assert that
// it doesn't have anything not considered hashable.
if cfg!(debug_assertions)
&& let Some(hash_value_fn) = query.hash_value_fn
{
tcx.with_stable_hashing_context(|mut hcx| {
hash_value_fn(&mut hcx, &value);
});
// Sanity: Fingerprint the key and the result to assert they don't contain anything unhashable.
if cfg!(debug_assertions) {
let _ = key.to_fingerprint(tcx);
if let Some(hash_value_fn) = query.hash_value_fn {
tcx.with_stable_hashing_context(|mut hcx| {
hash_value_fn(&mut hcx, &value);
});
}
}

(value, dep_node_index)
Expand Down
Loading
Loading