Auto merge of #122227 - Zoxc:query-hash-verify, r=michaelwoerister

Verify that query keys result in unique dep nodes

This implements checking that query keys result into unique dep nodes as mentioned in https://github.com/rust-lang/rust/pull/112469.

We could do a perf check to see how expensive this is.

r? `@michaelwoerister`
This commit is contained in:
bors 2024-03-13 02:01:56 +00:00
commit d3555f3d8e
4 changed files with 56 additions and 2 deletions

View File

@ -321,6 +321,8 @@ impl Compiler {
} }
self.sess.time("serialize_dep_graph", || gcx.enter(rustc_incremental::save_dep_graph)); self.sess.time("serialize_dep_graph", || gcx.enter(rustc_incremental::save_dep_graph));
gcx.enter(rustc_query_impl::query_key_hash_verify_all);
} }
// The timer's lifetime spans the dropping of `queries`, which contains // The timer's lifetime spans the dropping of `queries`, which contains

View File

@ -41,7 +41,7 @@ use rustc_span::{ErrorGuaranteed, Span};
#[macro_use] #[macro_use]
mod plumbing; mod plumbing;
pub use crate::plumbing::QueryCtxt; pub use crate::plumbing::{query_key_hash_verify_all, QueryCtxt};
mod profiling_support; mod profiling_support;
pub use self::profiling_support::alloc_self_profile_query_strings; pub use self::profiling_support::alloc_self_profile_query_strings;

View File

@ -7,6 +7,7 @@ use crate::rustc_middle::ty::TyEncoder;
use crate::QueryConfigRestored; use crate::QueryConfigRestored;
use rustc_data_structures::stable_hasher::{Hash64, HashStable, StableHasher}; use rustc_data_structures::stable_hasher::{Hash64, HashStable, StableHasher};
use rustc_data_structures::sync::Lock; use rustc_data_structures::sync::Lock;
use rustc_data_structures::unord::UnordMap;
use rustc_errors::DiagInner; use rustc_errors::DiagInner;
use rustc_index::Idx; use rustc_index::Idx;
@ -189,6 +190,16 @@ pub(super) fn encode_all_query_results<'tcx>(
} }
} }
pub fn query_key_hash_verify_all<'tcx>(tcx: TyCtxt<'tcx>) {
if tcx.sess().opts.unstable_opts.incremental_verify_ich || cfg!(debug_assertions) {
tcx.sess.time("query_key_hash_verify_all", || {
for verify in super::QUERY_KEY_HASH_VERIFY.iter() {
verify(tcx);
}
})
}
}
macro_rules! handle_cycle_error { macro_rules! handle_cycle_error {
([]) => {{ ([]) => {{
rustc_query_system::HandleCycleError::Error rustc_query_system::HandleCycleError::Error
@ -370,6 +381,34 @@ pub(crate) fn encode_query_results<'a, 'tcx, Q>(
}); });
} }
pub(crate) fn query_key_hash_verify<'tcx>(
query: impl QueryConfig<QueryCtxt<'tcx>>,
qcx: QueryCtxt<'tcx>,
) {
let _timer =
qcx.profiler().generic_activity_with_arg("query_key_hash_verify_for", query.name());
let mut map = UnordMap::default();
let cache = query.query_cache(qcx);
cache.iter(&mut |key, _, _| {
let node = DepNode::construct(qcx.tcx, query.dep_kind(), key);
if let Some(other_key) = map.insert(node, *key) {
bug!(
"query key:\n\
`{:?}`\n\
and key:\n\
`{:?}`\n\
mapped to the same dep node:\n\
{:?}",
key,
other_key,
node
);
}
});
}
fn try_load_from_on_disk_cache<'tcx, Q>(query: Q, tcx: TyCtxt<'tcx>, dep_node: DepNode) fn try_load_from_on_disk_cache<'tcx, Q>(query: Q, tcx: TyCtxt<'tcx>, dep_node: DepNode)
where where
Q: QueryConfig<QueryCtxt<'tcx>>, Q: QueryConfig<QueryCtxt<'tcx>>,
@ -691,6 +730,13 @@ macro_rules! define_queries {
) )
} }
}} }}
pub fn query_key_hash_verify<'tcx>(tcx: TyCtxt<'tcx>) {
$crate::plumbing::query_key_hash_verify(
query_impl::$name::QueryType::config(tcx),
QueryCtxt::new(tcx),
)
}
})*} })*}
pub(crate) fn engine(incremental: bool) -> QueryEngine { pub(crate) fn engine(incremental: bool) -> QueryEngine {
@ -730,6 +776,10 @@ macro_rules! define_queries {
> >
] = &[$(expand_if_cached!([$($modifiers)*], query_impl::$name::encode_query_results)),*]; ] = &[$(expand_if_cached!([$($modifiers)*], query_impl::$name::encode_query_results)),*];
const QUERY_KEY_HASH_VERIFY: &[
for<'tcx> fn(TyCtxt<'tcx>)
] = &[$(query_impl::$name::query_key_hash_verify),*];
#[allow(nonstandard_style)] #[allow(nonstandard_style)]
mod query_callbacks { mod query_callbacks {
use super::*; use super::*;

View File

@ -1674,7 +1674,9 @@ options! {
"print high-level information about incremental reuse (or the lack thereof) \ "print high-level information about incremental reuse (or the lack thereof) \
(default: no)"), (default: no)"),
incremental_verify_ich: bool = (false, parse_bool, [UNTRACKED], incremental_verify_ich: bool = (false, parse_bool, [UNTRACKED],
"verify incr. comp. hashes of green query instances (default: no)"), "verify extended properties for incr. comp. (default: no):
- hashes of green query instances
- hash collisions of query keys"),
inline_in_all_cgus: Option<bool> = (None, parse_opt_bool, [TRACKED], inline_in_all_cgus: Option<bool> = (None, parse_opt_bool, [TRACKED],
"control whether `#[inline]` functions are in all CGUs"), "control whether `#[inline]` functions are in all CGUs"),
inline_llvm: bool = (true, parse_bool, [TRACKED], inline_llvm: bool = (true, parse_bool, [TRACKED],