Add tracing spans to macro generated database

This commit is contained in:
Lukas Wirth 2024-03-06 19:11:40 +01:00
parent 52d8ae791d
commit a3b6e891ea
12 changed files with 78 additions and 128 deletions

View File

@ -348,7 +348,7 @@ pub(crate) fn attrs_query(db: &dyn DefDatabase, def: AttrDefId) -> Attrs {
.raw_attrs(AttrOwner::ModItem(definition_tree_id.value.into())) .raw_attrs(AttrOwner::ModItem(definition_tree_id.value.into()))
.clone(), .clone(),
ModuleOrigin::BlockExpr { id, .. } => { ModuleOrigin::BlockExpr { id, .. } => {
let tree = db.block_item_tree_query(id); let tree = db.block_item_tree(id);
tree.raw_attrs(AttrOwner::TopLevel).clone() tree.raw_attrs(AttrOwner::TopLevel).clone()
} }
} }

View File

@ -87,14 +87,10 @@ pub trait DefDatabase: InternDatabase + ExpandDatabase + Upcast<dyn ExpandDataba
fn file_item_tree(&self, file_id: HirFileId) -> Arc<ItemTree>; fn file_item_tree(&self, file_id: HirFileId) -> Arc<ItemTree>;
#[salsa::invoke(ItemTree::block_item_tree_query)] #[salsa::invoke(ItemTree::block_item_tree_query)]
fn block_item_tree_query(&self, block_id: BlockId) -> Arc<ItemTree>; fn block_item_tree(&self, block_id: BlockId) -> Arc<ItemTree>;
#[salsa::invoke(crate_def_map_wait)]
#[salsa::transparent]
fn crate_def_map(&self, krate: CrateId) -> Arc<DefMap>;
#[salsa::invoke(DefMap::crate_def_map_query)] #[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`. /// Computes the block-level `DefMap`.
#[salsa::invoke(DefMap::block_def_map_query)] #[salsa::invoke(DefMap::block_def_map_query)]
@ -253,11 +249,6 @@ fn include_macro_invoc(db: &dyn DefDatabase, krate: CrateId) -> Vec<(MacroCallId
.collect() .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 { fn crate_supports_no_std(db: &dyn DefDatabase, crate_id: CrateId) -> bool {
let file = db.crate_graph()[crate_id].root_file_id; let file = db.crate_graph()[crate_id].root_file_id;
let item_tree = db.file_item_tree(file.into()); let item_tree = db.file_item_tree(file.into());

View File

@ -392,7 +392,7 @@ pub(crate) fn new(file: HirFileId, block: Option<BlockId>) -> Self {
pub(crate) fn item_tree(&self, db: &dyn DefDatabase) -> Arc<ItemTree> { pub(crate) fn item_tree(&self, db: &dyn DefDatabase) -> Arc<ItemTree> {
match self.block { 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), None => db.file_item_tree(self.file),
} }
} }

View File

@ -31,12 +31,8 @@
#[salsa::query_group(HirDatabaseStorage)] #[salsa::query_group(HirDatabaseStorage)]
pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> { 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)] #[salsa::invoke(crate::infer::infer_query)]
fn infer_query(&self, def: DefWithBodyId) -> Arc<InferenceResult>; fn infer(&self, def: DefWithBodyId) -> Arc<InferenceResult>;
// region:mir // region:mir
@ -258,17 +254,8 @@ fn normalize_projection(
env: Arc<TraitEnvironment>, env: Arc<TraitEnvironment>,
) -> Ty; ) -> 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)] #[salsa::invoke(crate::traits::trait_solve_query)]
fn trait_solve_query( fn trait_solve(
&self, &self,
krate: CrateId, krate: CrateId,
block: Option<BlockId>, block: Option<BlockId>,
@ -284,38 +271,6 @@ fn program_clauses_for_chalk_env(
) -> chalk_ir::ProgramClauses<Interner>; ) -> 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] #[test]
fn hir_database_is_object_safe() { fn hir_database_is_object_safe() {
fn _assert_object_safe(_: &dyn HirDatabase) {} fn _assert_object_safe(_: &dyn HirDatabase) {}

View File

@ -4,20 +4,20 @@
//! //!
//! But we need this for at least LRU caching at the query level. //! But we need this for at least LRU caching at the query level.
pub use hir_def::db::{ pub use hir_def::db::{
AttrsQuery, BlockDefMapQuery, BlockItemTreeQueryQuery, BodyQuery, BodyWithSourceMapQuery, AttrsQuery, BlockDefMapQuery, BodyQuery, BodyWithSourceMapQuery, ConstDataQuery,
ConstDataQuery, ConstVisibilityQuery, CrateDefMapQueryQuery, CrateLangItemsQuery, ConstVisibilityQuery, CrateLangItemsQuery, CrateSupportsNoStdQuery, DefDatabase,
CrateSupportsNoStdQuery, DefDatabase, DefDatabaseStorage, EnumDataQuery, DefDatabaseStorage, EnumDataQuery, EnumVariantDataWithDiagnosticsQuery, ExprScopesQuery,
EnumVariantDataWithDiagnosticsQuery, ExprScopesQuery, ExternCrateDeclDataQuery, ExternCrateDeclDataQuery, FieldVisibilitiesQuery, FieldsAttrsQuery, FieldsAttrsSourceMapQuery,
FieldVisibilitiesQuery, FieldsAttrsQuery, FieldsAttrsSourceMapQuery, FileItemTreeQuery, FileItemTreeQuery, FunctionDataQuery, FunctionVisibilityQuery, GenericParamsQuery,
FunctionDataQuery, FunctionVisibilityQuery, GenericParamsQuery, ImplDataWithDiagnosticsQuery, ImplDataWithDiagnosticsQuery, ImportMapQuery, InternAnonymousConstQuery, InternBlockQuery,
ImportMapQuery, InternAnonymousConstQuery, InternBlockQuery, InternConstQuery, InternDatabase, InternConstQuery, InternDatabase, InternDatabaseStorage, InternEnumQuery,
InternDatabaseStorage, InternEnumQuery, InternExternBlockQuery, InternExternCrateQuery, InternExternBlockQuery, InternExternCrateQuery, InternFunctionQuery, InternImplQuery,
InternFunctionQuery, InternImplQuery, InternInTypeConstQuery, InternMacro2Query, InternInTypeConstQuery, InternMacro2Query, InternMacroRulesQuery, InternProcMacroQuery,
InternMacroRulesQuery, InternProcMacroQuery, InternStaticQuery, InternStructQuery, InternStaticQuery, InternStructQuery, InternTraitAliasQuery, InternTraitQuery,
InternTraitAliasQuery, InternTraitQuery, InternTypeAliasQuery, InternUnionQuery, InternTypeAliasQuery, InternUnionQuery, InternUseQuery, LangItemQuery, Macro2DataQuery,
InternUseQuery, LangItemQuery, Macro2DataQuery, MacroRulesDataQuery, ProcMacroDataQuery, MacroRulesDataQuery, ProcMacroDataQuery, StaticDataQuery, StructDataWithDiagnosticsQuery,
StaticDataQuery, StructDataWithDiagnosticsQuery, TraitAliasDataQuery, TraitAliasDataQuery, TraitDataWithDiagnosticsQuery, TypeAliasDataQuery,
TraitDataWithDiagnosticsQuery, TypeAliasDataQuery, UnionDataWithDiagnosticsQuery, UnionDataWithDiagnosticsQuery,
}; };
pub use hir_expand::db::{ pub use hir_expand::db::{
AstIdMapQuery, DeclMacroExpanderQuery, ExpandDatabase, ExpandDatabaseStorage, AstIdMapQuery, DeclMacroExpanderQuery, ExpandDatabase, ExpandDatabaseStorage,

View File

@ -91,7 +91,6 @@ macro_rules! purge_each_query {
crate::symbol_index::LocalRootsQuery crate::symbol_index::LocalRootsQuery
crate::symbol_index::LibraryRootsQuery crate::symbol_index::LibraryRootsQuery
// HirDatabase // HirDatabase
hir::db::InferQueryQuery
hir::db::MirBodyQuery hir::db::MirBodyQuery
hir::db::BorrowckQuery hir::db::BorrowckQuery
hir::db::TyQuery hir::db::TyQuery
@ -130,12 +129,10 @@ macro_rules! purge_each_query {
hir::db::FnDefVarianceQuery hir::db::FnDefVarianceQuery
hir::db::AdtVarianceQuery hir::db::AdtVarianceQuery
hir::db::AssociatedTyValueQuery hir::db::AssociatedTyValueQuery
hir::db::TraitSolveQueryQuery
hir::db::ProgramClausesForChalkEnvQuery hir::db::ProgramClausesForChalkEnvQuery
// DefDatabase // DefDatabase
hir::db::FileItemTreeQuery hir::db::FileItemTreeQuery
hir::db::CrateDefMapQueryQuery
hir::db::BlockDefMapQuery hir::db::BlockDefMapQuery
hir::db::StructDataWithDiagnosticsQuery hir::db::StructDataWithDiagnosticsQuery
hir::db::UnionDataWithDiagnosticsQuery hir::db::UnionDataWithDiagnosticsQuery
@ -165,7 +162,6 @@ macro_rules! purge_each_query {
hir::db::FunctionVisibilityQuery hir::db::FunctionVisibilityQuery
hir::db::ConstVisibilityQuery hir::db::ConstVisibilityQuery
hir::db::CrateSupportsNoStdQuery hir::db::CrateSupportsNoStdQuery
hir::db::BlockItemTreeQueryQuery
hir::db::ExternCrateDeclDataQuery hir::db::ExternCrateDeclDataQuery
hir::db::InternAnonymousConstQuery hir::db::InternAnonymousConstQuery
hir::db::InternExternCrateQuery hir::db::InternExternCrateQuery

View File

@ -216,7 +216,6 @@ macro_rules! update_lru_capacity_per_query {
// DefDatabase // DefDatabase
hir_db::FileItemTreeQuery hir_db::FileItemTreeQuery
hir_db::CrateDefMapQueryQuery
hir_db::BlockDefMapQuery hir_db::BlockDefMapQuery
hir_db::StructDataWithDiagnosticsQuery hir_db::StructDataWithDiagnosticsQuery
hir_db::UnionDataWithDiagnosticsQuery hir_db::UnionDataWithDiagnosticsQuery
@ -248,7 +247,6 @@ macro_rules! update_lru_capacity_per_query {
hir_db::CrateSupportsNoStdQuery hir_db::CrateSupportsNoStdQuery
// HirDatabase // HirDatabase
hir_db::InferQueryQuery
hir_db::MirBodyQuery hir_db::MirBodyQuery
hir_db::BorrowckQuery hir_db::BorrowckQuery
hir_db::TyQuery hir_db::TyQuery
@ -287,7 +285,6 @@ macro_rules! update_lru_capacity_per_query {
hir_db::FnDefVarianceQuery hir_db::FnDefVarianceQuery
hir_db::AdtVarianceQuery hir_db::AdtVarianceQuery
hir_db::AssociatedTyValueQuery hir_db::AssociatedTyValueQuery
hir_db::TraitSolveQueryQuery
hir_db::ProgramClausesForChalkEnvQuery hir_db::ProgramClausesForChalkEnvQuery
// SymbolsDatabase // SymbolsDatabase

View File

@ -235,8 +235,19 @@ fn #fn_name(&self, #(#key_names: #keys),*) -> #value {
queries_with_storage.push(fn_name); 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! { query_fn_definitions.extend(quote! {
fn #fn_name(&self, #(#key_names: #keys),*) -> #value { fn #fn_name(&self, #(#key_names: #keys),*) -> #value {
#(#tracing),*
// Create a shim to force the code to be monomorphized in the // Create a shim to force the code to be monomorphized in the
// query crate. Our experiments revealed that this makes a big // query crate. Our experiments revealed that this makes a big
// difference in total compilation time in rust-analyzer, though // difference in total compilation time in rust-analyzer, though

View File

@ -136,7 +136,7 @@ fn fmt_index(
) -> std::fmt::Result { ) -> std::fmt::Result {
let slot_map = self.slot_map.read(); let slot_map = self.slot_map.read();
let key = slot_map.get_index(index as usize).unwrap().0; 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( fn maybe_changed_after(
@ -146,13 +146,13 @@ fn maybe_changed_after(
revision: Revision, revision: Revision,
) -> bool { ) -> bool {
debug_assert!(revision < db.salsa_runtime().current_revision()); debug_assert!(revision < db.salsa_runtime().current_revision());
let (key, slot) = {
let read = self.slot_map.read(); let read = self.slot_map.read();
let Some((key, slot)) = read.get_index(index as usize) else { let Some((key, slot)) = read.get_index(index as usize) else {
return false; return false;
}; };
let (key, slot) = (key.clone(), slot.clone()); (key.clone(), slot.clone())
// note: this drop is load-bearing. removing it would causes deadlocks. };
drop(read);
slot.maybe_changed_after(db, revision, &key) slot.maybe_changed_after(db, revision, &key)
} }

View File

@ -171,8 +171,8 @@ fn cycle_memoized() {
let cycle = extract_cycle(|| db.memoized_a()); let cycle = extract_cycle(|| db.memoized_a());
expect![[r#" expect![[r#"
[ [
"memoized_a(())", "cycles::MemoizedAQuery::memoized_a(())",
"memoized_b(())", "cycles::MemoizedBQuery::memoized_b(())",
] ]
"#]] "#]]
.assert_debug_eq(&cycle.unexpected_participants(&db)); .assert_debug_eq(&cycle.unexpected_participants(&db));
@ -184,8 +184,8 @@ fn cycle_volatile() {
let cycle = extract_cycle(|| db.volatile_a()); let cycle = extract_cycle(|| db.volatile_a());
expect![[r#" expect![[r#"
[ [
"volatile_a(())", "cycles::VolatileAQuery::volatile_a(())",
"volatile_b(())", "cycles::VolatileBQuery::volatile_b(())",
] ]
"#]] "#]]
.assert_debug_eq(&cycle.unexpected_participants(&db)); .assert_debug_eq(&cycle.unexpected_participants(&db));
@ -222,8 +222,8 @@ fn inner_cycle() {
let cycle = err.unwrap_err().cycle; let cycle = err.unwrap_err().cycle;
expect![[r#" expect![[r#"
[ [
"cycle_a(())", "cycles::CycleAQuery::cycle_a(())",
"cycle_b(())", "cycles::CycleBQuery::cycle_b(())",
] ]
"#]] "#]]
.assert_debug_eq(&cycle); .assert_debug_eq(&cycle);
@ -262,8 +262,8 @@ fn cycle_revalidate_unchanged_twice() {
Err( Err(
Error { Error {
cycle: [ cycle: [
"cycle_a(())", "cycles::CycleAQuery::cycle_a(())",
"cycle_b(())", "cycles::CycleBQuery::cycle_b(())",
], ],
}, },
) )
@ -344,8 +344,8 @@ fn cycle_mixed_1() {
Err( Err(
Error { Error {
cycle: [ cycle: [
"cycle_b(())", "cycles::CycleBQuery::cycle_b(())",
"cycle_c(())", "cycles::CycleCQuery::cycle_c(())",
], ],
}, },
) )
@ -371,9 +371,9 @@ fn cycle_mixed_2() {
Err( Err(
Error { Error {
cycle: [ cycle: [
"cycle_a(())", "cycles::CycleAQuery::cycle_a(())",
"cycle_b(())", "cycles::CycleBQuery::cycle_b(())",
"cycle_c(())", "cycles::CycleCQuery::cycle_c(())",
], ],
}, },
) )
@ -400,16 +400,16 @@ fn cycle_deterministic_order() {
Err( Err(
Error { Error {
cycle: [ cycle: [
"cycle_a(())", "cycles::CycleAQuery::cycle_a(())",
"cycle_b(())", "cycles::CycleBQuery::cycle_b(())",
], ],
}, },
), ),
Err( Err(
Error { Error {
cycle: [ cycle: [
"cycle_a(())", "cycles::CycleAQuery::cycle_a(())",
"cycle_b(())", "cycles::CycleBQuery::cycle_b(())",
], ],
}, },
), ),
@ -445,24 +445,24 @@ fn cycle_multiple() {
Err( Err(
Error { Error {
cycle: [ cycle: [
"cycle_a(())", "cycles::CycleAQuery::cycle_a(())",
"cycle_b(())", "cycles::CycleBQuery::cycle_b(())",
], ],
}, },
), ),
Err( Err(
Error { Error {
cycle: [ cycle: [
"cycle_a(())", "cycles::CycleAQuery::cycle_a(())",
"cycle_b(())", "cycles::CycleBQuery::cycle_b(())",
], ],
}, },
), ),
Err( Err(
Error { Error {
cycle: [ cycle: [
"cycle_a(())", "cycles::CycleAQuery::cycle_a(())",
"cycle_b(())", "cycles::CycleBQuery::cycle_b(())",
], ],
}, },
), ),
@ -485,7 +485,7 @@ fn cycle_recovery_set_but_not_participating() {
let r = extract_cycle(|| drop(db.cycle_a())); let r = extract_cycle(|| drop(db.cycle_a()));
expect![[r#" expect![[r#"
[ [
"cycle_c(())", "cycles::CycleCQuery::cycle_c(())",
] ]
"#]] "#]]
.assert_debug_eq(&r.all_participants(&db)); .assert_debug_eq(&r.all_participants(&db));

View File

@ -103,10 +103,10 @@ fn on_demand_input_durability() {
expect_test::expect![[r#" expect_test::expect![[r#"
RefCell { RefCell {
value: [ value: [
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: b(1) } }", "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: a(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: b(2) } }", "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: a(2) } }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: on_demand_inputs::AQuery::a(2) } }",
], ],
} }
"#]].assert_debug_eq(&events); "#]].assert_debug_eq(&events);
@ -119,11 +119,11 @@ fn on_demand_input_durability() {
expect_test::expect![[r#" expect_test::expect![[r#"
RefCell { RefCell {
value: [ value: [
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: c(1) } }", "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: b(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: c(2) } }", "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: a(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: b(2) } }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: DidValidateMemoizedValue { database_key: on_demand_inputs::BQuery::b(2) } }",
], ],
} }
"#]].assert_debug_eq(&events); "#]].assert_debug_eq(&events);
@ -137,10 +137,10 @@ fn on_demand_input_durability() {
expect_test::expect![[r#" expect_test::expect![[r#"
RefCell { RefCell {
value: [ value: [
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: a(1) } }", "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: c(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: a(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: c(2) } }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: DidValidateMemoizedValue { database_key: on_demand_inputs::CQuery::c(2) } }",
], ],
} }
"#]].assert_debug_eq(&events); "#]].assert_debug_eq(&events);

View File

@ -27,8 +27,8 @@ fn parallel_cycle_none_recover() {
if let Some(c) = err_b.downcast_ref::<salsa::Cycle>() { if let Some(c) = err_b.downcast_ref::<salsa::Cycle>() {
expect![[r#" expect![[r#"
[ [
"a(-1)", "parallel::parallel_cycle_none_recover::AQuery::a(-1)",
"b(-1)", "parallel::parallel_cycle_none_recover::BQuery::b(-1)",
] ]
"#]] "#]]
.assert_debug_eq(&c.unexpected_participants(&db)); .assert_debug_eq(&c.unexpected_participants(&db));