about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--crates/base-db/src/lib.rs2
-rw-r--r--crates/hir-def/src/attr.rs2
-rw-r--r--crates/hir-def/src/db.rs13
-rw-r--r--crates/hir-def/src/item_tree.rs2
-rw-r--r--crates/hir-ty/src/db.rs49
-rw-r--r--crates/hir/src/db.rs28
-rw-r--r--crates/ide-db/src/apply_change.rs4
-rw-r--r--crates/ide-db/src/lib.rs3
-rw-r--r--crates/rust-analyzer/src/integrated_benchmarks.rs80
-rw-r--r--crates/rust-analyzer/src/tracing/config.rs41
-rw-r--r--crates/rust-analyzer/src/tracing/hprof.rs21
-rw-r--r--crates/salsa/salsa-macros/src/query_group.rs13
-rw-r--r--crates/salsa/src/derived.rs14
-rw-r--r--crates/salsa/tests/cycles.rs48
-rw-r--r--crates/salsa/tests/on_demand_inputs.rs26
-rw-r--r--crates/salsa/tests/parallel/parallel_cycle_none_recover.rs4
16 files changed, 174 insertions, 176 deletions
diff --git a/crates/base-db/src/lib.rs b/crates/base-db/src/lib.rs
index cb2e6cdaa28..758d2a45c8f 100644
--- a/crates/base-db/src/lib.rs
+++ b/crates/base-db/src/lib.rs
@@ -43,7 +43,7 @@ pub trait Upcast<T: ?Sized> {
 }
 
 pub const DEFAULT_PARSE_LRU_CAP: usize = 128;
-pub const DEFAULT_BORROWCK_LRU_CAP: usize = 256;
+pub const DEFAULT_BORROWCK_LRU_CAP: usize = 1024;
 
 pub trait FileLoader {
     /// Text of the file.
diff --git a/crates/hir-def/src/attr.rs b/crates/hir-def/src/attr.rs
index 519706c65f2..21536098b82 100644
--- a/crates/hir-def/src/attr.rs
+++ b/crates/hir-def/src/attr.rs
@@ -348,7 +348,7 @@ impl AttrsWithOwner {
                         .raw_attrs(AttrOwner::ModItem(definition_tree_id.value.into()))
                         .clone(),
                     ModuleOrigin::BlockExpr { id, .. } => {
-                        let tree = db.block_item_tree_query(id);
+                        let tree = db.block_item_tree(id);
                         tree.raw_attrs(AttrOwner::TopLevel).clone()
                     }
                 }
diff --git a/crates/hir-def/src/db.rs b/crates/hir-def/src/db.rs
index 68f57600ec4..544ed6bc347 100644
--- a/crates/hir-def/src/db.rs
+++ b/crates/hir-def/src/db.rs
@@ -87,14 +87,10 @@ pub trait DefDatabase: InternDatabase + ExpandDatabase + Upcast<dyn ExpandDataba
     fn file_item_tree(&self, file_id: HirFileId) -> Arc<ItemTree>;
 
     #[salsa::invoke(ItemTree::block_item_tree_query)]
-    fn block_item_tree_query(&self, block_id: BlockId) -> Arc<ItemTree>;
-
-    #[salsa::invoke(crate_def_map_wait)]
-    #[salsa::transparent]
-    fn crate_def_map(&self, krate: CrateId) -> Arc<DefMap>;
+    fn block_item_tree(&self, block_id: BlockId) -> Arc<ItemTree>;
 
     #[salsa::invoke(DefMap::crate_def_map_query)]
-    fn crate_def_map_query(&self, krate: CrateId) -> Arc<DefMap>;
+    fn crate_def_map(&self, krate: CrateId) -> Arc<DefMap>;
 
     /// Computes the block-level `DefMap`.
     #[salsa::invoke(DefMap::block_def_map_query)]
@@ -253,11 +249,6 @@ fn include_macro_invoc(db: &dyn DefDatabase, krate: CrateId) -> Vec<(MacroCallId
         .collect()
 }
 
-fn crate_def_map_wait(db: &dyn DefDatabase, krate: CrateId) -> Arc<DefMap> {
-    let _p = tracing::span!(tracing::Level::INFO, "crate_def_map:wait").entered();
-    db.crate_def_map_query(krate)
-}
-
 fn crate_supports_no_std(db: &dyn DefDatabase, crate_id: CrateId) -> bool {
     let file = db.crate_graph()[crate_id].root_file_id;
     let item_tree = db.file_item_tree(file.into());
diff --git a/crates/hir-def/src/item_tree.rs b/crates/hir-def/src/item_tree.rs
index 008fa7ef13a..179da788d33 100644
--- a/crates/hir-def/src/item_tree.rs
+++ b/crates/hir-def/src/item_tree.rs
@@ -392,7 +392,7 @@ impl TreeId {
 
     pub(crate) fn item_tree(&self, db: &dyn DefDatabase) -> Arc<ItemTree> {
         match self.block {
-            Some(block) => db.block_item_tree_query(block),
+            Some(block) => db.block_item_tree(block),
             None => db.file_item_tree(self.file),
         }
     }
diff --git a/crates/hir-ty/src/db.rs b/crates/hir-ty/src/db.rs
index f9e8cff5539..28c497989fe 100644
--- a/crates/hir-ty/src/db.rs
+++ b/crates/hir-ty/src/db.rs
@@ -31,12 +31,8 @@ use hir_expand::name::Name;
 
 #[salsa::query_group(HirDatabaseStorage)]
 pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
-    #[salsa::invoke(infer_wait)]
-    #[salsa::transparent]
-    fn infer(&self, def: DefWithBodyId) -> Arc<InferenceResult>;
-
     #[salsa::invoke(crate::infer::infer_query)]
-    fn infer_query(&self, def: DefWithBodyId) -> Arc<InferenceResult>;
+    fn infer(&self, def: DefWithBodyId) -> Arc<InferenceResult>;
 
     // region:mir
 
@@ -258,17 +254,8 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
         env: Arc<TraitEnvironment>,
     ) -> Ty;
 
-    #[salsa::invoke(trait_solve_wait)]
-    #[salsa::transparent]
-    fn trait_solve(
-        &self,
-        krate: CrateId,
-        block: Option<BlockId>,
-        goal: crate::Canonical<crate::InEnvironment<crate::Goal>>,
-    ) -> Option<crate::Solution>;
-
     #[salsa::invoke(crate::traits::trait_solve_query)]
-    fn trait_solve_query(
+    fn trait_solve(
         &self,
         krate: CrateId,
         block: Option<BlockId>,
@@ -284,38 +271,6 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
     ) -> chalk_ir::ProgramClauses<Interner>;
 }
 
-fn infer_wait(db: &dyn HirDatabase, def: DefWithBodyId) -> Arc<InferenceResult> {
-    let detail = match def {
-        DefWithBodyId::FunctionId(it) => db.function_data(it).name.display(db.upcast()).to_string(),
-        DefWithBodyId::StaticId(it) => {
-            db.static_data(it).name.clone().display(db.upcast()).to_string()
-        }
-        DefWithBodyId::ConstId(it) => db
-            .const_data(it)
-            .name
-            .clone()
-            .unwrap_or_else(Name::missing)
-            .display(db.upcast())
-            .to_string(),
-        DefWithBodyId::VariantId(it) => {
-            db.enum_variant_data(it).name.display(db.upcast()).to_string()
-        }
-        DefWithBodyId::InTypeConstId(it) => format!("in type const {it:?}"),
-    };
-    let _p = tracing::span!(tracing::Level::INFO, "infer:wait", ?detail).entered();
-    db.infer_query(def)
-}
-
-fn trait_solve_wait(
-    db: &dyn HirDatabase,
-    krate: CrateId,
-    block: Option<BlockId>,
-    goal: crate::Canonical<crate::InEnvironment<crate::Goal>>,
-) -> Option<crate::Solution> {
-    let _p = tracing::span!(tracing::Level::INFO, "trait_solve::wait").entered();
-    db.trait_solve_query(krate, block, goal)
-}
-
 #[test]
 fn hir_database_is_object_safe() {
     fn _assert_object_safe(_: &dyn HirDatabase) {}
diff --git a/crates/hir/src/db.rs b/crates/hir/src/db.rs
index 557c8d29a17..1d74f9a4bb2 100644
--- a/crates/hir/src/db.rs
+++ b/crates/hir/src/db.rs
@@ -4,20 +4,20 @@
 //!
 //! But we need this for at least LRU caching at the query level.
 pub use hir_def::db::{
-    AttrsQuery, BlockDefMapQuery, BlockItemTreeQueryQuery, BodyQuery, BodyWithSourceMapQuery,
-    ConstDataQuery, ConstVisibilityQuery, CrateDefMapQueryQuery, CrateLangItemsQuery,
-    CrateSupportsNoStdQuery, DefDatabase, DefDatabaseStorage, EnumDataQuery,
-    EnumVariantDataWithDiagnosticsQuery, ExprScopesQuery, ExternCrateDeclDataQuery,
-    FieldVisibilitiesQuery, FieldsAttrsQuery, FieldsAttrsSourceMapQuery, FileItemTreeQuery,
-    FunctionDataQuery, FunctionVisibilityQuery, GenericParamsQuery, ImplDataWithDiagnosticsQuery,
-    ImportMapQuery, InternAnonymousConstQuery, InternBlockQuery, InternConstQuery, InternDatabase,
-    InternDatabaseStorage, InternEnumQuery, InternExternBlockQuery, InternExternCrateQuery,
-    InternFunctionQuery, InternImplQuery, InternInTypeConstQuery, InternMacro2Query,
-    InternMacroRulesQuery, InternProcMacroQuery, InternStaticQuery, InternStructQuery,
-    InternTraitAliasQuery, InternTraitQuery, InternTypeAliasQuery, InternUnionQuery,
-    InternUseQuery, LangItemQuery, Macro2DataQuery, MacroRulesDataQuery, ProcMacroDataQuery,
-    StaticDataQuery, StructDataWithDiagnosticsQuery, TraitAliasDataQuery,
-    TraitDataWithDiagnosticsQuery, TypeAliasDataQuery, UnionDataWithDiagnosticsQuery,
+    AttrsQuery, BlockDefMapQuery, BodyQuery, BodyWithSourceMapQuery, ConstDataQuery,
+    ConstVisibilityQuery, CrateLangItemsQuery, CrateSupportsNoStdQuery, DefDatabase,
+    DefDatabaseStorage, EnumDataQuery, EnumVariantDataWithDiagnosticsQuery, ExprScopesQuery,
+    ExternCrateDeclDataQuery, FieldVisibilitiesQuery, FieldsAttrsQuery, FieldsAttrsSourceMapQuery,
+    FileItemTreeQuery, FunctionDataQuery, FunctionVisibilityQuery, GenericParamsQuery,
+    ImplDataWithDiagnosticsQuery, ImportMapQuery, InternAnonymousConstQuery, InternBlockQuery,
+    InternConstQuery, InternDatabase, InternDatabaseStorage, InternEnumQuery,
+    InternExternBlockQuery, InternExternCrateQuery, InternFunctionQuery, InternImplQuery,
+    InternInTypeConstQuery, InternMacro2Query, InternMacroRulesQuery, InternProcMacroQuery,
+    InternStaticQuery, InternStructQuery, InternTraitAliasQuery, InternTraitQuery,
+    InternTypeAliasQuery, InternUnionQuery, InternUseQuery, LangItemQuery, Macro2DataQuery,
+    MacroRulesDataQuery, ProcMacroDataQuery, StaticDataQuery, StructDataWithDiagnosticsQuery,
+    TraitAliasDataQuery, TraitDataWithDiagnosticsQuery, TypeAliasDataQuery,
+    UnionDataWithDiagnosticsQuery,
 };
 pub use hir_expand::db::{
     AstIdMapQuery, DeclMacroExpanderQuery, ExpandDatabase, ExpandDatabaseStorage,
diff --git a/crates/ide-db/src/apply_change.rs b/crates/ide-db/src/apply_change.rs
index f769f72d462..017635d88e7 100644
--- a/crates/ide-db/src/apply_change.rs
+++ b/crates/ide-db/src/apply_change.rs
@@ -91,7 +91,6 @@ impl RootDatabase {
             crate::symbol_index::LocalRootsQuery
             crate::symbol_index::LibraryRootsQuery
             // HirDatabase
-            hir::db::InferQueryQuery
             hir::db::MirBodyQuery
             hir::db::BorrowckQuery
             hir::db::TyQuery
@@ -130,12 +129,10 @@ impl RootDatabase {
             hir::db::FnDefVarianceQuery
             hir::db::AdtVarianceQuery
             hir::db::AssociatedTyValueQuery
-            hir::db::TraitSolveQueryQuery
             hir::db::ProgramClausesForChalkEnvQuery
 
             // DefDatabase
             hir::db::FileItemTreeQuery
-            hir::db::CrateDefMapQueryQuery
             hir::db::BlockDefMapQuery
             hir::db::StructDataWithDiagnosticsQuery
             hir::db::UnionDataWithDiagnosticsQuery
@@ -165,7 +162,6 @@ impl RootDatabase {
             hir::db::FunctionVisibilityQuery
             hir::db::ConstVisibilityQuery
             hir::db::CrateSupportsNoStdQuery
-            hir::db::BlockItemTreeQueryQuery
             hir::db::ExternCrateDeclDataQuery
             hir::db::InternAnonymousConstQuery
             hir::db::InternExternCrateQuery
diff --git a/crates/ide-db/src/lib.rs b/crates/ide-db/src/lib.rs
index 0d11858ed7f..be08b37bac3 100644
--- a/crates/ide-db/src/lib.rs
+++ b/crates/ide-db/src/lib.rs
@@ -216,7 +216,6 @@ impl RootDatabase {
 
             // DefDatabase
             hir_db::FileItemTreeQuery
-            hir_db::CrateDefMapQueryQuery
             hir_db::BlockDefMapQuery
             hir_db::StructDataWithDiagnosticsQuery
             hir_db::UnionDataWithDiagnosticsQuery
@@ -248,7 +247,6 @@ impl RootDatabase {
             hir_db::CrateSupportsNoStdQuery
 
             // HirDatabase
-            hir_db::InferQueryQuery
             hir_db::MirBodyQuery
             hir_db::BorrowckQuery
             hir_db::TyQuery
@@ -287,7 +285,6 @@ impl RootDatabase {
             hir_db::FnDefVarianceQuery
             hir_db::AdtVarianceQuery
             hir_db::AssociatedTyValueQuery
-            hir_db::TraitSolveQueryQuery
             hir_db::ProgramClausesForChalkEnvQuery
 
             // SymbolsDatabase
diff --git a/crates/rust-analyzer/src/integrated_benchmarks.rs b/crates/rust-analyzer/src/integrated_benchmarks.rs
index 28eae6079c5..3bba4847f92 100644
--- a/crates/rust-analyzer/src/integrated_benchmarks.rs
+++ b/crates/rust-analyzer/src/integrated_benchmarks.rs
@@ -11,7 +11,9 @@
 //! which you can use to paste the command in terminal and add `--release` manually.
 
 use hir::ChangeWithProcMacros;
-use ide::{AnalysisHost, CallableSnippets, CompletionConfig, FilePosition, TextSize};
+use ide::{
+    AnalysisHost, CallableSnippets, CompletionConfig, DiagnosticsConfig, FilePosition, TextSize,
+};
 use ide_db::{
     imports::insert_use::{ImportGranularity, InsertUseConfig},
     SnippetCap,
@@ -157,7 +159,7 @@ fn integrated_completion_benchmark() {
         analysis.completions(&config, position, None).unwrap();
     }
 
-    crate::tracing::hprof::init("*>5");
+    let _g = crate::tracing::hprof::init("*");
 
     let completion_offset = {
         let _it = stdx::timeit("change");
@@ -244,6 +246,80 @@ fn integrated_completion_benchmark() {
     }
 }
 
+#[test]
+fn integrated_diagnostics_benchmark() {
+    if std::env::var("RUN_SLOW_BENCHES").is_err() {
+        return;
+    }
+
+    // Load rust-analyzer itself.
+    let workspace_to_load = project_root();
+    let file = "./crates/hir/src/lib.rs";
+
+    let cargo_config = CargoConfig {
+        sysroot: Some(project_model::RustLibSource::Discover),
+        ..CargoConfig::default()
+    };
+    let load_cargo_config = LoadCargoConfig {
+        load_out_dirs_from_check: true,
+        with_proc_macro_server: ProcMacroServerChoice::None,
+        prefill_caches: true,
+    };
+
+    let (db, vfs, _proc_macro) = {
+        let _it = stdx::timeit("workspace loading");
+        load_workspace_at(&workspace_to_load, &cargo_config, &load_cargo_config, &|_| {}).unwrap()
+    };
+    let mut host = AnalysisHost::with_database(db);
+
+    let file_id = {
+        let file = workspace_to_load.join(file);
+        let path = VfsPath::from(AbsPathBuf::assert(file));
+        vfs.file_id(&path).unwrap_or_else(|| panic!("can't find virtual file for {path}"))
+    };
+
+    let diagnostics_config = DiagnosticsConfig {
+        enabled: false,
+        proc_macros_enabled: true,
+        proc_attr_macros_enabled: true,
+        disable_experimental: true,
+        disabled: Default::default(),
+        expr_fill_default: Default::default(),
+        style_lints: false,
+        insert_use: InsertUseConfig {
+            granularity: ImportGranularity::Crate,
+            enforce_granularity: false,
+            prefix_kind: hir::PrefixKind::ByCrate,
+            group: true,
+            skip_glob_imports: true,
+        },
+        prefer_no_std: false,
+        prefer_prelude: false,
+    };
+    host.analysis()
+        .diagnostics(&diagnostics_config, ide::AssistResolveStrategy::None, file_id)
+        .unwrap();
+
+    let _g = crate::tracing::hprof::init("*>1");
+
+    {
+        let _it = stdx::timeit("change");
+        let mut text = host.analysis().file_text(file_id).unwrap().to_string();
+        patch(&mut text, "db.struct_data(self.id)", "();\ndb.struct_data(self.id)");
+        let mut change = ChangeWithProcMacros::new();
+        change.change_file(file_id, Some(Arc::from(text)));
+        host.apply_change(change);
+    };
+
+    {
+        let _p = tracing::span!(tracing::Level::INFO, "diagnostics").entered();
+        let _span = profile::cpu_span();
+        host.analysis()
+            .diagnostics(&diagnostics_config, ide::AssistResolveStrategy::None, file_id)
+            .unwrap();
+    }
+}
+
 fn patch(what: &mut String, from: &str, to: &str) -> usize {
     let idx = what.find(from).unwrap();
     *what = what.replacen(from, to, 1);
diff --git a/crates/rust-analyzer/src/tracing/config.rs b/crates/rust-analyzer/src/tracing/config.rs
index fcdbd1e6d9b..f77d9893304 100644
--- a/crates/rust-analyzer/src/tracing/config.rs
+++ b/crates/rust-analyzer/src/tracing/config.rs
@@ -4,13 +4,10 @@
 use std::io;
 
 use anyhow::Context;
-use tracing::{level_filters::LevelFilter, Level};
+use tracing::level_filters::LevelFilter;
 use tracing_subscriber::{
-    filter::{self, Targets},
-    fmt::{format::FmtSpan, MakeWriter},
-    layer::SubscriberExt,
-    util::SubscriberInitExt,
-    Layer, Registry,
+    filter::Targets, fmt::MakeWriter, layer::SubscriberExt, util::SubscriberInitExt, Layer,
+    Registry,
 };
 use tracing_tree::HierarchicalLayer;
 
@@ -50,10 +47,7 @@ where
 
         let writer = self.writer;
 
-        let ra_fmt_layer = tracing_subscriber::fmt::layer()
-            .with_span_events(FmtSpan::CLOSE)
-            .with_writer(writer)
-            .with_filter(filter);
+        let ra_fmt_layer = tracing_subscriber::fmt::layer().with_writer(writer).with_filter(filter);
 
         let mut chalk_layer = None;
         if let Some(chalk_filter) = self.chalk_filter {
@@ -74,32 +68,7 @@ where
             );
         };
 
-        let mut profiler_layer = None;
-        if let Some(spec) = self.profile_filter {
-            let (write_filter, allowed_names) = hprof::WriteFilter::from_spec(&spec);
-
-            // this filter the first pass for `tracing`: these are all the "profiling" spans, but things like
-            // span depth or duration are not filtered here: that only occurs at write time.
-            let profile_filter = filter::filter_fn(move |metadata| {
-                let allowed = match &allowed_names {
-                    Some(names) => names.contains(metadata.name()),
-                    None => true,
-                };
-
-                metadata.is_span()
-                    && allowed
-                    && metadata.level() >= &Level::INFO
-                    && !metadata.target().starts_with("salsa")
-                    && !metadata.target().starts_with("chalk")
-            });
-
-            let layer = hprof::SpanTree::default()
-                .aggregate(true)
-                .spec_filter(write_filter)
-                .with_filter(profile_filter);
-
-            profiler_layer = Some(layer);
-        }
+        let profiler_layer = self.profile_filter.map(|spec| hprof::layer(&spec));
 
         Registry::default().with(ra_fmt_layer).with(chalk_layer).with(profiler_layer).try_init()?;
 
diff --git a/crates/rust-analyzer/src/tracing/hprof.rs b/crates/rust-analyzer/src/tracing/hprof.rs
index 5fcda6ba136..73f94671f2d 100644
--- a/crates/rust-analyzer/src/tracing/hprof.rs
+++ b/crates/rust-analyzer/src/tracing/hprof.rs
@@ -53,6 +53,14 @@ use tracing_subscriber::{
 use crate::tracing::hprof;
 
 pub fn init(spec: &str) -> tracing::subscriber::DefaultGuard {
+    let subscriber = Registry::default().with(layer(spec));
+    tracing::subscriber::set_default(subscriber)
+}
+
+pub fn layer<S>(spec: &str) -> impl Layer<S>
+where
+    S: Subscriber + for<'span> tracing_subscriber::registry::LookupSpan<'span>,
+{
     let (write_filter, allowed_names) = WriteFilter::from_spec(spec);
 
     // this filter the first pass for `tracing`: these are all the "profiling" spans, but things like
@@ -63,20 +71,15 @@ pub fn init(spec: &str) -> tracing::subscriber::DefaultGuard {
             None => true,
         };
 
-        metadata.is_span()
-            && allowed
+        allowed
+            && metadata.is_span()
             && metadata.level() >= &Level::INFO
             && !metadata.target().starts_with("salsa")
+            && metadata.name() != "compute_exhaustiveness_and_usefulness"
             && !metadata.target().starts_with("chalk")
     });
 
-    let layer = hprof::SpanTree::default()
-        .aggregate(true)
-        .spec_filter(write_filter)
-        .with_filter(profile_filter);
-
-    let subscriber = Registry::default().with(layer);
-    tracing::subscriber::set_default(subscriber)
+    hprof::SpanTree::default().aggregate(true).spec_filter(write_filter).with_filter(profile_filter)
 }
 
 #[derive(Default, Debug)]
diff --git a/crates/salsa/salsa-macros/src/query_group.rs b/crates/salsa/salsa-macros/src/query_group.rs
index a868d920b66..5983765eec7 100644
--- a/crates/salsa/salsa-macros/src/query_group.rs
+++ b/crates/salsa/salsa-macros/src/query_group.rs
@@ -235,13 +235,24 @@ pub(crate) fn query_group(args: TokenStream, input: TokenStream) -> TokenStream
 
         queries_with_storage.push(fn_name);
 
+        let tracing = if let QueryStorage::Memoized = query.storage {
+            let s = format!("{trait_name}::{fn_name}");
+            Some(quote! {
+                let _p = tracing::span!(tracing::Level::DEBUG, #s, #(#key_names = tracing::field::debug(&#key_names)),*).entered();
+            })
+        } else {
+            None
+        }
+        .into_iter();
+
         query_fn_definitions.extend(quote! {
             fn #fn_name(&self, #(#key_names: #keys),*) -> #value {
+                #(#tracing),*
                 // Create a shim to force the code to be monomorphized in the
                 // query crate. Our experiments revealed that this makes a big
                 // difference in total compilation time in rust-analyzer, though
                 // it's not totally obvious why that should be.
-                fn __shim(db: &(dyn #trait_name + '_),  #(#key_names: #keys),*) -> #value {
+                fn __shim(db: &(dyn #trait_name + '_), #(#key_names: #keys),*) -> #value {
                     salsa::plumbing::get_query_table::<#qt>(db).get((#(#key_names),*))
                 }
                 __shim(self, #(#key_names),*)
diff --git a/crates/salsa/src/derived.rs b/crates/salsa/src/derived.rs
index 153df999f53..3b5bd7f9e3b 100644
--- a/crates/salsa/src/derived.rs
+++ b/crates/salsa/src/derived.rs
@@ -136,7 +136,7 @@ where
     ) -> std::fmt::Result {
         let slot_map = self.slot_map.read();
         let key = slot_map.get_index(index as usize).unwrap().0;
-        write!(fmt, "{}({:?})", Q::QUERY_NAME, key)
+        write!(fmt, "{}::{}({:?})", std::any::type_name::<Q>(), Q::QUERY_NAME, key)
     }
 
     fn maybe_changed_after(
@@ -146,13 +146,13 @@ where
         revision: Revision,
     ) -> bool {
         debug_assert!(revision < db.salsa_runtime().current_revision());
-        let read = self.slot_map.read();
-        let Some((key, slot)) = read.get_index(index as usize) else {
-            return false;
+        let (key, slot) = {
+            let read = self.slot_map.read();
+            let Some((key, slot)) = read.get_index(index as usize) else {
+                return false;
+            };
+            (key.clone(), slot.clone())
         };
-        let (key, slot) = (key.clone(), slot.clone());
-        // note: this drop is load-bearing. removing it would causes deadlocks.
-        drop(read);
         slot.maybe_changed_after(db, revision, &key)
     }
 
diff --git a/crates/salsa/tests/cycles.rs b/crates/salsa/tests/cycles.rs
index 2be167bd8d3..ea5d15a250f 100644
--- a/crates/salsa/tests/cycles.rs
+++ b/crates/salsa/tests/cycles.rs
@@ -171,8 +171,8 @@ fn cycle_memoized() {
     let cycle = extract_cycle(|| db.memoized_a());
     expect![[r#"
         [
-            "memoized_a(())",
-            "memoized_b(())",
+            "cycles::MemoizedAQuery::memoized_a(())",
+            "cycles::MemoizedBQuery::memoized_b(())",
         ]
     "#]]
     .assert_debug_eq(&cycle.unexpected_participants(&db));
@@ -184,8 +184,8 @@ fn cycle_volatile() {
     let cycle = extract_cycle(|| db.volatile_a());
     expect![[r#"
         [
-            "volatile_a(())",
-            "volatile_b(())",
+            "cycles::VolatileAQuery::volatile_a(())",
+            "cycles::VolatileBQuery::volatile_b(())",
         ]
     "#]]
     .assert_debug_eq(&cycle.unexpected_participants(&db));
@@ -222,8 +222,8 @@ fn inner_cycle() {
     let cycle = err.unwrap_err().cycle;
     expect![[r#"
         [
-            "cycle_a(())",
-            "cycle_b(())",
+            "cycles::CycleAQuery::cycle_a(())",
+            "cycles::CycleBQuery::cycle_b(())",
         ]
     "#]]
     .assert_debug_eq(&cycle);
@@ -262,8 +262,8 @@ fn cycle_revalidate_unchanged_twice() {
         Err(
             Error {
                 cycle: [
-                    "cycle_a(())",
-                    "cycle_b(())",
+                    "cycles::CycleAQuery::cycle_a(())",
+                    "cycles::CycleBQuery::cycle_b(())",
                 ],
             },
         )
@@ -344,8 +344,8 @@ fn cycle_mixed_1() {
         Err(
             Error {
                 cycle: [
-                    "cycle_b(())",
-                    "cycle_c(())",
+                    "cycles::CycleBQuery::cycle_b(())",
+                    "cycles::CycleCQuery::cycle_c(())",
                 ],
             },
         )
@@ -371,9 +371,9 @@ fn cycle_mixed_2() {
         Err(
             Error {
                 cycle: [
-                    "cycle_a(())",
-                    "cycle_b(())",
-                    "cycle_c(())",
+                    "cycles::CycleAQuery::cycle_a(())",
+                    "cycles::CycleBQuery::cycle_b(())",
+                    "cycles::CycleCQuery::cycle_c(())",
                 ],
             },
         )
@@ -400,16 +400,16 @@ fn cycle_deterministic_order() {
             Err(
                 Error {
                     cycle: [
-                        "cycle_a(())",
-                        "cycle_b(())",
+                        "cycles::CycleAQuery::cycle_a(())",
+                        "cycles::CycleBQuery::cycle_b(())",
                     ],
                 },
             ),
             Err(
                 Error {
                     cycle: [
-                        "cycle_a(())",
-                        "cycle_b(())",
+                        "cycles::CycleAQuery::cycle_a(())",
+                        "cycles::CycleBQuery::cycle_b(())",
                     ],
                 },
             ),
@@ -445,24 +445,24 @@ fn cycle_multiple() {
             Err(
                 Error {
                     cycle: [
-                        "cycle_a(())",
-                        "cycle_b(())",
+                        "cycles::CycleAQuery::cycle_a(())",
+                        "cycles::CycleBQuery::cycle_b(())",
                     ],
                 },
             ),
             Err(
                 Error {
                     cycle: [
-                        "cycle_a(())",
-                        "cycle_b(())",
+                        "cycles::CycleAQuery::cycle_a(())",
+                        "cycles::CycleBQuery::cycle_b(())",
                     ],
                 },
             ),
             Err(
                 Error {
                     cycle: [
-                        "cycle_a(())",
-                        "cycle_b(())",
+                        "cycles::CycleAQuery::cycle_a(())",
+                        "cycles::CycleBQuery::cycle_b(())",
                     ],
                 },
             ),
@@ -485,7 +485,7 @@ fn cycle_recovery_set_but_not_participating() {
     let r = extract_cycle(|| drop(db.cycle_a()));
     expect![[r#"
         [
-            "cycle_c(())",
+            "cycles::CycleCQuery::cycle_c(())",
         ]
     "#]]
     .assert_debug_eq(&r.all_participants(&db));
diff --git a/crates/salsa/tests/on_demand_inputs.rs b/crates/salsa/tests/on_demand_inputs.rs
index 677d633ee7c..cad594f536f 100644
--- a/crates/salsa/tests/on_demand_inputs.rs
+++ b/crates/salsa/tests/on_demand_inputs.rs
@@ -103,10 +103,10 @@ fn on_demand_input_durability() {
     expect_test::expect![[r#"
         RefCell {
             value: [
-                "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: b(1) } }",
-                "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: a(1) } }",
-                "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: b(2) } }",
-                "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: a(2) } }",
+                "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: on_demand_inputs::BQuery::b(1) } }",
+                "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: on_demand_inputs::AQuery::a(1) } }",
+                "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: on_demand_inputs::BQuery::b(2) } }",
+                "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: on_demand_inputs::AQuery::a(2) } }",
             ],
         }
     "#]].assert_debug_eq(&events);
@@ -119,11 +119,11 @@ fn on_demand_input_durability() {
     expect_test::expect![[r#"
         RefCell {
             value: [
-                "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: c(1) } }",
-                "Event { runtime_id: RuntimeId { counter: 0 }, kind: DidValidateMemoizedValue { database_key: b(1) } }",
-                "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: c(2) } }",
-                "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: a(2) } }",
-                "Event { runtime_id: RuntimeId { counter: 0 }, kind: DidValidateMemoizedValue { database_key: b(2) } }",
+                "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: on_demand_inputs::CQuery::c(1) } }",
+                "Event { runtime_id: RuntimeId { counter: 0 }, kind: DidValidateMemoizedValue { database_key: on_demand_inputs::BQuery::b(1) } }",
+                "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: on_demand_inputs::CQuery::c(2) } }",
+                "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: on_demand_inputs::AQuery::a(2) } }",
+                "Event { runtime_id: RuntimeId { counter: 0 }, kind: DidValidateMemoizedValue { database_key: on_demand_inputs::BQuery::b(2) } }",
             ],
         }
     "#]].assert_debug_eq(&events);
@@ -137,10 +137,10 @@ fn on_demand_input_durability() {
     expect_test::expect![[r#"
         RefCell {
             value: [
-                "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: a(1) } }",
-                "Event { runtime_id: RuntimeId { counter: 0 }, kind: DidValidateMemoizedValue { database_key: c(1) } }",
-                "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: a(2) } }",
-                "Event { runtime_id: RuntimeId { counter: 0 }, kind: DidValidateMemoizedValue { database_key: c(2) } }",
+                "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: on_demand_inputs::AQuery::a(1) } }",
+                "Event { runtime_id: RuntimeId { counter: 0 }, kind: DidValidateMemoizedValue { database_key: on_demand_inputs::CQuery::c(1) } }",
+                "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: on_demand_inputs::AQuery::a(2) } }",
+                "Event { runtime_id: RuntimeId { counter: 0 }, kind: DidValidateMemoizedValue { database_key: on_demand_inputs::CQuery::c(2) } }",
             ],
         }
     "#]].assert_debug_eq(&events);
diff --git a/crates/salsa/tests/parallel/parallel_cycle_none_recover.rs b/crates/salsa/tests/parallel/parallel_cycle_none_recover.rs
index e94982f513c..2930c4e379f 100644
--- a/crates/salsa/tests/parallel/parallel_cycle_none_recover.rs
+++ b/crates/salsa/tests/parallel/parallel_cycle_none_recover.rs
@@ -27,8 +27,8 @@ fn parallel_cycle_none_recover() {
     if let Some(c) = err_b.downcast_ref::<salsa::Cycle>() {
         expect![[r#"
             [
-                "a(-1)",
-                "b(-1)",
+                "parallel::parallel_cycle_none_recover::AQuery::a(-1)",
+                "parallel::parallel_cycle_none_recover::BQuery::b(-1)",
             ]
         "#]]
         .assert_debug_eq(&c.unexpected_participants(&db));