about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJohn Kåre Alsaker <john.kare.alsaker@gmail.com>2024-03-09 09:29:16 +0100
committerJohn Kåre Alsaker <john.kare.alsaker@gmail.com>2024-03-12 05:31:41 +0100
commit55ba7a7c622fb1ac95ef05e4a652cedf923a8164 (patch)
treec6c98d3a2adfb969613ec3112313f266088e324f
parent1b427b3bf79c2cd48c75915301be3b009b82dea3 (diff)
downloadrust-55ba7a7c622fb1ac95ef05e4a652cedf923a8164.tar.gz
rust-55ba7a7c622fb1ac95ef05e4a652cedf923a8164.zip
Verify that query keys result in unique dep nodes
-rw-r--r--compiler/rustc_interface/src/queries.rs2
-rw-r--r--compiler/rustc_query_impl/src/lib.rs2
-rw-r--r--compiler/rustc_query_impl/src/plumbing.rs50
-rw-r--r--compiler/rustc_session/src/options.rs4
4 files changed, 56 insertions, 2 deletions
diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs
index da11d090b74..c2218822696 100644
--- a/compiler/rustc_interface/src/queries.rs
+++ b/compiler/rustc_interface/src/queries.rs
@@ -321,6 +321,8 @@ impl Compiler {
             }
 
             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
diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs
index 33116737a42..52767155532 100644
--- a/compiler/rustc_query_impl/src/lib.rs
+++ b/compiler/rustc_query_impl/src/lib.rs
@@ -41,7 +41,7 @@ use rustc_span::{ErrorGuaranteed, Span};
 
 #[macro_use]
 mod plumbing;
-pub use crate::plumbing::QueryCtxt;
+pub use crate::plumbing::{query_key_hash_verify_all, QueryCtxt};
 
 mod profiling_support;
 pub use self::profiling_support::alloc_self_profile_query_strings;
diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs
index b06d75be390..aa965779731 100644
--- a/compiler/rustc_query_impl/src/plumbing.rs
+++ b/compiler/rustc_query_impl/src/plumbing.rs
@@ -7,6 +7,7 @@ use crate::rustc_middle::ty::TyEncoder;
 use crate::QueryConfigRestored;
 use rustc_data_structures::stable_hasher::{Hash64, HashStable, StableHasher};
 use rustc_data_structures::sync::Lock;
+use rustc_data_structures::unord::UnordMap;
 use rustc_errors::DiagInner;
 
 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 {
     ([]) => {{
         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)
 where
     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 {
@@ -730,6 +776,10 @@ macro_rules! define_queries {
             >
         ] = &[$(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)]
         mod query_callbacks {
             use super::*;
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index 93bef82e4ba..0122b9ec33e 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -1674,7 +1674,9 @@ options! {
         "print high-level information about incremental reuse (or the lack thereof) \
         (default: no)"),
     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],
         "control whether `#[inline]` functions are in all CGUs"),
     inline_llvm: bool = (true, parse_bool, [TRACKED],