Sanity check computed value for feeable queries.
This commit is contained in:
parent
ee7a9a8641
commit
9f2c6b0b09
4 changed files with 42 additions and 3 deletions
|
@ -359,6 +359,15 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream {
|
||||||
});
|
});
|
||||||
|
|
||||||
if modifiers.feedable.is_some() {
|
if modifiers.feedable.is_some() {
|
||||||
|
assert!(modifiers.anon.is_none(), "Query {name} cannot be both `feedable` and `anon`.");
|
||||||
|
assert!(
|
||||||
|
modifiers.eval_always.is_none(),
|
||||||
|
"Query {name} cannot be both `feedable` and `eval_always`."
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
modifiers.no_hash.is_none(),
|
||||||
|
"Query {name} cannot be both `feedable` and `no_hash`."
|
||||||
|
);
|
||||||
feedable_queries.extend(quote! {
|
feedable_queries.extend(quote! {
|
||||||
#(#doc_comments)*
|
#(#doc_comments)*
|
||||||
[#attribute_stream] fn #name(#arg) #result,
|
[#attribute_stream] fn #name(#arg) #result,
|
||||||
|
|
|
@ -252,6 +252,18 @@ macro_rules! depth_limit {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! feedable {
|
||||||
|
([]) => {{
|
||||||
|
false
|
||||||
|
}};
|
||||||
|
([(feedable) $($rest:tt)*]) => {{
|
||||||
|
true
|
||||||
|
}};
|
||||||
|
([$other:tt $($modifiers:tt)*]) => {
|
||||||
|
feedable!([$($modifiers)*])
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
macro_rules! hash_result {
|
macro_rules! hash_result {
|
||||||
([]) => {{
|
([]) => {{
|
||||||
Some(dep_graph::hash_result)
|
Some(dep_graph::hash_result)
|
||||||
|
@ -491,6 +503,7 @@ macro_rules! define_queries {
|
||||||
anon: is_anon!([$($modifiers)*]),
|
anon: is_anon!([$($modifiers)*]),
|
||||||
eval_always: is_eval_always!([$($modifiers)*]),
|
eval_always: is_eval_always!([$($modifiers)*]),
|
||||||
depth_limit: depth_limit!([$($modifiers)*]),
|
depth_limit: depth_limit!([$($modifiers)*]),
|
||||||
|
feedable: feedable!([$($modifiers)*]),
|
||||||
dep_kind: dep_graph::DepKind::$name,
|
dep_kind: dep_graph::DepKind::$name,
|
||||||
hash_result: hash_result!([$($modifiers)*]),
|
hash_result: hash_result!([$($modifiers)*]),
|
||||||
handle_cycle_error: handle_cycle_error!([$($modifiers)*]),
|
handle_cycle_error: handle_cycle_error!([$($modifiers)*]),
|
||||||
|
|
|
@ -15,8 +15,8 @@ pub trait QueryConfig<Qcx: QueryContext> {
|
||||||
const NAME: &'static str;
|
const NAME: &'static str;
|
||||||
|
|
||||||
type Key: Eq + Hash + Clone + Debug;
|
type Key: Eq + Hash + Clone + Debug;
|
||||||
type Value;
|
type Value: Debug;
|
||||||
type Stored: Clone;
|
type Stored: Debug + Clone + std::borrow::Borrow<Self::Value>;
|
||||||
|
|
||||||
type Cache: QueryCache<Key = Self::Key, Stored = Self::Stored, Value = Self::Value>;
|
type Cache: QueryCache<Key = Self::Key, Stored = Self::Stored, Value = Self::Value>;
|
||||||
|
|
||||||
|
@ -45,6 +45,7 @@ pub struct QueryVTable<Qcx: QueryContext, K, V> {
|
||||||
pub dep_kind: Qcx::DepKind,
|
pub dep_kind: Qcx::DepKind,
|
||||||
pub eval_always: bool,
|
pub eval_always: bool,
|
||||||
pub depth_limit: bool,
|
pub depth_limit: bool,
|
||||||
|
pub feedable: bool,
|
||||||
|
|
||||||
pub compute: fn(Qcx::DepContext, K) -> V,
|
pub compute: fn(Qcx::DepContext, K) -> V,
|
||||||
pub hash_result: Option<fn(&mut StableHashingContext<'_>, &V) -> Fingerprint>,
|
pub hash_result: Option<fn(&mut StableHashingContext<'_>, &V) -> Fingerprint>,
|
||||||
|
|
|
@ -20,6 +20,7 @@ use rustc_data_structures::sync::Lock;
|
||||||
use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed, FatalError};
|
use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed, FatalError};
|
||||||
use rustc_session::Session;
|
use rustc_session::Session;
|
||||||
use rustc_span::{Span, DUMMY_SP};
|
use rustc_span::{Span, DUMMY_SP};
|
||||||
|
use std::borrow::Borrow;
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
use std::collections::hash_map::Entry;
|
use std::collections::hash_map::Entry;
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
|
@ -370,11 +371,26 @@ where
|
||||||
C: QueryCache,
|
C: QueryCache,
|
||||||
C::Key: Clone + DepNodeParams<Qcx::DepContext>,
|
C::Key: Clone + DepNodeParams<Qcx::DepContext>,
|
||||||
C::Value: Value<Qcx::DepContext>,
|
C::Value: Value<Qcx::DepContext>,
|
||||||
|
C::Stored: Debug + std::borrow::Borrow<C::Value>,
|
||||||
Qcx: QueryContext,
|
Qcx: QueryContext,
|
||||||
{
|
{
|
||||||
match JobOwner::<'_, C::Key>::try_start(&qcx, state, span, key.clone()) {
|
match JobOwner::<'_, C::Key>::try_start(&qcx, state, span, key.clone()) {
|
||||||
TryGetJob::NotYetStarted(job) => {
|
TryGetJob::NotYetStarted(job) => {
|
||||||
let (result, dep_node_index) = execute_job(qcx, key, dep_node, query, job.id);
|
let (result, dep_node_index) = execute_job(qcx, key.clone(), dep_node, query, job.id);
|
||||||
|
if query.feedable {
|
||||||
|
// We may have put a value inside the cache from inside the execution.
|
||||||
|
// Verify that it has the same hash as what we have now, to ensure consistency.
|
||||||
|
let _ = cache.lookup(&key, |cached_result, _| {
|
||||||
|
let hasher = query.hash_result.expect("feedable forbids no_hash");
|
||||||
|
let old_hash = qcx.dep_context().with_stable_hashing_context(|mut hcx| hasher(&mut hcx, cached_result.borrow()));
|
||||||
|
let new_hash = qcx.dep_context().with_stable_hashing_context(|mut hcx| hasher(&mut hcx, &result));
|
||||||
|
debug_assert_eq!(
|
||||||
|
old_hash, new_hash,
|
||||||
|
"Computed query value for {:?}({:?}) is inconsistent with fed value,\ncomputed={:#?}\nfed={:#?}",
|
||||||
|
query.dep_kind, key, result, cached_result,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
let result = job.complete(cache, result, dep_node_index);
|
let result = job.complete(cache, result, dep_node_index);
|
||||||
(result, Some(dep_node_index))
|
(result, Some(dep_node_index))
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue