From 3d01f41270a929b8c3a7bb9dff6531df6a585c0a Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Sat, 27 Jul 2024 12:29:41 +0000 Subject: [PATCH] switch to new database design Under this design, *all* databases are a `DatabaseImpl`, where the `U` implements `UserData` (you can use `()` if there is none). Code would default to `&dyn salsa::Database` but if you want to give access to the userdata, you can define a custom database trait `MyDatabase: salsa::Databse` so long as you * annotate `MyDatabase` trait definition of impls of `MyDatabase` with `#[salsa::db]` * implement `MyDatabase` for `DatabaseImpl` where `U` is your userdata (this could be a blanket impl, if you don't know the precise userdata type). The `tests/common/mod.rs` shows the pattern. --- components/salsa-macros/src/db.rs | 52 +-------- examples/calc/db.rs | 43 ++++--- examples/calc/main.rs | 3 +- examples/calc/parser.rs | 6 +- examples/calc/type_check.rs | 9 +- examples/lazy-input/main.rs | 35 +++--- src/database.rs | 109 ++++++++++++++++-- src/function/accumulated.rs | 4 +- src/function/execute.rs | 3 +- src/function/fetch.rs | 3 +- src/function/maybe_changed_after.rs | 4 +- src/function/specify.rs | 1 - src/lib.rs | 20 +--- src/storage.rs | 46 ++++---- tests/accumulate-chain.rs | 4 +- tests/accumulate-custom-clone.rs | 2 +- tests/accumulate-custom-debug.rs | 2 +- tests/accumulate-dag.rs | 2 +- tests/accumulate-execution-order.rs | 2 +- tests/accumulate-from-tracked-fn.rs | 31 +---- tests/accumulate-no-duplicates.rs | 2 +- tests/accumulate-reuse-workaround.rs | 36 +----- tests/accumulate-reuse.rs | 32 +---- tests/accumulate.rs | 40 ++----- tests/common/mod.rs | 96 ++++++++++++++- .../get-set-on-private-input-field.rs | 2 +- ...of-tracked-structs-from-older-revisions.rs | 2 +- tests/compile-fail/span-input-setter.rs | 2 +- tests/compile-fail/span-tracked-getter.rs | 2 +- tests/compile-fail/span-tracked-getter.stderr | 2 +- tests/cycles.rs | 41 +++---- tests/debug.rs | 17 +-- tests/deletion-cascade.rs | 47 ++------ tests/deletion-drops.rs | 2 +- tests/deletion.rs | 43 +------ tests/elided-lifetime-in-tracked-fn.rs | 32 +---- ...truct_changes_but_fn_depends_on_field_y.rs | 34 +----- ...input_changes_but_fn_depends_on_field_y.rs | 31 +---- tests/hello_world.rs | 32 +---- tests/interned-struct-with-lifetime.rs | 30 +---- tests/is_send_sync.rs | 20 +--- tests/lru.rs | 40 ++----- tests/mutate_in_place.rs | 21 +--- tests/override_new_get_set.rs | 14 +-- ...ng-tracked-struct-outside-of-tracked-fn.rs | 11 +- tests/parallel/parallel_cancellation.rs | 15 +-- tests/parallel/parallel_cycle_all_recover.rs | 27 ++--- tests/parallel/parallel_cycle_mid_recover.rs | 27 ++--- tests/parallel/parallel_cycle_none_recover.rs | 15 +-- tests/parallel/parallel_cycle_one_recover.rs | 23 ++-- tests/parallel/setup.rs | 35 +++--- tests/preverify-struct-with-leaked-data.rs | 35 +----- tests/singleton.rs | 24 +--- ...the-key-is-created-in-the-current-query.rs | 26 ++--- tests/tracked-struct-id-field-bad-eq.rs | 16 +-- tests/tracked-struct-id-field-bad-hash.rs | 11 +- tests/tracked-struct-unchanged-in-new-rev.rs | 11 +- tests/tracked-struct-value-field-bad-eq.rs | 39 +------ tests/tracked-struct-value-field-not-eq.rs | 15 +-- tests/tracked_fn_constant.rs | 11 +- tests/tracked_fn_no_eq.rs | 33 +----- tests/tracked_fn_on_input.rs | 11 +- tests/tracked_fn_on_interned.rs | 11 +- tests/tracked_fn_on_tracked.rs | 11 +- tests/tracked_fn_on_tracked_specify.rs | 13 +-- tests/tracked_fn_read_own_entity.rs | 32 +---- tests/tracked_fn_read_own_specify.rs | 32 +---- tests/tracked_fn_return_ref.rs | 13 +-- tests/tracked_method.rs | 11 +- tests/tracked_method_inherent_return_ref.rs | 13 +-- tests/tracked_method_on_tracked_struct.rs | 4 +- tests/tracked_method_trait_return_ref.rs | 13 +-- tests/tracked_struct_db1_lt.rs | 9 -- tests/tracked_with_intern.rs | 9 -- tests/tracked_with_struct_db.rs | 15 +-- 75 files changed, 484 insertions(+), 1088 deletions(-) diff --git a/components/salsa-macros/src/db.rs b/components/salsa-macros/src/db.rs index b7057613..e70ad745 100644 --- a/components/salsa-macros/src/db.rs +++ b/components/salsa-macros/src/db.rs @@ -32,13 +32,6 @@ struct DbMacro { impl DbMacro { fn try_db(self, input: syn::Item) -> syn::Result { match input { - syn::Item::Struct(input) => { - let has_storage_impl = self.zalsa_database_impl(&input)?; - Ok(quote! { - #has_storage_impl - #input - }) - } syn::Item::Trait(mut input) => { self.add_salsa_view_method(&mut input)?; Ok(quote! { @@ -53,54 +46,11 @@ impl DbMacro { } _ => Err(syn::Error::new_spanned( input, - "`db` must be applied to a struct, trait, or impl", + "`db` must be applied to a trait or impl", )), } } - fn find_storage_field(&self, input: &syn::ItemStruct) -> syn::Result { - let storage = "storage"; - for field in input.fields.iter() { - if let Some(i) = &field.ident { - if i == storage { - return Ok(i.clone()); - } - } else { - return Err(syn::Error::new_spanned( - field, - "database struct must be a braced struct (`{}`) with a field named `storage`", - )); - } - } - - Err(syn::Error::new_spanned( - &input.ident, - "database struct must be a braced struct (`{}`) with a field named `storage`", - )) - } - - fn zalsa_database_impl(&self, input: &syn::ItemStruct) -> syn::Result { - let storage = self.find_storage_field(input)?; - let db = &input.ident; - let zalsa = self.hygiene.ident("zalsa"); - - Ok(quote! { - const _: () = { - use salsa::plumbing as #zalsa; - - unsafe impl #zalsa::ZalsaDatabase for #db { - fn zalsa(&self) -> &dyn #zalsa::Zalsa { - &self.#storage - } - - fn zalsa_mut(&mut self) -> &mut dyn #zalsa::Zalsa { - &mut self.#storage - } - } - }; - }) - } - fn add_salsa_view_method(&self, input: &mut syn::ItemTrait) -> syn::Result<()> { input.items.push(parse_quote! { #[doc(hidden)] diff --git a/examples/calc/db.rs b/examples/calc/db.rs index 35d47341..5f1d98f7 100644 --- a/examples/calc/db.rs +++ b/examples/calc/db.rs @@ -1,49 +1,48 @@ use std::sync::{Arc, Mutex}; +use salsa::UserData; + +pub type CalcDatabaseImpl = salsa::DatabaseImpl; + // ANCHOR: db_struct #[derive(Default)] -#[salsa::db] -pub(crate) struct Database { - storage: salsa::Storage, - +pub struct Calc { // The logs are only used for testing and demonstrating reuse: - // - logs: Option>>>, + logs: Arc>>>, } // ANCHOR_END: db_struct -impl Database { +impl Calc { /// Enable logging of each salsa event. #[cfg(test)] - pub fn enable_logging(self) -> Self { - assert!(self.logs.is_none()); - Self { - storage: self.storage, - logs: Some(Default::default()), + pub fn enable_logging(&self) { + let mut logs = self.logs.lock().unwrap(); + if logs.is_none() { + *logs = Some(vec![]); } } #[cfg(test)] - pub fn take_logs(&mut self) -> Vec { - if let Some(logs) = &self.logs { - std::mem::take(&mut *logs.lock().unwrap()) + pub fn take_logs(&self) -> Vec { + let mut logs = self.logs.lock().unwrap(); + if let Some(logs) = &mut *logs { + std::mem::take(logs) } else { - panic!("logs not enabled"); + vec![] } } } // ANCHOR: db_impl -#[salsa::db] -impl salsa::Database for Database { - fn salsa_event(&self, event: &dyn Fn() -> salsa::Event) { +impl UserData for Calc { + fn salsa_event(db: &CalcDatabaseImpl, event: &dyn Fn() -> salsa::Event) { let event = event(); eprintln!("Event: {event:?}"); // Log interesting events, if logging is enabled - if let Some(logs) = &self.logs { - // don't log boring events + if let Some(logs) = &mut *db.logs.lock().unwrap() { + // only log interesting events if let salsa::EventKind::WillExecute { .. } = event.kind { - logs.lock().unwrap().push(format!("Event: {event:?}")); + logs.push(format!("Event: {event:?}")); } } } diff --git a/examples/calc/main.rs b/examples/calc/main.rs index 332b20e2..616dede6 100644 --- a/examples/calc/main.rs +++ b/examples/calc/main.rs @@ -1,3 +1,4 @@ +use db::CalcDatabaseImpl; use ir::{Diagnostic, SourceProgram}; use salsa::Database as Db; @@ -8,7 +9,7 @@ mod parser; mod type_check; pub fn main() { - let db = db::Database::default(); + let db: CalcDatabaseImpl = Default::default(); let source_program = SourceProgram::new(&db, String::new()); compile::compile(&db, source_program); let diagnostics = compile::compile::accumulated::(&db, source_program); diff --git a/examples/calc/parser.rs b/examples/calc/parser.rs index 05c1c4b3..40077361 100644 --- a/examples/calc/parser.rs +++ b/examples/calc/parser.rs @@ -351,9 +351,11 @@ impl<'db> Parser<'_, 'db> { /// Returns the statements and the diagnostics generated. #[cfg(test)] fn parse_string(source_text: &str) -> String { - use salsa::Database as _; + use salsa::Database; - crate::db::Database::default().attach(|db| { + use crate::db::CalcDatabaseImpl; + + CalcDatabaseImpl::default().attach(|db| { // Create the source program let source_program = SourceProgram::new(db, source_text.to_string()); diff --git a/examples/calc/type_check.rs b/examples/calc/type_check.rs index 4fe22605..de449ad3 100644 --- a/examples/calc/type_check.rs +++ b/examples/calc/type_check.rs @@ -6,8 +6,6 @@ use derive_new::new; use expect_test::expect; use salsa::Accumulator; #[cfg(test)] -use salsa::Database as _; -#[cfg(test)] use test_log::test; // ANCHOR: parse_statements @@ -100,12 +98,13 @@ fn check_string( expected_diagnostics: expect_test::Expect, edits: &[(&str, expect_test::Expect, expect_test::Expect)], ) { - use salsa::Setter; + use salsa::{Database, Setter}; - use crate::{db::Database, ir::SourceProgram, parser::parse_statements}; + use crate::{db::CalcDatabaseImpl, ir::SourceProgram, parser::parse_statements}; // Create the database - let mut db = Database::default().enable_logging(); + let mut db = CalcDatabaseImpl::default(); + db.enable_logging(); // Create the source program let source_program = SourceProgram::new(&db, source_text.to_string()); diff --git a/examples/lazy-input/main.rs b/examples/lazy-input/main.rs index daf0c21c..b4ce1e48 100644 --- a/examples/lazy-input/main.rs +++ b/examples/lazy-input/main.rs @@ -8,13 +8,13 @@ use notify_debouncer_mini::{ notify::{RecommendedWatcher, RecursiveMode}, DebounceEventResult, Debouncer, }; -use salsa::{Accumulator, Setter}; +use salsa::{Accumulator, DatabaseImpl, Setter, UserData}; // ANCHOR: main fn main() -> Result<()> { // Create the channel to receive file change events. let (tx, rx) = unbounded(); - let mut db = Database::new(tx); + let mut db = DatabaseImpl::with(LazyInput::new(tx)); let initial_file_path = std::env::args_os() .nth(1) @@ -74,19 +74,15 @@ trait Db: salsa::Database { fn input(&self, path: PathBuf) -> Result; } -#[salsa::db] -struct Database { - storage: salsa::Storage, +struct LazyInput { logs: Mutex>, files: DashMap, file_watcher: Mutex>, } -impl Database { +impl LazyInput { fn new(tx: Sender) -> Self { - let storage = Default::default(); Self { - storage, logs: Default::default(), files: DashMap::new(), file_watcher: Mutex::new(new_debouncer(Duration::from_secs(1), None, tx).unwrap()), @@ -94,8 +90,18 @@ impl Database { } } +impl UserData for LazyInput { + fn salsa_event(db: &DatabaseImpl, event: &dyn Fn() -> salsa::Event) { + // don't log boring events + let event = event(); + if let salsa::EventKind::WillExecute { .. } = event.kind { + db.logs.lock().unwrap().push(format!("{:?}", event)); + } + } +} + #[salsa::db] -impl Db for Database { +impl Db for DatabaseImpl { fn input(&self, path: PathBuf) -> Result { let path = path .canonicalize() @@ -122,17 +128,6 @@ impl Db for Database { } // ANCHOR_END: db -#[salsa::db] -impl salsa::Database for Database { - fn salsa_event(&self, event: &dyn Fn() -> salsa::Event) { - // don't log boring events - let event = event(); - if let salsa::EventKind::WillExecute { .. } = event.kind { - self.logs.lock().unwrap().push(format!("{:?}", event)); - } - } -} - #[salsa::accumulator] struct Diagnostic(String); diff --git a/src/database.rs b/src/database.rs index 23606cfa..52f74e65 100644 --- a/src/database.rs +++ b/src/database.rs @@ -1,20 +1,24 @@ -use crate::{local_state, storage::ZalsaDatabase, Durability, Event, Revision}; +use std::{any::Any, panic::RefUnwindSafe}; +use crate::{self as salsa, local_state, storage::Zalsa, Durability, Event, Revision, Storage}; + +/// The trait implemented by all Salsa databases. +/// You can create your own subtraits of this trait using the `#[salsa::db]` procedural macro. +/// +/// # Safety conditions +/// +/// This trait can only safely be implemented by Salsa's [`DatabaseImpl`][] type. +/// FIXME: Document better the unsafety conditions we guarantee. #[salsa_macros::db] -pub trait Database: ZalsaDatabase + AsDynDatabase { - /// This function is invoked at key points in the salsa - /// runtime. It permits the database to be customized and to - /// inject logging or other custom behavior. - /// - /// By default, the event is logged at level debug using - /// the standard `log` facade. +pub unsafe trait Database: AsDynDatabase + Any { + /// This function is invoked by the salsa runtime at various points during execution. + /// You can customize what happens by implementing the [`UserData`][] trait. + /// By default, the event is logged at level debug using tracing facade. /// /// # Parameters /// /// * `event`, a fn that, if called, will create the event that occurred - fn salsa_event(&self, event: &dyn Fn() -> Event) { - tracing::debug!("salsa_event: {:?}", event()) - } + fn salsa_event(&self, event: &dyn Fn() -> Event); /// A "synthetic write" causes the system to act *as though* some /// input of durability `durability` has changed. This is mostly @@ -48,6 +52,13 @@ pub trait Database: ZalsaDatabase + AsDynDatabase { { local_state::attach(self, |_state| op(self)) } + + /// Plumbing methods. + #[doc(hidden)] + fn zalsa(&self) -> &dyn Zalsa; + + #[doc(hidden)] + fn zalsa_mut(&mut self) -> &mut dyn Zalsa; } /// Upcast to a `dyn Database`. @@ -83,3 +94,79 @@ impl dyn Database { self.zalsa().views().try_view_as(self).unwrap() } } + +/// Concrete implementation of the [`Database`][] trait. +/// Takes an optional type parameter `U` that allows you to thread your own data. +pub struct DatabaseImpl { + storage: Storage, +} + +impl Default for DatabaseImpl { + fn default() -> Self { + Self::with(U::default()) + } +} + +impl DatabaseImpl<()> { + /// Create a new database with the given user data. + /// + /// You can also use the [`Default`][] trait if your userdata implements it. + pub fn new() -> Self { + Self { + storage: Storage::with(()), + } + } +} + +impl DatabaseImpl { + /// Create a new database with the given user data. + /// + /// You can also use the [`Default`][] trait if your userdata implements it. + pub fn with(u: U) -> Self { + Self { + storage: Storage::with(u), + } + } +} + +impl std::ops::Deref for DatabaseImpl { + type Target = U; + + fn deref(&self) -> &U { + &self.storage.user_data() + } +} + +impl RefUnwindSafe for DatabaseImpl {} + +#[salsa_macros::db] +unsafe impl Database for DatabaseImpl { + fn zalsa(&self) -> &dyn Zalsa { + &self.storage + } + + fn zalsa_mut(&mut self) -> &mut dyn Zalsa { + &mut self.storage + } + + // Report a salsa event. + fn salsa_event(&self, event: &dyn Fn() -> Event) { + U::salsa_event(self, event) + } +} + +pub trait UserData: Any + Sized { + /// Callback invoked by the [`Database`][] at key points during salsa execution. + /// By overriding this method, you can inject logging or other custom behavior. + /// + /// By default, the event is logged at level debug using the `tracing` crate. + /// + /// # Parameters + /// + /// * `event` a fn that, if called, will return the event that occurred + fn salsa_event(_db: &DatabaseImpl, event: &dyn Fn() -> Event) { + tracing::debug!("salsa_event: {:?}", event()) + } +} + +impl UserData for () {} diff --git a/src/function/accumulated.rs b/src/function/accumulated.rs index d1fc003d..98d11eaa 100644 --- a/src/function/accumulated.rs +++ b/src/function/accumulated.rs @@ -1,6 +1,4 @@ -use crate::{ - accumulator, hash::FxHashSet, local_state, storage::ZalsaDatabase as _, DatabaseKeyIndex, Id, -}; +use crate::{accumulator, hash::FxHashSet, local_state, Database, DatabaseKeyIndex, Id}; use super::{Configuration, IngredientImpl}; diff --git a/src/function/execute.rs b/src/function/execute.rs index 9ed1699e..cba601d0 100644 --- a/src/function/execute.rs +++ b/src/function/execute.rs @@ -1,8 +1,7 @@ use std::sync::Arc; use crate::{ - local_state::ActiveQueryGuard, runtime::StampedValue, storage::ZalsaDatabase, Cycle, Database, - Event, EventKind, + local_state::ActiveQueryGuard, runtime::StampedValue, Cycle, Database, Event, EventKind, }; use super::{memo::Memo, Configuration, IngredientImpl}; diff --git a/src/function/fetch.rs b/src/function/fetch.rs index 2474acbe..f204145f 100644 --- a/src/function/fetch.rs +++ b/src/function/fetch.rs @@ -3,8 +3,7 @@ use arc_swap::Guard; use crate::{ local_state::{self, LocalState}, runtime::StampedValue, - storage::ZalsaDatabase as _, - AsDynDatabase as _, Id, + AsDynDatabase as _, Database as _, Id, }; use super::{Configuration, IngredientImpl}; diff --git a/src/function/maybe_changed_after.rs b/src/function/maybe_changed_after.rs index a9426cf7..15a677d5 100644 --- a/src/function/maybe_changed_after.rs +++ b/src/function/maybe_changed_after.rs @@ -4,8 +4,8 @@ use crate::{ key::DatabaseKeyIndex, local_state::{self, ActiveQueryGuard, EdgeKind, LocalState, QueryOrigin}, runtime::StampedValue, - storage::{Zalsa, ZalsaDatabase as _}, - AsDynDatabase as _, Id, Revision, + storage::Zalsa, + AsDynDatabase as _, Database, Id, Revision, }; use super::{memo::Memo, Configuration, IngredientImpl}; diff --git a/src/function/specify.rs b/src/function/specify.rs index 37e88082..d8d5dea8 100644 --- a/src/function/specify.rs +++ b/src/function/specify.rs @@ -2,7 +2,6 @@ use crossbeam::atomic::AtomicCell; use crate::{ local_state::{self, QueryOrigin, QueryRevisions}, - storage::ZalsaDatabase, tracked_struct::TrackedStructInDb, AsDynDatabase as _, Database, DatabaseKeyIndex, Id, }; diff --git a/src/lib.rs b/src/lib.rs index 395938dd..7b38a291 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -31,6 +31,8 @@ pub use self::cancelled::Cancelled; pub use self::cycle::Cycle; pub use self::database::AsDynDatabase; pub use self::database::Database; +pub use self::database::DatabaseImpl; +pub use self::database::UserData; pub use self::durability::Durability; pub use self::event::Event; pub use self::event::EventKind; @@ -50,23 +52,9 @@ pub use salsa_macros::interned; pub use salsa_macros::tracked; pub use salsa_macros::Update; -pub fn default_database() -> impl Database { - use crate as salsa; - - #[crate::db] - #[derive(Default)] - struct DefaultDatabase { - storage: Storage, - } - - #[crate::db] - impl Database for DefaultDatabase {} - - DefaultDatabase::default() -} - pub mod prelude { pub use crate::Accumulator; + pub use crate::Database; pub use crate::Setter; } @@ -82,6 +70,7 @@ pub mod plumbing { pub use crate::cycle::CycleRecoveryStrategy; pub use crate::database::current_revision; pub use crate::database::Database; + pub use crate::database::UserData; pub use crate::function::should_backdate_value; pub use crate::id::AsId; pub use crate::id::FromId; @@ -102,7 +91,6 @@ pub mod plumbing { pub use crate::storage::IngredientIndex; pub use crate::storage::Storage; pub use crate::storage::Zalsa; - pub use crate::storage::ZalsaDatabase; pub use crate::tracked_struct::TrackedStructInDb; pub use crate::update::always_update; pub use crate::update::helper::Dispatch as UpdateDispatch; diff --git a/src/storage.rs b/src/storage.rs index 0ecf132e..f05c22f8 100644 --- a/src/storage.rs +++ b/src/storage.rs @@ -1,10 +1,11 @@ -use std::any::{Any, TypeId}; +use std::any::TypeId; use orx_concurrent_vec::ConcurrentVec; use parking_lot::Mutex; use rustc_hash::FxHashMap; use crate::cycle::CycleRecoveryStrategy; +use crate::database::{DatabaseImpl, UserData}; use crate::ingredient::{Ingredient, Jar}; use crate::nonce::{Nonce, NonceGenerator}; use crate::runtime::Runtime; @@ -15,22 +16,6 @@ pub fn views(db: &Db) -> &Views { db.zalsa().views() } -/// Salsa database methods whose implementation is generated by -/// the `#[salsa::database]` procedural macro. -/// -/// # Safety -/// -/// This trait is meant to be implemented by our procedural macro. -/// We need to document any non-obvious conditions that it satisfies. -pub unsafe trait ZalsaDatabase: Any { - /// Plumbing methods. - #[doc(hidden)] - fn zalsa(&self) -> &dyn Zalsa; - - #[doc(hidden)] - fn zalsa_mut(&mut self) -> &mut dyn Zalsa; -} - /// The "plumbing interface" to the Salsa database. /// /// **NOT SEMVER STABLE.** @@ -87,9 +72,9 @@ pub trait Zalsa { fn report_tracked_write(&mut self, durability: Durability); } -impl Zalsa for Storage { +impl Zalsa for Storage { fn views(&self) -> &Views { - &self.upcasts + &self.views_of } fn nonce(&self) -> Nonce { @@ -227,8 +212,10 @@ impl IngredientIndex { /// The "storage" struct stores all the data for the jars. /// It is shared between the main database and any active snapshots. -pub struct Storage { - upcasts: ViewsOf, +pub struct Storage { + user_data: U, + + views_of: ViewsOf>, nonce: Nonce, @@ -254,19 +241,30 @@ pub struct Storage { } // ANCHOR: default -impl Default for Storage { +impl Default for Storage { fn default() -> Self { + Self::with(Default::default()) + } +} +// ANCHOR_END: default + +impl Storage { + pub(crate) fn with(user_data: U) -> Self { Self { - upcasts: Default::default(), + views_of: Default::default(), nonce: NONCE.nonce(), jar_map: Default::default(), ingredients_vec: Default::default(), ingredients_requiring_reset: Default::default(), runtime: Runtime::default(), + user_data, } } + + pub(crate) fn user_data(&self) -> &U { + &self.user_data + } } -// ANCHOR_END: default /// Caches a pointer to an ingredient in a database. /// Optimized for the case of a single database. diff --git a/tests/accumulate-chain.rs b/tests/accumulate-chain.rs index bf19bc29..b0d79bd4 100644 --- a/tests/accumulate-chain.rs +++ b/tests/accumulate-chain.rs @@ -4,7 +4,7 @@ mod common; use expect_test::expect; -use salsa::{Accumulator, Database}; +use salsa::{Accumulator, Database, DatabaseImpl}; use test_log::test; #[salsa::accumulator] @@ -40,7 +40,7 @@ fn push_d_logs(db: &dyn Database) { #[test] fn accumulate_chain() { - salsa::default_database().attach(|db| { + DatabaseImpl::new().attach(|db| { let logs = push_logs::accumulated::(db); // Check that we get all the logs. expect![[r#" diff --git a/tests/accumulate-custom-clone.rs b/tests/accumulate-custom-clone.rs index deb27791..81612b31 100644 --- a/tests/accumulate-custom-clone.rs +++ b/tests/accumulate-custom-clone.rs @@ -27,7 +27,7 @@ fn push_logs(db: &dyn salsa::Database, input: MyInput) { #[test] fn accumulate_custom_clone() { - salsa::default_database().attach(|db| { + salsa::DatabaseImpl::new().attach(|db| { let input = MyInput::new(db, 2); let logs = push_logs::accumulated::(db, input); expect![[r##" diff --git a/tests/accumulate-custom-debug.rs b/tests/accumulate-custom-debug.rs index 59053803..71a4ba86 100644 --- a/tests/accumulate-custom-debug.rs +++ b/tests/accumulate-custom-debug.rs @@ -27,7 +27,7 @@ fn push_logs(db: &dyn salsa::Database, input: MyInput) { #[test] fn accumulate_custom_debug() { - salsa::default_database().attach(|db| { + salsa::DatabaseImpl::new().attach(|db| { let input = MyInput::new(db, 2); let logs = push_logs::accumulated::(db, input); expect![[r##" diff --git a/tests/accumulate-dag.rs b/tests/accumulate-dag.rs index d0c0cfeb..e23050ba 100644 --- a/tests/accumulate-dag.rs +++ b/tests/accumulate-dag.rs @@ -39,7 +39,7 @@ fn push_b_logs(db: &dyn Database, input: MyInput) { #[test] fn accumulate_a_called_twice() { - salsa::default_database().attach(|db| { + salsa::DatabaseImpl::new().attach(|db| { let input = MyInput::new(db, 2, 3); let logs = push_logs::accumulated::(db, input); // Check that we don't see logs from `a` appearing twice in the input. diff --git a/tests/accumulate-execution-order.rs b/tests/accumulate-execution-order.rs index c1fa0481..edb82e48 100644 --- a/tests/accumulate-execution-order.rs +++ b/tests/accumulate-execution-order.rs @@ -41,7 +41,7 @@ fn push_d_logs(db: &dyn Database) { #[test] fn accumulate_execution_order() { - salsa::default_database().attach(|db| { + salsa::DatabaseImpl::new().attach(|db| { let logs = push_logs::accumulated::(db); // Check that we get logs in execution order expect![[r#" diff --git a/tests/accumulate-from-tracked-fn.rs b/tests/accumulate-from-tracked-fn.rs index 039b1a9b..33d7bd3f 100644 --- a/tests/accumulate-from-tracked-fn.rs +++ b/tests/accumulate-from-tracked-fn.rs @@ -2,16 +2,10 @@ //! Then mutate the values so that the tracked function re-executes. //! Check that we accumulate the appropriate, new values. -mod common; -use common::{HasLogger, Logger}; - use expect_test::expect; use salsa::{Accumulator, Setter}; use test_log::test; -#[salsa::db] -trait Db: salsa::Database + HasLogger {} - #[salsa::input] struct List { value: u32, @@ -23,7 +17,7 @@ struct List { struct Integers(u32); #[salsa::tracked] -fn compute(db: &dyn Db, input: List) { +fn compute(db: &dyn salsa::Database, input: List) { eprintln!( "{:?}(value={:?}, next={:?})", input, @@ -43,30 +37,9 @@ fn compute(db: &dyn Db, input: List) { eprintln!("pushed result {:?}", result); } -#[salsa::db] -#[derive(Default)] -struct Database { - storage: salsa::Storage, - logger: Logger, -} - -#[salsa::db] -impl salsa::Database for Database { - fn salsa_event(&self, _event: &dyn Fn() -> salsa::Event) {} -} - -#[salsa::db] -impl Db for Database {} - -impl HasLogger for Database { - fn logger(&self) -> &Logger { - &self.logger - } -} - #[test] fn test1() { - let mut db = Database::default(); + let mut db = salsa::DatabaseImpl::new(); let l0 = List::new(&db, 1, None); let l1 = List::new(&db, 10, Some(l0)); diff --git a/tests/accumulate-no-duplicates.rs b/tests/accumulate-no-duplicates.rs index 10d47baa..faf8c03a 100644 --- a/tests/accumulate-no-duplicates.rs +++ b/tests/accumulate-no-duplicates.rs @@ -73,7 +73,7 @@ fn push_e_logs(db: &dyn Database) { #[test] fn accumulate_no_duplicates() { - salsa::default_database().attach(|db| { + salsa::DatabaseImpl::new().attach(|db| { let logs = push_logs::accumulated::(db); // Test that there aren't duplicate B logs. // Note that log A appears twice, because they both come diff --git a/tests/accumulate-reuse-workaround.rs b/tests/accumulate-reuse-workaround.rs index 783ca0cc..f43c098e 100644 --- a/tests/accumulate-reuse-workaround.rs +++ b/tests/accumulate-reuse-workaround.rs @@ -3,15 +3,12 @@ //! reuse. mod common; -use common::{HasLogger, Logger}; +use common::{LogDatabase, Logger}; use expect_test::expect; -use salsa::{Accumulator, Setter}; +use salsa::{Accumulator, DatabaseImpl, Setter}; use test_log::test; -#[salsa::db] -trait Db: salsa::Database + HasLogger {} - #[salsa::input] struct List { value: u32, @@ -23,7 +20,7 @@ struct List { struct Integers(u32); #[salsa::tracked] -fn compute(db: &dyn Db, input: List) -> u32 { +fn compute(db: &dyn LogDatabase, input: List) -> u32 { db.push_log(format!("compute({:?})", input,)); // always pushes 0 @@ -42,38 +39,17 @@ fn compute(db: &dyn Db, input: List) -> u32 { } #[salsa::tracked(return_ref)] -fn accumulated(db: &dyn Db, input: List) -> Vec { - db.push_log(format!("accumulated({:?})", input,)); +fn accumulated(db: &dyn LogDatabase, input: List) -> Vec { + db.push_log(format!("accumulated({:?})", input)); compute::accumulated::(db, input) .into_iter() .map(|a| a.0) .collect() } -#[salsa::db] -#[derive(Default)] -struct Database { - storage: salsa::Storage, - logger: Logger, -} - -#[salsa::db] -impl salsa::Database for Database { - fn salsa_event(&self, _event: &dyn Fn() -> salsa::Event) {} -} - -#[salsa::db] -impl Db for Database {} - -impl HasLogger for Database { - fn logger(&self) -> &Logger { - &self.logger - } -} - #[test] fn test1() { - let mut db = Database::default(); + let mut db: DatabaseImpl = DatabaseImpl::default(); let l1 = List::new(&db, 1, None); let l2 = List::new(&db, 2, Some(l1)); diff --git a/tests/accumulate-reuse.rs b/tests/accumulate-reuse.rs index 2075a8e7..e9ac47b3 100644 --- a/tests/accumulate-reuse.rs +++ b/tests/accumulate-reuse.rs @@ -4,15 +4,12 @@ //! are the accumulated values from another query. mod common; -use common::{HasLogger, Logger}; +use common::{LogDatabase, Logger}; use expect_test::expect; -use salsa::prelude::*; +use salsa::{prelude::*, DatabaseImpl}; use test_log::test; -#[salsa::db] -trait Db: salsa::Database + HasLogger {} - #[salsa::input] struct List { value: u32, @@ -23,7 +20,7 @@ struct List { struct Integers(u32); #[salsa::tracked] -fn compute(db: &dyn Db, input: List) -> u32 { +fn compute(db: &dyn LogDatabase, input: List) -> u32 { db.push_log(format!("compute({:?})", input,)); // always pushes 0 @@ -41,30 +38,9 @@ fn compute(db: &dyn Db, input: List) -> u32 { result } -#[salsa::db] -#[derive(Default)] -struct Database { - storage: salsa::Storage, - logger: Logger, -} - -#[salsa::db] -impl salsa::Database for Database { - fn salsa_event(&self, _event: &dyn Fn() -> salsa::Event) {} -} - -#[salsa::db] -impl Db for Database {} - -impl HasLogger for Database { - fn logger(&self) -> &Logger { - &self.logger - } -} - #[test] fn test1() { - let mut db = Database::default(); + let mut db = DatabaseImpl::with(Logger::default()); let l1 = List::new(&db, 1, None); let l2 = List::new(&db, 2, Some(l1)); diff --git a/tests/accumulate.rs b/tests/accumulate.rs index 099128bd..e20cc05f 100644 --- a/tests/accumulate.rs +++ b/tests/accumulate.rs @@ -1,13 +1,10 @@ mod common; -use common::{HasLogger, Logger}; +use common::{LogDatabase, Logger}; use expect_test::expect; use salsa::{Accumulator, Setter}; use test_log::test; -#[salsa::db] -trait Db: salsa::Database + HasLogger {} - #[salsa::input] struct MyInput { field_a: u32, @@ -18,7 +15,7 @@ struct MyInput { struct Log(#[allow(dead_code)] String); #[salsa::tracked] -fn push_logs(db: &dyn Db, input: MyInput) { +fn push_logs(db: &dyn LogDatabase, input: MyInput) { db.push_log(format!( "push_logs(a = {}, b = {})", input.field_a(db), @@ -37,7 +34,7 @@ fn push_logs(db: &dyn Db, input: MyInput) { } #[salsa::tracked] -fn push_a_logs(db: &dyn Db, input: MyInput) { +fn push_a_logs(db: &dyn LogDatabase, input: MyInput) { let field_a = input.field_a(db); db.push_log(format!("push_a_logs({})", field_a)); @@ -47,7 +44,7 @@ fn push_a_logs(db: &dyn Db, input: MyInput) { } #[salsa::tracked] -fn push_b_logs(db: &dyn Db, input: MyInput) { +fn push_b_logs(db: &dyn LogDatabase, input: MyInput) { let field_a = input.field_b(db); db.push_log(format!("push_b_logs({})", field_a)); @@ -56,30 +53,9 @@ fn push_b_logs(db: &dyn Db, input: MyInput) { } } -#[salsa::db] -#[derive(Default)] -struct Database { - storage: salsa::Storage, - logger: Logger, -} - -#[salsa::db] -impl salsa::Database for Database { - fn salsa_event(&self, _event: &dyn Fn() -> salsa::Event) {} -} - -#[salsa::db] -impl Db for Database {} - -impl HasLogger for Database { - fn logger(&self) -> &Logger { - &self.logger - } -} - #[test] fn accumulate_once() { - let mut db = Database::default(); + let mut db = salsa::DatabaseImpl::with(Logger::default()); // Just call accumulate on a base input to see what happens. let input = MyInput::new(&db, 2, 3); @@ -115,7 +91,7 @@ fn accumulate_once() { #[test] fn change_a_from_2_to_0() { - let mut db = Database::default(); + let mut db = salsa::DatabaseImpl::with(Logger::default()); // Accumulate logs for `a = 2` and `b = 3` let input = MyInput::new(&db, 2, 3); @@ -170,7 +146,7 @@ fn change_a_from_2_to_0() { #[test] fn change_a_from_2_to_1() { - let mut db = Database::default(); + let mut db = salsa::DatabaseImpl::with(Logger::default()); // Accumulate logs for `a = 2` and `b = 3` let input = MyInput::new(&db, 2, 3); @@ -229,7 +205,7 @@ fn change_a_from_2_to_1() { #[test] fn get_a_logs_after_changing_b() { - let mut db = Database::default(); + let mut db = salsa::DatabaseImpl::with(Logger::default()); // Invoke `push_a_logs` with `a = 2` and `b = 3` (but `b` doesn't matter) let input = MyInput::new(&db, 2, 3); diff --git a/tests/common/mod.rs b/tests/common/mod.rs index 8e5d51ef..cb741f37 100644 --- a/tests/common/mod.rs +++ b/tests/common/mod.rs @@ -2,16 +2,21 @@ #![allow(dead_code)] +use salsa::{DatabaseImpl, UserData}; + +/// Logging userdata: provides [`LogDatabase`][] trait. +/// +/// If you wish to use it along with other userdata, +/// you can also embed it in another struct and implement [`HasLogger`][] for that struct. #[derive(Default)] pub struct Logger { logs: std::sync::Mutex>, } -/// Trait implemented by databases that lets them log events. -pub trait HasLogger { - /// Return a reference to the logger from the database. - fn logger(&self) -> &Logger; +impl UserData for Logger {} +#[salsa::db] +pub trait LogDatabase: HasLogger + salsa::Database { /// Log an event from inside a tracked function. fn push_log(&self, string: String) { self.logger().logs.lock().unwrap().push(string); @@ -33,3 +38,86 @@ pub trait HasLogger { assert_eq!(logs.len(), expected); } } + +#[salsa::db] +impl LogDatabase for DatabaseImpl {} + +/// Trait implemented by databases that lets them log events. +pub trait HasLogger { + /// Return a reference to the logger from the database. + fn logger(&self) -> &Logger; +} + +impl HasLogger for DatabaseImpl { + fn logger(&self) -> &Logger { + U::logger(self) + } +} + +impl HasLogger for Logger { + fn logger(&self) -> &Logger { + self + } +} + +/// Userdata that provides logging and logs salsa events. +#[derive(Default)] +pub struct EventLogger { + logger: Logger, +} + +impl UserData for EventLogger { + fn salsa_event(db: &DatabaseImpl, event: &dyn Fn() -> salsa::Event) { + db.push_log(format!("{:?}", event())); + } +} + +impl HasLogger for EventLogger { + fn logger(&self) -> &Logger { + &self.logger + } +} + +#[derive(Default)] +pub struct DiscardLogger(Logger); + +impl UserData for DiscardLogger { + fn salsa_event(db: &DatabaseImpl, event: &dyn Fn() -> salsa::Event) { + let event = event(); + match event.kind { + salsa::EventKind::WillDiscardStaleOutput { .. } + | salsa::EventKind::DidDiscard { .. } => { + db.push_log(format!("salsa_event({:?})", event.kind)); + } + _ => {} + } + } +} + +impl HasLogger for DiscardLogger { + fn logger(&self) -> &Logger { + &self.0 + } +} + +#[derive(Default)] +pub struct ExecuteValidateLogger(Logger); + +impl UserData for ExecuteValidateLogger { + fn salsa_event(db: &DatabaseImpl, event: &dyn Fn() -> salsa::Event) { + let event = event(); + match event.kind { + salsa::EventKind::WillExecute { .. } + | salsa::EventKind::DidValidateMemoizedValue { .. } => { + db.push_log(format!("salsa_event({:?})", event.kind)); + } + _ => {} + } + } +} + +impl HasLogger for ExecuteValidateLogger { + fn logger(&self) -> &Logger { + &self.0 + } +} diff --git a/tests/compile-fail/get-set-on-private-input-field.rs b/tests/compile-fail/get-set-on-private-input-field.rs index ae1dd75e..5ecec583 100644 --- a/tests/compile-fail/get-set-on-private-input-field.rs +++ b/tests/compile-fail/get-set-on-private-input-field.rs @@ -8,7 +8,7 @@ mod a { } fn main() { - let mut db = salsa::default_database(); + let mut db = salsa::DatabaseImpl::new(); let input = a::MyInput::new(&mut db, 22); input.field(&db); diff --git a/tests/compile-fail/panic-when-reading-fields-of-tracked-structs-from-older-revisions.rs b/tests/compile-fail/panic-when-reading-fields-of-tracked-structs-from-older-revisions.rs index 0860efc3..3dbb4f2f 100644 --- a/tests/compile-fail/panic-when-reading-fields-of-tracked-structs-from-older-revisions.rs +++ b/tests/compile-fail/panic-when-reading-fields-of-tracked-structs-from-older-revisions.rs @@ -16,7 +16,7 @@ fn tracked_fn<'db>(db: &'db dyn salsa::Database, input: MyInput) -> MyTracked<'d } fn main() { - let mut db = salsa::default_database(); + let mut db = salsa::DatabaseImpl::new(); let input = MyInput::new(&db, 22); let tracked = tracked_fn(&db, input); input.set_field(&mut db).to(24); diff --git a/tests/compile-fail/span-input-setter.rs b/tests/compile-fail/span-input-setter.rs index 1f4a4513..9abf4b6c 100644 --- a/tests/compile-fail/span-input-setter.rs +++ b/tests/compile-fail/span-input-setter.rs @@ -4,7 +4,7 @@ pub struct MyInput { } fn main() { - let mut db = salsa::default_database(); + let mut db = salsa::DatabaseImpl::new(); let input = MyInput::new(&mut db, 22); input.field(&db); input.set_field(22); diff --git a/tests/compile-fail/span-tracked-getter.rs b/tests/compile-fail/span-tracked-getter.rs index d588c140..245fd100 100644 --- a/tests/compile-fail/span-tracked-getter.rs +++ b/tests/compile-fail/span-tracked-getter.rs @@ -10,6 +10,6 @@ fn my_fn(db: &dyn salsa::Database) { } fn main() { - let mut db = salsa::default_database(); + let mut db = salsa::DatabaseImpl::new(); my_fn(&db); } diff --git a/tests/compile-fail/span-tracked-getter.stderr b/tests/compile-fail/span-tracked-getter.stderr index 8ae7219e..fcf546c7 100644 --- a/tests/compile-fail/span-tracked-getter.stderr +++ b/tests/compile-fail/span-tracked-getter.stderr @@ -24,7 +24,7 @@ help: consider borrowing here warning: variable does not need to be mutable --> tests/compile-fail/span-tracked-getter.rs:13:9 | -13 | let mut db = salsa::default_database(); +13 | let mut db = salsa::DatabaseImpl::new(); | ----^^ | | | help: remove this `mut` diff --git a/tests/cycles.rs b/tests/cycles.rs index a37d6f6c..1cc2f06a 100644 --- a/tests/cycles.rs +++ b/tests/cycles.rs @@ -3,6 +3,7 @@ use std::panic::{RefUnwindSafe, UnwindSafe}; use expect_test::expect; +use salsa::DatabaseImpl; use salsa::Durability; // Axes: @@ -59,17 +60,6 @@ struct Error { use salsa::Database as Db; use salsa::Setter; -#[salsa::db] -#[derive(Default)] -struct Database { - storage: salsa::Storage, -} - -#[salsa::db] -impl salsa::Database for Database {} - -impl RefUnwindSafe for Database {} - #[salsa::input] struct MyInput {} @@ -169,7 +159,7 @@ fn extract_cycle(f: impl FnOnce() + UnwindSafe) -> salsa::Cycle { #[test] fn cycle_memoized() { - Database::default().attach(|db| { + salsa::DatabaseImpl::new().attach(|db| { let input = MyInput::new(db); let cycle = extract_cycle(|| memoized_a(db, input)); let expected = expect![[r#" @@ -184,7 +174,7 @@ fn cycle_memoized() { #[test] fn cycle_volatile() { - Database::default().attach(|db| { + salsa::DatabaseImpl::new().attach(|db| { let input = MyInput::new(db); let cycle = extract_cycle(|| volatile_a(db, input)); let expected = expect![[r#" @@ -203,7 +193,7 @@ fn expect_cycle() { // ^ | // +-----+ - Database::default().attach(|db| { + salsa::DatabaseImpl::new().attach(|db| { let abc = ABC::new(db, CycleQuery::B, CycleQuery::A, CycleQuery::None); assert!(cycle_a(db, abc).is_err()); }) @@ -214,7 +204,7 @@ fn inner_cycle() { // A --> B <-- C // ^ | // +-----+ - Database::default().attach(|db| { + salsa::DatabaseImpl::new().attach(|db| { let abc = ABC::new(db, CycleQuery::B, CycleQuery::A, CycleQuery::B); let err = cycle_c(db, abc); assert!(err.is_err()); @@ -233,7 +223,7 @@ fn cycle_revalidate() { // A --> B // ^ | // +-----+ - let mut db = Database::default(); + let mut db = salsa::DatabaseImpl::new(); let abc = ABC::new(&db, CycleQuery::B, CycleQuery::A, CycleQuery::None); assert!(cycle_a(&db, abc).is_err()); abc.set_b(&mut db).to(CycleQuery::A); // same value as default @@ -245,7 +235,7 @@ fn cycle_recovery_unchanged_twice() { // A --> B // ^ | // +-----+ - let mut db = Database::default(); + let mut db = salsa::DatabaseImpl::new(); let abc = ABC::new(&db, CycleQuery::B, CycleQuery::A, CycleQuery::None); assert!(cycle_a(&db, abc).is_err()); @@ -255,8 +245,7 @@ fn cycle_recovery_unchanged_twice() { #[test] fn cycle_appears() { - let mut db = Database::default(); - + let mut db = salsa::DatabaseImpl::new(); // A --> B let abc = ABC::new(&db, CycleQuery::B, CycleQuery::None, CycleQuery::None); assert!(cycle_a(&db, abc).is_ok()); @@ -270,7 +259,7 @@ fn cycle_appears() { #[test] fn cycle_disappears() { - let mut db = Database::default(); + let mut db = salsa::DatabaseImpl::new(); // A --> B // ^ | @@ -289,7 +278,7 @@ fn cycle_disappears() { /// the fact that the cycle will no longer occur. #[test] fn cycle_disappears_durability() { - let mut db = Database::default(); + let mut db = salsa::DatabaseImpl::new(); let abc = ABC::new( &mut db, CycleQuery::None, @@ -320,7 +309,7 @@ fn cycle_disappears_durability() { #[test] fn cycle_mixed_1() { - Database::default().attach(|db| { + salsa::DatabaseImpl::new().attach(|db| { // A --> B <-- C // | ^ // +-----+ @@ -338,7 +327,7 @@ fn cycle_mixed_1() { #[test] fn cycle_mixed_2() { - Database::default().attach(|db| { + salsa::DatabaseImpl::new().attach(|db| { // Configuration: // // A --> B --> C @@ -360,7 +349,7 @@ fn cycle_mixed_2() { fn cycle_deterministic_order() { // No matter whether we start from A or B, we get the same set of participants: let f = || { - let mut db = Database::default(); + let mut db = salsa::DatabaseImpl::new(); // A --> B // ^ | @@ -390,7 +379,7 @@ fn cycle_deterministic_order() { #[test] fn cycle_multiple() { // No matter whether we start from A or B, we get the same set of participants: - let mut db = Database::default(); + let mut db = salsa::DatabaseImpl::new(); // Configuration: // @@ -432,7 +421,7 @@ fn cycle_multiple() { #[test] fn cycle_recovery_set_but_not_participating() { - Database::default().attach(|db| { + salsa::DatabaseImpl::new().attach(|db| { // A --> C -+ // ^ | // +--+ diff --git a/tests/debug.rs b/tests/debug.rs index f1bde114..194c6511 100644 --- a/tests/debug.rs +++ b/tests/debug.rs @@ -1,7 +1,7 @@ //! Test that `DeriveWithDb` is correctly derived. use expect_test::expect; -use salsa::{Database as _, Setter}; +use salsa::{Database, Setter}; #[salsa::input] struct MyInput { @@ -19,18 +19,9 @@ struct ComplexStruct { not_salsa: NotSalsa, } -#[salsa::db] -#[derive(Default)] -struct Database { - storage: salsa::Storage, -} - -#[salsa::db] -impl salsa::Database for Database {} - #[test] fn input() { - Database::default().attach(|db| { + salsa::DatabaseImpl::new().attach(|db| { let input = MyInput::new(db, 22); let not_salsa = NotSalsa { field: "it's salsa time".to_string(), @@ -54,7 +45,7 @@ fn leak_debug_string(_db: &dyn salsa::Database, input: MyInput) -> String { /// Don't try this at home, kids. #[test] fn untracked_dependencies() { - let mut db = Database::default(); + let mut db = salsa::DatabaseImpl::new(); let input = MyInput::new(&db, 22); @@ -95,7 +86,7 @@ fn leak_derived_custom(db: &dyn salsa::Database, input: MyInput, value: u32) -> #[test] fn custom_debug_impl() { - let db = Database::default(); + let db = salsa::DatabaseImpl::new(); let input = MyInput::new(&db, 22); diff --git a/tests/deletion-cascade.rs b/tests/deletion-cascade.rs index 8385d048..023e584b 100644 --- a/tests/deletion-cascade.rs +++ b/tests/deletion-cascade.rs @@ -3,22 +3,19 @@ //! * when we delete memoized data, also delete outputs from that data mod common; -use common::{HasLogger, Logger}; +use common::{DiscardLogger, LogDatabase}; use expect_test::expect; -use salsa::Setter; +use salsa::{DatabaseImpl, Setter}; use test_log::test; -#[salsa::db] -trait Db: salsa::Database + HasLogger {} - #[salsa::input(singleton)] struct MyInput { field: u32, } #[salsa::tracked] -fn final_result(db: &dyn Db, input: MyInput) -> u32 { +fn final_result(db: &dyn LogDatabase, input: MyInput) -> u32 { db.push_log(format!("final_result({:?})", input)); let mut sum = 0; for tracked_struct in create_tracked_structs(db, input) { @@ -33,7 +30,7 @@ struct MyTracked<'db> { } #[salsa::tracked] -fn create_tracked_structs(db: &dyn Db, input: MyInput) -> Vec> { +fn create_tracked_structs(db: &dyn LogDatabase, input: MyInput) -> Vec> { db.push_log(format!("intermediate_result({:?})", input)); (0..input.field(db)) .map(|i| MyTracked::new(db, i)) @@ -41,49 +38,19 @@ fn create_tracked_structs(db: &dyn Db, input: MyInput) -> Vec> { } #[salsa::tracked] -fn contribution_from_struct<'db>(db: &'db dyn Db, tracked: MyTracked<'db>) -> u32 { +fn contribution_from_struct<'db>(db: &'db dyn LogDatabase, tracked: MyTracked<'db>) -> u32 { let m = MyTracked::new(db, tracked.field(db)); copy_field(db, m) * 2 } #[salsa::tracked] -fn copy_field<'db>(db: &'db dyn Db, tracked: MyTracked<'db>) -> u32 { +fn copy_field<'db>(db: &'db dyn LogDatabase, tracked: MyTracked<'db>) -> u32 { tracked.field(db) } -#[salsa::db] -#[derive(Default)] -struct Database { - storage: salsa::Storage, - logger: Logger, -} - -#[salsa::db] -impl salsa::Database for Database { - fn salsa_event(&self, event: &dyn Fn() -> salsa::Event) { - let event = event(); - match event.kind { - salsa::EventKind::WillDiscardStaleOutput { .. } - | salsa::EventKind::DidDiscard { .. } => { - self.push_log(format!("salsa_event({:?})", event.kind)); - } - _ => {} - } - } -} - -#[salsa::db] -impl Db for Database {} - -impl HasLogger for Database { - fn logger(&self) -> &Logger { - &self.logger - } -} - #[test] fn basic() { - let mut db = Database::default(); + let mut db: DatabaseImpl = Default::default(); // Creates 3 tracked structs let input = MyInput::new(&db, 3); diff --git a/tests/deletion-drops.rs b/tests/deletion-drops.rs index 989f934f..b03ceda7 100644 --- a/tests/deletion-drops.rs +++ b/tests/deletion-drops.rs @@ -56,7 +56,7 @@ impl MyInput { #[test] fn deletion_drops() { - let mut db = salsa::default_database(); + let mut db = salsa::DatabaseImpl::new(); let input = MyInput::new(&db, 22); diff --git a/tests/deletion.rs b/tests/deletion.rs index cdcc14bf..74b69547 100644 --- a/tests/deletion.rs +++ b/tests/deletion.rs @@ -3,22 +3,19 @@ //! * entities not created in a revision are deleted, as is any memoized data keyed on them. mod common; -use common::{HasLogger, Logger}; +use common::LogDatabase; use expect_test::expect; use salsa::Setter; use test_log::test; -#[salsa::db] -trait Db: salsa::Database + HasLogger {} - #[salsa::input] struct MyInput { field: u32, } #[salsa::tracked] -fn final_result(db: &dyn Db, input: MyInput) -> u32 { +fn final_result(db: &dyn LogDatabase, input: MyInput) -> u32 { db.push_log(format!("final_result({:?})", input)); let mut sum = 0; for tracked_struct in create_tracked_structs(db, input) { @@ -33,7 +30,7 @@ struct MyTracked<'db> { } #[salsa::tracked] -fn create_tracked_structs(db: &dyn Db, input: MyInput) -> Vec> { +fn create_tracked_structs(db: &dyn LogDatabase, input: MyInput) -> Vec> { db.push_log(format!("intermediate_result({:?})", input)); (0..input.field(db)) .map(|i| MyTracked::new(db, i)) @@ -41,43 +38,13 @@ fn create_tracked_structs(db: &dyn Db, input: MyInput) -> Vec> { } #[salsa::tracked] -fn contribution_from_struct<'db>(db: &'db dyn Db, tracked: MyTracked<'db>) -> u32 { +fn contribution_from_struct<'db>(db: &'db dyn LogDatabase, tracked: MyTracked<'db>) -> u32 { tracked.field(db) * 2 } -#[salsa::db] -#[derive(Default)] -struct Database { - storage: salsa::Storage, - logger: Logger, -} - -#[salsa::db] -impl salsa::Database for Database { - fn salsa_event(&self, event: &dyn Fn() -> salsa::Event) { - let event = event(); - match event.kind { - salsa::EventKind::WillDiscardStaleOutput { .. } - | salsa::EventKind::DidDiscard { .. } => { - self.push_log(format!("salsa_event({:?})", event.kind)); - } - _ => {} - } - } -} - -#[salsa::db] -impl Db for Database {} - -impl HasLogger for Database { - fn logger(&self) -> &Logger { - &self.logger - } -} - #[test] fn basic() { - let mut db = Database::default(); + let mut db: salsa::DatabaseImpl = Default::default(); // Creates 3 tracked structs let input = MyInput::new(&db, 3); diff --git a/tests/elided-lifetime-in-tracked-fn.rs b/tests/elided-lifetime-in-tracked-fn.rs index bd0e2184..07090d60 100644 --- a/tests/elided-lifetime-in-tracked-fn.rs +++ b/tests/elided-lifetime-in-tracked-fn.rs @@ -2,22 +2,19 @@ //! compiles and executes successfully. mod common; -use common::{HasLogger, Logger}; +use common::{LogDatabase, Logger}; use expect_test::expect; -use salsa::Setter; +use salsa::{DatabaseImpl, Setter}; use test_log::test; -#[salsa::db] -trait Db: salsa::Database + HasLogger {} - #[salsa::input] struct MyInput { field: u32, } #[salsa::tracked] -fn final_result(db: &dyn Db, input: MyInput) -> u32 { +fn final_result(db: &dyn LogDatabase, input: MyInput) -> u32 { db.push_log(format!("final_result({:?})", input)); intermediate_result(db, input).field(db) * 2 } @@ -28,33 +25,14 @@ struct MyTracked<'db> { } #[salsa::tracked] -fn intermediate_result(db: &dyn Db, input: MyInput) -> MyTracked<'_> { +fn intermediate_result(db: &dyn LogDatabase, input: MyInput) -> MyTracked<'_> { db.push_log(format!("intermediate_result({:?})", input)); MyTracked::new(db, input.field(db) / 2) } -#[salsa::db] -#[derive(Default)] -struct Database { - storage: salsa::Storage, - logger: Logger, -} - -#[salsa::db] -impl salsa::Database for Database {} - -#[salsa::db] -impl Db for Database {} - -impl HasLogger for Database { - fn logger(&self) -> &Logger { - &self.logger - } -} - #[test] fn execute() { - let mut db = Database::default(); + let mut db: DatabaseImpl = Default::default(); let input = MyInput::new(&db, 22); assert_eq!(final_result(&db, input), 22); diff --git a/tests/expect_reuse_field_x_of_a_tracked_struct_changes_but_fn_depends_on_field_y.rs b/tests/expect_reuse_field_x_of_a_tracked_struct_changes_but_fn_depends_on_field_y.rs index d9fb6d52..5c110c21 100644 --- a/tests/expect_reuse_field_x_of_a_tracked_struct_changes_but_fn_depends_on_field_y.rs +++ b/tests/expect_reuse_field_x_of_a_tracked_struct_changes_but_fn_depends_on_field_y.rs @@ -4,13 +4,10 @@ #![allow(dead_code)] mod common; -use common::{HasLogger, Logger}; +use common::{LogDatabase, Logger}; use expect_test::expect; -use salsa::Setter; - -#[salsa::db] -trait Db: salsa::Database + HasLogger {} +use salsa::{DatabaseImpl, Setter}; #[salsa::input] struct MyInput { @@ -18,13 +15,13 @@ struct MyInput { } #[salsa::tracked] -fn final_result_depends_on_x(db: &dyn Db, input: MyInput) -> u32 { +fn final_result_depends_on_x(db: &dyn LogDatabase, input: MyInput) -> u32 { db.push_log(format!("final_result_depends_on_x({:?})", input)); intermediate_result(db, input).x(db) * 2 } #[salsa::tracked] -fn final_result_depends_on_y(db: &dyn Db, input: MyInput) -> u32 { +fn final_result_depends_on_y(db: &dyn LogDatabase, input: MyInput) -> u32 { db.push_log(format!("final_result_depends_on_y({:?})", input)); intermediate_result(db, input).y(db) * 2 } @@ -36,36 +33,17 @@ struct MyTracked<'db> { } #[salsa::tracked] -fn intermediate_result(db: &dyn Db, input: MyInput) -> MyTracked<'_> { +fn intermediate_result(db: &dyn LogDatabase, input: MyInput) -> MyTracked<'_> { MyTracked::new(db, (input.field(db) + 1) / 2, input.field(db) / 2) } -#[salsa::db] -#[derive(Default)] -struct Database { - storage: salsa::Storage, - logger: Logger, -} - -#[salsa::db] -impl salsa::Database for Database {} - -#[salsa::db] -impl Db for Database {} - -impl HasLogger for Database { - fn logger(&self) -> &Logger { - &self.logger - } -} - #[test] fn execute() { // x = (input.field + 1) / 2 // y = input.field / 2 // final_result_depends_on_x = x * 2 = (input.field + 1) / 2 * 2 // final_result_depends_on_y = y * 2 = input.field / 2 * 2 - let mut db = Database::default(); + let mut db: DatabaseImpl = Default::default(); // intermediate results: // x = (22 + 1) / 2 = 11 diff --git a/tests/expect_reuse_field_x_of_an_input_changes_but_fn_depends_on_field_y.rs b/tests/expect_reuse_field_x_of_an_input_changes_but_fn_depends_on_field_y.rs index c1c2df18..12f2cfbf 100644 --- a/tests/expect_reuse_field_x_of_an_input_changes_but_fn_depends_on_field_y.rs +++ b/tests/expect_reuse_field_x_of_an_input_changes_but_fn_depends_on_field_y.rs @@ -4,14 +4,11 @@ #![allow(dead_code)] mod common; -use common::{HasLogger, Logger}; +use common::{LogDatabase, Logger}; use expect_test::expect; use salsa::Setter; -#[salsa::db] -trait Db: salsa::Database + HasLogger {} - #[salsa::input] struct MyInput { x: u32, @@ -19,41 +16,21 @@ struct MyInput { } #[salsa::tracked] -fn result_depends_on_x(db: &dyn Db, input: MyInput) -> u32 { +fn result_depends_on_x(db: &dyn LogDatabase, input: MyInput) -> u32 { db.push_log(format!("result_depends_on_x({:?})", input)); input.x(db) + 1 } #[salsa::tracked] -fn result_depends_on_y(db: &dyn Db, input: MyInput) -> u32 { +fn result_depends_on_y(db: &dyn LogDatabase, input: MyInput) -> u32 { db.push_log(format!("result_depends_on_y({:?})", input)); input.y(db) - 1 } - -#[salsa::db] -#[derive(Default)] -struct Database { - storage: salsa::Storage, - logger: Logger, -} - -#[salsa::db] -impl salsa::Database for Database {} - -#[salsa::db] -impl Db for Database {} - -impl HasLogger for Database { - fn logger(&self) -> &Logger { - &self.logger - } -} - #[test] fn execute() { // result_depends_on_x = x + 1 // result_depends_on_y = y - 1 - let mut db = Database::default(); + let mut db: salsa::DatabaseImpl = Default::default(); let input = MyInput::new(&db, 22, 33); assert_eq!(result_depends_on_x(&db, input), 23); diff --git a/tests/hello_world.rs b/tests/hello_world.rs index 63e3d5ce..3a316d1e 100644 --- a/tests/hello_world.rs +++ b/tests/hello_world.rs @@ -2,22 +2,19 @@ //! compiles and executes successfully. mod common; -use common::{HasLogger, Logger}; +use common::{LogDatabase, Logger}; use expect_test::expect; use salsa::Setter; use test_log::test; -#[salsa::db] -trait Db: salsa::Database + HasLogger {} - #[salsa::input] struct MyInput { field: u32, } #[salsa::tracked] -fn final_result(db: &dyn Db, input: MyInput) -> u32 { +fn final_result(db: &dyn LogDatabase, input: MyInput) -> u32 { db.push_log(format!("final_result({:?})", input)); intermediate_result(db, input).field(db) * 2 } @@ -28,33 +25,14 @@ struct MyTracked<'db> { } #[salsa::tracked] -fn intermediate_result(db: &dyn Db, input: MyInput) -> MyTracked<'_> { +fn intermediate_result(db: &dyn LogDatabase, input: MyInput) -> MyTracked<'_> { db.push_log(format!("intermediate_result({:?})", input)); MyTracked::new(db, input.field(db) / 2) } -#[salsa::db] -#[derive(Default)] -struct Database { - storage: salsa::Storage, - logger: Logger, -} - -#[salsa::db] -impl salsa::Database for Database {} - -#[salsa::db] -impl Db for Database {} - -impl HasLogger for Database { - fn logger(&self) -> &Logger { - &self.logger - } -} - #[test] fn execute() { - let mut db = Database::default(); + let mut db: salsa::DatabaseImpl = Default::default(); let input = MyInput::new(&db, 22); assert_eq!(final_result(&db, input), 22); @@ -85,7 +63,7 @@ fn execute() { /// Create and mutate a distinct input. No re-execution required. #[test] fn red_herring() { - let mut db = Database::default(); + let mut db: salsa::DatabaseImpl = Default::default(); let input = MyInput::new(&db, 22); assert_eq!(final_result(&db, input), 22); diff --git a/tests/interned-struct-with-lifetime.rs b/tests/interned-struct-with-lifetime.rs index aa06678a..a74d2c42 100644 --- a/tests/interned-struct-with-lifetime.rs +++ b/tests/interned-struct-with-lifetime.rs @@ -1,14 +1,9 @@ //! Test that a `tracked` fn on a `salsa::input` //! compiles and executes successfully. -mod common; -use common::{HasLogger, Logger}; use expect_test::expect; use test_log::test; -#[salsa::db] -trait Db: salsa::Database + HasLogger {} - #[salsa::interned] struct InternedString<'db> { data: String, @@ -20,38 +15,17 @@ struct InternedPair<'db> { } #[salsa::tracked] -fn intern_stuff(db: &dyn Db) -> String { +fn intern_stuff(db: &dyn salsa::Database) -> String { let s1 = InternedString::new(db, "Hello, ".to_string()); let s2 = InternedString::new(db, "World, ".to_string()); let s3 = InternedPair::new(db, (s1, s2)); format!("{s3:?}") } -#[salsa::db] -#[derive(Default)] -struct Database { - storage: salsa::Storage, - logger: Logger, -} - -#[salsa::db] -impl salsa::Database for Database {} - -#[salsa::db] -impl Db for Database {} - -impl HasLogger for Database { - fn logger(&self) -> &Logger { - &self.logger - } -} - #[test] fn execute() { - let mut db = Database::default(); - + let db = salsa::DatabaseImpl::new(); expect![[r#" "InternedPair { data: (InternedString { data: \"Hello, \" }, InternedString { data: \"World, \" }) }" "#]].assert_debug_eq(&intern_stuff(&db)); - db.assert_logs(expect!["[]"]); } diff --git a/tests/is_send_sync.rs b/tests/is_send_sync.rs index 9fa994bf..6ada1bac 100644 --- a/tests/is_send_sync.rs +++ b/tests/is_send_sync.rs @@ -1,23 +1,9 @@ //! Test that a setting a field on a `#[salsa::input]` //! overwrites and returns the old value. +use salsa::Database; use test_log::test; -#[salsa::db] -trait Db: salsa::Database {} - -#[salsa::db] -#[derive(Default)] -struct Database { - storage: salsa::Storage, -} - -#[salsa::db] -impl salsa::Database for Database {} - -#[salsa::db] -impl Db for Database {} - #[salsa::input] struct MyInput { field: String, @@ -34,7 +20,7 @@ struct MyInterned<'db> { } #[salsa::tracked] -fn test(db: &dyn crate::Db, input: MyInput) { +fn test(db: &dyn Database, input: MyInput) { let input = is_send_sync(input); let interned = is_send_sync(MyInterned::new(db, input.field(db).clone())); let _tracked_struct = is_send_sync(MyTracked::new(db, interned)); @@ -46,7 +32,7 @@ fn is_send_sync(t: T) -> T { #[test] fn execute() { - let db = Database::default(); + let db = salsa::DatabaseImpl::new(); let input = MyInput::new(&db, "Hello".to_string()); test(&db, input); } diff --git a/tests/lru.rs b/tests/lru.rs index f45539b0..2d5b1b5d 100644 --- a/tests/lru.rs +++ b/tests/lru.rs @@ -6,14 +6,11 @@ use std::sync::{ Arc, }; -use salsa::Database as _; mod common; -use common::{HasLogger, Logger}; +use common::{LogDatabase, Logger}; +use salsa::Database as _; use test_log::test; -#[salsa::db] -trait Db: salsa::Database + HasLogger {} - #[derive(Debug, PartialEq, Eq)] struct HotPotato(u32); @@ -40,50 +37,31 @@ struct MyInput { } #[salsa::tracked(lru = 32)] -fn get_hot_potato(db: &dyn Db, input: MyInput) -> Arc { +fn get_hot_potato(db: &dyn LogDatabase, input: MyInput) -> Arc { db.push_log(format!("get_hot_potato({:?})", input.field(db))); Arc::new(HotPotato::new(input.field(db))) } #[salsa::tracked] -fn get_hot_potato2(db: &dyn Db, input: MyInput) -> u32 { +fn get_hot_potato2(db: &dyn LogDatabase, input: MyInput) -> u32 { db.push_log(format!("get_hot_potato2({:?})", input.field(db))); get_hot_potato(db, input).0 } #[salsa::tracked(lru = 32)] -fn get_volatile(db: &dyn Db, _input: MyInput) -> usize { +fn get_volatile(db: &dyn LogDatabase, _input: MyInput) -> usize { static COUNTER: AtomicUsize = AtomicUsize::new(0); db.report_untracked_read(); COUNTER.fetch_add(1, Ordering::SeqCst) } -#[salsa::db] -#[derive(Default)] -struct DatabaseImpl { - storage: salsa::Storage, - logger: Logger, -} - -#[salsa::db] -impl salsa::Database for DatabaseImpl {} - -#[salsa::db] -impl Db for DatabaseImpl {} - -impl HasLogger for DatabaseImpl { - fn logger(&self) -> &Logger { - &self.logger - } -} - fn load_n_potatoes() -> usize { N_POTATOES.with(|n| n.load(Ordering::SeqCst)) } #[test] fn lru_works() { - let db = DatabaseImpl::default(); + let db: salsa::DatabaseImpl = Default::default(); assert_eq!(load_n_potatoes(), 0); for i in 0..128u32 { @@ -99,7 +77,7 @@ fn lru_works() { #[test] fn lru_doesnt_break_volatile_queries() { - let db = DatabaseImpl::default(); + let db: salsa::DatabaseImpl = Default::default(); // Create all inputs first, so that there are no revision changes among calls to `get_volatile` let inputs: Vec = (0..128usize).map(|i| MyInput::new(&db, i as u32)).collect(); @@ -117,7 +95,7 @@ fn lru_doesnt_break_volatile_queries() { #[test] fn lru_can_be_changed_at_runtime() { - let db = DatabaseImpl::default(); + let db: salsa::DatabaseImpl = Default::default(); assert_eq!(load_n_potatoes(), 0); let inputs: Vec<(u32, MyInput)> = (0..128).map(|i| (i, MyInput::new(&db, i))).collect(); @@ -160,7 +138,7 @@ fn lru_can_be_changed_at_runtime() { #[test] fn lru_keeps_dependency_info() { - let mut db = DatabaseImpl::default(); + let mut db: salsa::DatabaseImpl = Default::default(); let capacity = 32; // Invoke `get_hot_potato2` 33 times. This will (in turn) invoke diff --git a/tests/mutate_in_place.rs b/tests/mutate_in_place.rs index d8fa88b0..047373ee 100644 --- a/tests/mutate_in_place.rs +++ b/tests/mutate_in_place.rs @@ -1,9 +1,6 @@ //! Test that a setting a field on a `#[salsa::input]` //! overwrites and returns the old value. -mod common; -use common::{HasLogger, Logger}; - use salsa::Setter; use test_log::test; @@ -12,25 +9,9 @@ struct MyInput { field: String, } -#[salsa::db] -#[derive(Default)] -struct Database { - storage: salsa::Storage, - logger: Logger, -} - -#[salsa::db] -impl salsa::Database for Database {} - -impl HasLogger for Database { - fn logger(&self) -> &Logger { - &self.logger - } -} - #[test] fn execute() { - let mut db = Database::default(); + let mut db = salsa::DatabaseImpl::new(); let input = MyInput::new(&db, "Hello".to_string()); diff --git a/tests/override_new_get_set.rs b/tests/override_new_get_set.rs index a5604962..9f3a8752 100644 --- a/tests/override_new_get_set.rs +++ b/tests/override_new_get_set.rs @@ -66,17 +66,5 @@ impl<'db> MyTracked<'db> { #[test] fn execute() { - #[salsa::db] - #[derive(Default)] - struct Database { - storage: salsa::Storage, - } - - #[salsa::db] - impl salsa::Database for Database {} - - #[salsa::db] - impl Db for Database {} - - let mut db = Database::default(); + salsa::DatabaseImpl::new(); } diff --git a/tests/panic-when-creating-tracked-struct-outside-of-tracked-fn.rs b/tests/panic-when-creating-tracked-struct-outside-of-tracked-fn.rs index d59741aa..32b444c7 100644 --- a/tests/panic-when-creating-tracked-struct-outside-of-tracked-fn.rs +++ b/tests/panic-when-creating-tracked-struct-outside-of-tracked-fn.rs @@ -6,20 +6,11 @@ struct MyTracked<'db> { field: u32, } -#[salsa::db] -#[derive(Default)] -struct Database { - storage: salsa::Storage, -} - -#[salsa::db] -impl salsa::Database for Database {} - #[test] #[should_panic( expected = "cannot create a tracked struct disambiguator outside of a tracked function" )] fn execute() { - let db = Database::default(); + let db = salsa::DatabaseImpl::new(); MyTracked::new(&db, 0); } diff --git a/tests/parallel/parallel_cancellation.rs b/tests/parallel/parallel_cancellation.rs index 715f8a72..0e35ab25 100644 --- a/tests/parallel/parallel_cancellation.rs +++ b/tests/parallel/parallel_cancellation.rs @@ -3,17 +3,12 @@ //! both intra and cross thread. use salsa::Cancelled; +use salsa::DatabaseImpl; use salsa::Handle; use salsa::Setter; -use crate::setup::Database; use crate::setup::Knobs; - -#[salsa::db] -pub(crate) trait Db: salsa::Database + Knobs {} - -#[salsa::db] -impl Db for T {} +use crate::setup::KnobsDatabase; #[salsa::input] struct MyInput { @@ -21,14 +16,14 @@ struct MyInput { } #[salsa::tracked] -fn a1(db: &dyn Db, input: MyInput) -> MyInput { +fn a1(db: &dyn KnobsDatabase, input: MyInput) -> MyInput { db.signal(1); db.wait_for(2); dummy(db, input) } #[salsa::tracked] -fn dummy(_db: &dyn Db, _input: MyInput) -> MyInput { +fn dummy(_db: &dyn KnobsDatabase, _input: MyInput) -> MyInput { panic!("should never get here!") } @@ -49,7 +44,7 @@ fn dummy(_db: &dyn Db, _input: MyInput) -> MyInput { #[test] fn execute() { - let mut db = Handle::new(Database::default()); + let mut db = Handle::new(>::default()); db.knobs().signal_on_will_block.store(3); let input = MyInput::new(&*db, 1); diff --git a/tests/parallel/parallel_cycle_all_recover.rs b/tests/parallel/parallel_cycle_all_recover.rs index 32dbbf6f..7706d6ec 100644 --- a/tests/parallel/parallel_cycle_all_recover.rs +++ b/tests/parallel/parallel_cycle_all_recover.rs @@ -2,16 +2,11 @@ //! See `../cycles.rs` for a complete listing of cycle tests, //! both intra and cross thread. +use salsa::DatabaseImpl; use salsa::Handle; -use crate::setup::Database; use crate::setup::Knobs; - -#[salsa::db] -pub(crate) trait Db: salsa::Database + Knobs {} - -#[salsa::db] -impl Db for T {} +use crate::setup::KnobsDatabase; #[salsa::input] pub(crate) struct MyInput { @@ -19,7 +14,7 @@ pub(crate) struct MyInput { } #[salsa::tracked(recovery_fn = recover_a1)] -pub(crate) fn a1(db: &dyn Db, input: MyInput) -> i32 { +pub(crate) fn a1(db: &dyn KnobsDatabase, input: MyInput) -> i32 { // Wait to create the cycle until both threads have entered db.signal(1); db.wait_for(2); @@ -27,23 +22,23 @@ pub(crate) fn a1(db: &dyn Db, input: MyInput) -> i32 { a2(db, input) } -fn recover_a1(db: &dyn Db, _cycle: &salsa::Cycle, key: MyInput) -> i32 { +fn recover_a1(db: &dyn KnobsDatabase, _cycle: &salsa::Cycle, key: MyInput) -> i32 { dbg!("recover_a1"); key.field(db) * 10 + 1 } #[salsa::tracked(recovery_fn=recover_a2)] -pub(crate) fn a2(db: &dyn Db, input: MyInput) -> i32 { +pub(crate) fn a2(db: &dyn KnobsDatabase, input: MyInput) -> i32 { b1(db, input) } -fn recover_a2(db: &dyn Db, _cycle: &salsa::Cycle, key: MyInput) -> i32 { +fn recover_a2(db: &dyn KnobsDatabase, _cycle: &salsa::Cycle, key: MyInput) -> i32 { dbg!("recover_a2"); key.field(db) * 10 + 2 } #[salsa::tracked(recovery_fn=recover_b1)] -pub(crate) fn b1(db: &dyn Db, input: MyInput) -> i32 { +pub(crate) fn b1(db: &dyn KnobsDatabase, input: MyInput) -> i32 { // Wait to create the cycle until both threads have entered db.wait_for(1); db.signal(2); @@ -53,17 +48,17 @@ pub(crate) fn b1(db: &dyn Db, input: MyInput) -> i32 { b2(db, input) } -fn recover_b1(db: &dyn Db, _cycle: &salsa::Cycle, key: MyInput) -> i32 { +fn recover_b1(db: &dyn KnobsDatabase, _cycle: &salsa::Cycle, key: MyInput) -> i32 { dbg!("recover_b1"); key.field(db) * 20 + 1 } #[salsa::tracked(recovery_fn=recover_b2)] -pub(crate) fn b2(db: &dyn Db, input: MyInput) -> i32 { +pub(crate) fn b2(db: &dyn KnobsDatabase, input: MyInput) -> i32 { a1(db, input) } -fn recover_b2(db: &dyn Db, _cycle: &salsa::Cycle, key: MyInput) -> i32 { +fn recover_b2(db: &dyn KnobsDatabase, _cycle: &salsa::Cycle, key: MyInput) -> i32 { dbg!("recover_b2"); key.field(db) * 20 + 2 } @@ -92,7 +87,7 @@ fn recover_b2(db: &dyn Db, _cycle: &salsa::Cycle, key: MyInput) -> i32 { #[test] fn execute() { - let db = Handle::new(Database::default()); + let db = Handle::new(>::default()); db.knobs().signal_on_will_block.store(3); let input = MyInput::new(&*db, 1); diff --git a/tests/parallel/parallel_cycle_mid_recover.rs b/tests/parallel/parallel_cycle_mid_recover.rs index 867a6be7..0c5e3475 100644 --- a/tests/parallel/parallel_cycle_mid_recover.rs +++ b/tests/parallel/parallel_cycle_mid_recover.rs @@ -2,16 +2,9 @@ //! See `../cycles.rs` for a complete listing of cycle tests, //! both intra and cross thread. -use salsa::Handle; +use salsa::{DatabaseImpl, Handle}; -use crate::setup::Database; -use crate::setup::Knobs; - -#[salsa::db] -pub(crate) trait Db: salsa::Database + Knobs {} - -#[salsa::db] -impl Db for T {} +use crate::setup::{Knobs, KnobsDatabase}; #[salsa::input] pub(crate) struct MyInput { @@ -19,7 +12,7 @@ pub(crate) struct MyInput { } #[salsa::tracked] -pub(crate) fn a1(db: &dyn Db, input: MyInput) -> i32 { +pub(crate) fn a1(db: &dyn KnobsDatabase, input: MyInput) -> i32 { // tell thread b we have started db.signal(1); @@ -30,25 +23,25 @@ pub(crate) fn a1(db: &dyn Db, input: MyInput) -> i32 { } #[salsa::tracked] -pub(crate) fn a2(db: &dyn Db, input: MyInput) -> i32 { +pub(crate) fn a2(db: &dyn KnobsDatabase, input: MyInput) -> i32 { // create the cycle b1(db, input) } #[salsa::tracked(recovery_fn=recover_b1)] -pub(crate) fn b1(db: &dyn Db, input: MyInput) -> i32 { +pub(crate) fn b1(db: &dyn KnobsDatabase, input: MyInput) -> i32 { // wait for thread a to have started db.wait_for(1); b2(db, input) } -fn recover_b1(db: &dyn Db, _cycle: &salsa::Cycle, key: MyInput) -> i32 { +fn recover_b1(db: &dyn KnobsDatabase, _cycle: &salsa::Cycle, key: MyInput) -> i32 { dbg!("recover_b1"); key.field(db) * 20 + 2 } #[salsa::tracked] -pub(crate) fn b2(db: &dyn Db, input: MyInput) -> i32 { +pub(crate) fn b2(db: &dyn KnobsDatabase, input: MyInput) -> i32 { // will encounter a cycle but recover b3(db, input); b1(db, input); // hasn't recovered yet @@ -56,12 +49,12 @@ pub(crate) fn b2(db: &dyn Db, input: MyInput) -> i32 { } #[salsa::tracked(recovery_fn=recover_b3)] -pub(crate) fn b3(db: &dyn Db, input: MyInput) -> i32 { +pub(crate) fn b3(db: &dyn KnobsDatabase, input: MyInput) -> i32 { // will block on thread a, signaling stage 2 a1(db, input) } -fn recover_b3(db: &dyn Db, _cycle: &salsa::Cycle, key: MyInput) -> i32 { +fn recover_b3(db: &dyn KnobsDatabase, _cycle: &salsa::Cycle, key: MyInput) -> i32 { dbg!("recover_b3"); key.field(db) * 200 + 2 } @@ -88,7 +81,7 @@ fn recover_b3(db: &dyn Db, _cycle: &salsa::Cycle, key: MyInput) -> i32 { #[test] fn execute() { - let db = Handle::new(Database::default()); + let db = Handle::new(>::default()); db.knobs().signal_on_will_block.store(3); let input = MyInput::new(&*db, 1); diff --git a/tests/parallel/parallel_cycle_none_recover.rs b/tests/parallel/parallel_cycle_none_recover.rs index 59036685..39b6299c 100644 --- a/tests/parallel/parallel_cycle_none_recover.rs +++ b/tests/parallel/parallel_cycle_none_recover.rs @@ -2,25 +2,20 @@ //! See the `../cycles.rs` for a complete listing of cycle tests, //! both intra and cross thread. -use crate::setup::Database; use crate::setup::Knobs; +use crate::setup::KnobsDatabase; use expect_test::expect; use salsa::Database as _; +use salsa::DatabaseImpl; use salsa::Handle; -#[salsa::db] -pub(crate) trait Db: salsa::Database + Knobs {} - -#[salsa::db] -impl Db for T {} - #[salsa::input] pub(crate) struct MyInput { field: i32, } #[salsa::tracked] -pub(crate) fn a(db: &dyn Db, input: MyInput) -> i32 { +pub(crate) fn a(db: &dyn KnobsDatabase, input: MyInput) -> i32 { // Wait to create the cycle until both threads have entered db.signal(1); db.wait_for(2); @@ -29,7 +24,7 @@ pub(crate) fn a(db: &dyn Db, input: MyInput) -> i32 { } #[salsa::tracked] -pub(crate) fn b(db: &dyn Db, input: MyInput) -> i32 { +pub(crate) fn b(db: &dyn KnobsDatabase, input: MyInput) -> i32 { // Wait to create the cycle until both threads have entered db.wait_for(1); db.signal(2); @@ -43,7 +38,7 @@ pub(crate) fn b(db: &dyn Db, input: MyInput) -> i32 { #[test] fn execute() { - let db = Handle::new(Database::default()); + let db = Handle::new(>::default()); db.knobs().signal_on_will_block.store(3); let input = MyInput::new(&*db, -1); diff --git a/tests/parallel/parallel_cycle_one_recover.rs b/tests/parallel/parallel_cycle_one_recover.rs index 044fe826..7a32d95c 100644 --- a/tests/parallel/parallel_cycle_one_recover.rs +++ b/tests/parallel/parallel_cycle_one_recover.rs @@ -2,16 +2,9 @@ //! See `../cycles.rs` for a complete listing of cycle tests, //! both intra and cross thread. -use salsa::Handle; +use salsa::{DatabaseImpl, Handle}; -use crate::setup::Database; -use crate::setup::Knobs; - -#[salsa::db] -pub(crate) trait Db: salsa::Database + Knobs {} - -#[salsa::db] -impl Db for T {} +use crate::setup::{Knobs, KnobsDatabase}; #[salsa::input] pub(crate) struct MyInput { @@ -19,7 +12,7 @@ pub(crate) struct MyInput { } #[salsa::tracked] -pub(crate) fn a1(db: &dyn Db, input: MyInput) -> i32 { +pub(crate) fn a1(db: &dyn KnobsDatabase, input: MyInput) -> i32 { // Wait to create the cycle until both threads have entered db.signal(1); db.wait_for(2); @@ -28,17 +21,17 @@ pub(crate) fn a1(db: &dyn Db, input: MyInput) -> i32 { } #[salsa::tracked(recovery_fn=recover)] -pub(crate) fn a2(db: &dyn Db, input: MyInput) -> i32 { +pub(crate) fn a2(db: &dyn KnobsDatabase, input: MyInput) -> i32 { b1(db, input) } -fn recover(db: &dyn Db, _cycle: &salsa::Cycle, key: MyInput) -> i32 { +fn recover(db: &dyn KnobsDatabase, _cycle: &salsa::Cycle, key: MyInput) -> i32 { dbg!("recover"); key.field(db) * 20 + 2 } #[salsa::tracked] -pub(crate) fn b1(db: &dyn Db, input: MyInput) -> i32 { +pub(crate) fn b1(db: &dyn KnobsDatabase, input: MyInput) -> i32 { // Wait to create the cycle until both threads have entered db.wait_for(1); db.signal(2); @@ -49,7 +42,7 @@ pub(crate) fn b1(db: &dyn Db, input: MyInput) -> i32 { } #[salsa::tracked] -pub(crate) fn b2(db: &dyn Db, input: MyInput) -> i32 { +pub(crate) fn b2(db: &dyn KnobsDatabase, input: MyInput) -> i32 { a1(db, input) } @@ -77,7 +70,7 @@ pub(crate) fn b2(db: &dyn Db, input: MyInput) -> i32 { #[test] fn execute() { - let db = Handle::new(Database::default()); + let db = Handle::new(>::default()); db.knobs().signal_on_will_block.store(3); let input = MyInput::new(&*db, 1); diff --git a/tests/parallel/setup.rs b/tests/parallel/setup.rs index c7c00ee8..6410f853 100644 --- a/tests/parallel/setup.rs +++ b/tests/parallel/setup.rs @@ -1,11 +1,13 @@ use crossbeam::atomic::AtomicCell; +use salsa::{Database, DatabaseImpl, UserData}; use crate::signal::Signal; /// Various "knobs" and utilities used by tests to force /// a certain behavior. -pub(crate) trait Knobs { - fn knobs(&self) -> &KnobsStruct; +#[salsa::db] +pub(crate) trait KnobsDatabase: Database { + fn knobs(&self) -> &Knobs; fn signal(&self, stage: usize); @@ -16,7 +18,7 @@ pub(crate) trait Knobs { /// behave on one specific thread. Note that this state is /// intentionally thread-local (apart from `signal`). #[derive(Default)] -pub(crate) struct KnobsStruct { +pub(crate) struct Knobs { /// A kind of flexible barrier used to coordinate execution across /// threads to ensure we reach various weird states. pub(crate) signal: Signal, @@ -28,39 +30,32 @@ pub(crate) struct KnobsStruct { pub(crate) signal_on_did_cancel: AtomicCell, } -#[salsa::db] -#[derive(Default)] -pub(crate) struct Database { - storage: salsa::Storage, - knobs: KnobsStruct, -} - -#[salsa::db] -impl salsa::Database for Database { - fn salsa_event(&self, event: &dyn Fn() -> salsa::Event) { +impl UserData for Knobs { + fn salsa_event(db: &DatabaseImpl, event: &dyn Fn() -> salsa::Event) { let event = event(); match event.kind { salsa::EventKind::WillBlockOn { .. } => { - self.signal(self.knobs().signal_on_will_block.load()); + db.signal(db.signal_on_will_block.load()); } salsa::EventKind::DidSetCancellationFlag => { - self.signal(self.knobs().signal_on_did_cancel.load()); + db.signal(db.signal_on_did_cancel.load()); } _ => {} } } } -impl Knobs for Database { - fn knobs(&self) -> &KnobsStruct { - &self.knobs +#[salsa::db] +impl KnobsDatabase for DatabaseImpl { + fn knobs(&self) -> &Knobs { + self } fn signal(&self, stage: usize) { - self.knobs.signal.signal(stage); + self.signal.signal(stage); } fn wait_for(&self, stage: usize) { - self.knobs.signal.wait_for(stage); + self.signal.wait_for(stage); } } diff --git a/tests/preverify-struct-with-leaked-data.rs b/tests/preverify-struct-with-leaked-data.rs index 2e311c6f..2c5bdfd5 100644 --- a/tests/preverify-struct-with-leaked-data.rs +++ b/tests/preverify-struct-with-leaked-data.rs @@ -5,41 +5,14 @@ use std::cell::Cell; use expect_test::expect; mod common; -use common::{HasLogger, Logger}; -use salsa::Setter; +use common::{EventLogger, LogDatabase}; +use salsa::{Database, Setter}; use test_log::test; thread_local! { static COUNTER: Cell = const { Cell::new(0) }; } -#[salsa::db] -trait Db: salsa::Database + HasLogger {} - -#[salsa::db] -#[derive(Default)] -struct Database { - storage: salsa::Storage, - logger: Logger, -} - -#[salsa::db] -impl salsa::Database for Database { - fn salsa_event(&self, event: &dyn Fn() -> salsa::Event) { - let event = event(); - self.push_log(format!("{event:?}")); - } -} - -#[salsa::db] -impl Db for Database {} - -impl HasLogger for Database { - fn logger(&self) -> &Logger { - &self.logger - } -} - #[salsa::input] struct MyInput { field1: u32, @@ -52,7 +25,7 @@ struct MyTracked<'db> { } #[salsa::tracked] -fn function(db: &dyn Db, input: MyInput) -> usize { +fn function(db: &dyn Database, input: MyInput) -> usize { // Read input 1 let _field1 = input.field1(db); @@ -71,7 +44,7 @@ fn function(db: &dyn Db, input: MyInput) -> usize { #[test] fn test_leaked_inputs_ignored() { - let mut db = Database::default(); + let mut db: salsa::DatabaseImpl = Default::default(); let input = MyInput::new(&db, 10, 20); let result_in_rev_1 = function(&db, input); diff --git a/tests/singleton.rs b/tests/singleton.rs index 041eb309..539d48cb 100644 --- a/tests/singleton.rs +++ b/tests/singleton.rs @@ -3,8 +3,6 @@ //! Singleton structs are created only once. Subsequent `get`s and `new`s after creation return the same `Id`. use expect_test::expect; -mod common; -use common::{HasLogger, Logger}; use salsa::Database as _; use test_log::test; @@ -15,25 +13,9 @@ struct MyInput { id_field: u16, } -#[salsa::db] -#[derive(Default)] -struct Database { - storage: salsa::Storage, - logger: Logger, -} - -#[salsa::db] -impl salsa::Database for Database {} - -impl HasLogger for Database { - fn logger(&self) -> &Logger { - &self.logger - } -} - #[test] fn basic() { - let db = Database::default(); + let db = salsa::DatabaseImpl::new(); let input1 = MyInput::new(&db, 3, 4); let input2 = MyInput::get(&db); @@ -46,7 +28,7 @@ fn basic() { #[test] #[should_panic] fn twice() { - let db = Database::default(); + let db = salsa::DatabaseImpl::new(); let input1 = MyInput::new(&db, 3, 4); let input2 = MyInput::get(&db); @@ -58,7 +40,7 @@ fn twice() { #[test] fn debug() { - Database::default().attach(|db| { + salsa::DatabaseImpl::new().attach(|db| { let input = MyInput::new(db, 3, 4); let actual = format!("{:?}", input); let expected = expect!["MyInput { [salsa id]: Id(0), field: 3, id_field: 4 }"]; diff --git a/tests/specify-only-works-if-the-key-is-created-in-the-current-query.rs b/tests/specify-only-works-if-the-key-is-created-in-the-current-query.rs index f82a684c..a407aee6 100644 --- a/tests/specify-only-works-if-the-key-is-created-in-the-current-query.rs +++ b/tests/specify-only-works-if-the-key-is-created-in-the-current-query.rs @@ -2,9 +2,6 @@ //! compilation succeeds but execution panics #![allow(warnings)] -#[salsa::db] -trait Db: salsa::Database {} - #[salsa::input] struct MyInput { field: u32, @@ -16,12 +13,15 @@ struct MyTracked<'db> { } #[salsa::tracked] -fn tracked_struct_created_in_another_query<'db>(db: &'db dyn Db, input: MyInput) -> MyTracked<'db> { +fn tracked_struct_created_in_another_query<'db>( + db: &'db dyn salsa::Database, + input: MyInput, +) -> MyTracked<'db> { MyTracked::new(db, input.field(db) * 2) } #[salsa::tracked] -fn tracked_fn<'db>(db: &'db dyn Db, input: MyInput) -> MyTracked<'db> { +fn tracked_fn<'db>(db: &'db dyn salsa::Database, input: MyInput) -> MyTracked<'db> { let t = tracked_struct_created_in_another_query(db, input); if input.field(db) != 0 { tracked_fn_extra::specify(db, t, 2222); @@ -30,28 +30,16 @@ fn tracked_fn<'db>(db: &'db dyn Db, input: MyInput) -> MyTracked<'db> { } #[salsa::tracked(specify)] -fn tracked_fn_extra<'db>(_db: &'db dyn Db, _input: MyTracked<'db>) -> u32 { +fn tracked_fn_extra<'db>(_db: &'db dyn salsa::Database, _input: MyTracked<'db>) -> u32 { 0 } -#[salsa::db] -#[derive(Default)] -struct Database { - storage: salsa::Storage, -} - -#[salsa::db] -impl salsa::Database for Database {} - -#[salsa::db] -impl Db for Database {} - #[test] #[should_panic( expected = "can only use `specify` on salsa structs created during the current tracked fn" )] fn execute_when_specified() { - let mut db = Database::default(); + let mut db = salsa::DatabaseImpl::new(); let input = MyInput::new(&db, 22); let tracked = tracked_fn(&db, input); } diff --git a/tests/tracked-struct-id-field-bad-eq.rs b/tests/tracked-struct-id-field-bad-eq.rs index 49c4544d..b003a305 100644 --- a/tests/tracked-struct-id-field-bad-eq.rs +++ b/tests/tracked-struct-id-field-bad-eq.rs @@ -1,6 +1,6 @@ //! Test an id field whose `PartialEq` impl is always true. -use salsa::{Database as Db, Setter}; +use salsa::{Database, Setter}; use test_log::test; #[salsa::input] @@ -33,24 +33,14 @@ struct MyTracked<'db> { } #[salsa::tracked] -fn the_fn(db: &dyn Db, input: MyInput) { +fn the_fn(db: &dyn Database, input: MyInput) { let tracked0 = MyTracked::new(db, BadEq::from(input.field(db))); assert_eq!(tracked0.field(db).field, input.field(db)); } -#[salsa::db] -#[derive(Default)] -struct Database { - storage: salsa::Storage, -} - -#[salsa::db] -impl salsa::Database for Database {} - #[test] fn execute() { - let mut db = Database::default(); - + let mut db = salsa::DatabaseImpl::new(); let input = MyInput::new(&db, true); the_fn(&db, input); input.set_field(&mut db).to(false); diff --git a/tests/tracked-struct-id-field-bad-hash.rs b/tests/tracked-struct-id-field-bad-hash.rs index c1f455ae..8a391b3b 100644 --- a/tests/tracked-struct-id-field-bad-hash.rs +++ b/tests/tracked-struct-id-field-bad-hash.rs @@ -42,18 +42,9 @@ fn the_fn(db: &dyn Db, input: MyInput) { assert_eq!(tracked0.field(db).field, input.field(db)); } -#[salsa::db] -#[derive(Default)] -struct Database { - storage: salsa::Storage, -} - -#[salsa::db] -impl salsa::Database for Database {} - #[test] fn execute() { - let mut db = Database::default(); + let mut db = salsa::DatabaseImpl::new(); let input = MyInput::new(&db, true); the_fn(&db, input); diff --git a/tests/tracked-struct-unchanged-in-new-rev.rs b/tests/tracked-struct-unchanged-in-new-rev.rs index 7bbfb340..e4633740 100644 --- a/tests/tracked-struct-unchanged-in-new-rev.rs +++ b/tests/tracked-struct-unchanged-in-new-rev.rs @@ -16,18 +16,9 @@ fn tracked_fn(db: &dyn Db, input: MyInput) -> MyTracked<'_> { MyTracked::new(db, input.field(db) / 2) } -#[salsa::db] -#[derive(Default)] -struct Database { - storage: salsa::Storage, -} - -#[salsa::db] -impl salsa::Database for Database {} - #[test] fn execute() { - let mut db = Database::default(); + let mut db = salsa::DatabaseImpl::new(); let input1 = MyInput::new(&db, 22); let input2 = MyInput::new(&db, 44); diff --git a/tests/tracked-struct-value-field-bad-eq.rs b/tests/tracked-struct-value-field-bad-eq.rs index a9d50c6f..ec4cac5f 100644 --- a/tests/tracked-struct-value-field-bad-eq.rs +++ b/tests/tracked-struct-value-field-bad-eq.rs @@ -3,9 +3,9 @@ //! if we were to execute from scratch. use expect_test::expect; -use salsa::{Database as Db, Setter}; +use salsa::{Database, Setter}; mod common; -use common::{HasLogger, Logger}; +use common::LogDatabase; use test_log::test; #[salsa::input] @@ -37,51 +37,24 @@ struct MyTracked<'db> { } #[salsa::tracked] -fn the_fn(db: &dyn Db, input: MyInput) -> bool { +fn the_fn(db: &dyn Database, input: MyInput) -> bool { let tracked = make_tracked_struct(db, input); read_tracked_struct(db, tracked) } #[salsa::tracked] -fn make_tracked_struct(db: &dyn Db, input: MyInput) -> MyTracked<'_> { +fn make_tracked_struct(db: &dyn Database, input: MyInput) -> MyTracked<'_> { MyTracked::new(db, BadEq::from(input.field(db))) } #[salsa::tracked] -fn read_tracked_struct<'db>(db: &'db dyn Db, tracked: MyTracked<'db>) -> bool { +fn read_tracked_struct<'db>(db: &'db dyn Database, tracked: MyTracked<'db>) -> bool { tracked.field(db).field } -#[salsa::db] -#[derive(Default)] -struct Database { - storage: salsa::Storage, - logger: Logger, -} - -#[salsa::db] -impl salsa::Database for Database { - fn salsa_event(&self, event: &dyn Fn() -> salsa::Event) { - let event = event(); - match event.kind { - salsa::EventKind::WillExecute { .. } - | salsa::EventKind::DidValidateMemoizedValue { .. } => { - self.push_log(format!("salsa_event({:?})", event.kind)); - } - _ => {} - } - } -} - -impl HasLogger for Database { - fn logger(&self) -> &Logger { - &self.logger - } -} - #[test] fn execute() { - let mut db = Database::default(); + let mut db: salsa::DatabaseImpl = Default::default(); let input = MyInput::new(&db, true); let result = the_fn(&db, input); diff --git a/tests/tracked-struct-value-field-not-eq.rs b/tests/tracked-struct-value-field-not-eq.rs index f529f31a..eaf4a30c 100644 --- a/tests/tracked-struct-value-field-not-eq.rs +++ b/tests/tracked-struct-value-field-not-eq.rs @@ -2,7 +2,7 @@ //! This can our "last changed" data to be wrong //! but we *should* always reflect the final values. -use salsa::{Database as Db, Setter}; +use salsa::{Database, Setter}; use test_log::test; #[salsa::input] @@ -28,23 +28,14 @@ struct MyTracked<'db> { } #[salsa::tracked] -fn the_fn(db: &dyn Db, input: MyInput) { +fn the_fn(db: &dyn Database, input: MyInput) { let tracked0 = MyTracked::new(db, NotEq::from(input.field(db))); assert_eq!(tracked0.field(db).field, input.field(db)); } -#[salsa::db] -#[derive(Default)] -struct Database { - storage: salsa::Storage, -} - -#[salsa::db] -impl salsa::Database for Database {} - #[test] fn execute() { - let mut db = Database::default(); + let mut db = salsa::DatabaseImpl::new(); let input = MyInput::new(&db, true); the_fn(&db, input); diff --git a/tests/tracked_fn_constant.rs b/tests/tracked_fn_constant.rs index db443a79..b53f1b15 100644 --- a/tests/tracked_fn_constant.rs +++ b/tests/tracked_fn_constant.rs @@ -9,15 +9,6 @@ fn tracked_fn(db: &dyn salsa::Database) -> u32 { #[test] fn execute() { - #[salsa::db] - #[derive(Default)] - struct Database { - storage: salsa::Storage, - } - - #[salsa::db] - impl salsa::Database for Database {} - - let mut db = Database::default(); + let mut db = salsa::DatabaseImpl::new(); assert_eq!(tracked_fn(&db), 44); } diff --git a/tests/tracked_fn_no_eq.rs b/tests/tracked_fn_no_eq.rs index 77d45050..ee7c5651 100644 --- a/tests/tracked_fn_no_eq.rs +++ b/tests/tracked_fn_no_eq.rs @@ -1,11 +1,8 @@ mod common; -use common::{HasLogger, Logger}; +use common::{LogDatabase, Logger}; use expect_test::expect; -use salsa::Setter as _; - -#[salsa::db] -trait Db: salsa::Database + HasLogger {} +use salsa::{DatabaseImpl, Setter as _}; #[salsa::input] struct Input { @@ -13,7 +10,7 @@ struct Input { } #[salsa::tracked(no_eq)] -fn abs_float(db: &dyn Db, input: Input) -> f32 { +fn abs_float(db: &dyn LogDatabase, input: Input) -> f32 { let number = input.number(db); db.push_log(format!("abs_float({number})")); @@ -21,35 +18,15 @@ fn abs_float(db: &dyn Db, input: Input) -> f32 { } #[salsa::tracked] -fn derived(db: &dyn Db, input: Input) -> u32 { +fn derived(db: &dyn LogDatabase, input: Input) -> u32 { let x = abs_float(db, input); db.push_log("derived".to_string()); x as u32 } - -#[salsa::db] -#[derive(Default)] -struct Database { - storage: salsa::Storage, - logger: Logger, -} - -impl HasLogger for Database { - fn logger(&self) -> &Logger { - &self.logger - } -} - -#[salsa::db] -impl salsa::Database for Database {} - -#[salsa::db] -impl Db for Database {} - #[test] fn invoke() { - let mut db = Database::default(); + let mut db: DatabaseImpl = Default::default(); let input = Input::new(&db, 5); let x = derived(&db, input); diff --git a/tests/tracked_fn_on_input.rs b/tests/tracked_fn_on_input.rs index 2ea3fa6f..e588a40a 100644 --- a/tests/tracked_fn_on_input.rs +++ b/tests/tracked_fn_on_input.rs @@ -14,16 +14,7 @@ fn tracked_fn(db: &dyn salsa::Database, input: MyInput) -> u32 { #[test] fn execute() { - #[salsa::db] - #[derive(Default)] - struct Database { - storage: salsa::Storage, - } - - #[salsa::db] - impl salsa::Database for Database {} - - let mut db = Database::default(); + let mut db = salsa::DatabaseImpl::new(); let input = MyInput::new(&db, 22); assert_eq!(tracked_fn(&db, input), 44); } diff --git a/tests/tracked_fn_on_interned.rs b/tests/tracked_fn_on_interned.rs index 852c3428..b551b880 100644 --- a/tests/tracked_fn_on_interned.rs +++ b/tests/tracked_fn_on_interned.rs @@ -11,18 +11,9 @@ fn tracked_fn<'db>(db: &'db dyn salsa::Database, name: Name<'db>) -> String { name.name(db).clone() } -#[salsa::db] -#[derive(Default)] -struct Database { - storage: salsa::Storage, -} - -#[salsa::db] -impl salsa::Database for Database {} - #[test] fn execute() { - let db = Database::default(); + let db = salsa::DatabaseImpl::new(); let name = Name::new(&db, "Salsa".to_string()); assert_eq!(tracked_fn(&db, name), "Salsa"); diff --git a/tests/tracked_fn_on_tracked.rs b/tests/tracked_fn_on_tracked.rs index 72aae634..967bbd55 100644 --- a/tests/tracked_fn_on_tracked.rs +++ b/tests/tracked_fn_on_tracked.rs @@ -16,18 +16,9 @@ fn tracked_fn(db: &dyn salsa::Database, input: MyInput) -> MyTracked<'_> { MyTracked::new(db, input.field(db) * 2) } -#[salsa::db] -#[derive(Default)] -struct Database { - storage: salsa::Storage, -} - -#[salsa::db] -impl salsa::Database for Database {} - #[test] fn execute() { - let db = Database::default(); + let db = salsa::DatabaseImpl::new(); let input = MyInput::new(&db, 22); assert_eq!(tracked_fn(&db, input).field(&db), 44); } diff --git a/tests/tracked_fn_on_tracked_specify.rs b/tests/tracked_fn_on_tracked_specify.rs index 9a76b498..70e4997a 100644 --- a/tests/tracked_fn_on_tracked_specify.rs +++ b/tests/tracked_fn_on_tracked_specify.rs @@ -26,18 +26,9 @@ fn tracked_fn_extra<'db>(_db: &'db dyn salsa::Database, _input: MyTracked<'db>) 0 } -#[salsa::db] -#[derive(Default)] -struct Database { - storage: salsa::Storage, -} - -#[salsa::db] -impl salsa::Database for Database {} - #[test] fn execute_when_specified() { - let mut db = Database::default(); + let mut db = salsa::DatabaseImpl::new(); let input = MyInput::new(&db, 22); let tracked = tracked_fn(&db, input); assert_eq!(tracked.field(&db), 44); @@ -46,7 +37,7 @@ fn execute_when_specified() { #[test] fn execute_when_not_specified() { - let mut db = Database::default(); + let mut db = salsa::DatabaseImpl::new(); let input = MyInput::new(&db, 0); let tracked = tracked_fn(&db, input); assert_eq!(tracked.field(&db), 0); diff --git a/tests/tracked_fn_read_own_entity.rs b/tests/tracked_fn_read_own_entity.rs index 588a221f..ad4a7002 100644 --- a/tests/tracked_fn_read_own_entity.rs +++ b/tests/tracked_fn_read_own_entity.rs @@ -3,20 +3,17 @@ use expect_test::expect; mod common; -use common::{HasLogger, Logger}; +use common::{LogDatabase, Logger}; use salsa::Setter; use test_log::test; -#[salsa::db] -trait Db: salsa::Database + HasLogger {} - #[salsa::input] struct MyInput { field: u32, } #[salsa::tracked] -fn final_result(db: &dyn Db, input: MyInput) -> u32 { +fn final_result(db: &dyn LogDatabase, input: MyInput) -> u32 { db.push_log(format!("final_result({:?})", input)); intermediate_result(db, input).field(db) * 2 } @@ -27,35 +24,16 @@ struct MyTracked<'db> { } #[salsa::tracked] -fn intermediate_result(db: &dyn Db, input: MyInput) -> MyTracked<'_> { +fn intermediate_result(db: &dyn LogDatabase, input: MyInput) -> MyTracked<'_> { db.push_log(format!("intermediate_result({:?})", input)); let tracked = MyTracked::new(db, input.field(db) / 2); let _ = tracked.field(db); // read the field of an entity we created tracked } -#[salsa::db] -#[derive(Default)] -struct Database { - storage: salsa::Storage, - logger: Logger, -} - -#[salsa::db] -impl salsa::Database for Database {} - -#[salsa::db] -impl Db for Database {} - -impl HasLogger for Database { - fn logger(&self) -> &Logger { - &self.logger - } -} - #[test] fn one_entity() { - let mut db = Database::default(); + let mut db: salsa::DatabaseImpl = Default::default(); let input = MyInput::new(&db, 22); assert_eq!(final_result(&db, input), 22); @@ -86,7 +64,7 @@ fn one_entity() { /// Create and mutate a distinct input. No re-execution required. #[test] fn red_herring() { - let mut db = Database::default(); + let mut db: salsa::DatabaseImpl = Default::default(); let input = MyInput::new(&db, 22); assert_eq!(final_result(&db, input), 22); diff --git a/tests/tracked_fn_read_own_specify.rs b/tests/tracked_fn_read_own_specify.rs index 63d2134e..0c643366 100644 --- a/tests/tracked_fn_read_own_specify.rs +++ b/tests/tracked_fn_read_own_specify.rs @@ -1,10 +1,7 @@ use expect_test::expect; -use salsa::Database as SalsaDatabase; mod common; -use common::{HasLogger, Logger}; - -#[salsa::db] -trait Db: salsa::Database + HasLogger {} +use common::{LogDatabase, Logger}; +use salsa::Database; #[salsa::input] struct MyInput { @@ -17,7 +14,7 @@ struct MyTracked<'db> { } #[salsa::tracked] -fn tracked_fn(db: &dyn Db, input: MyInput) -> u32 { +fn tracked_fn(db: &dyn LogDatabase, input: MyInput) -> u32 { db.push_log(format!("tracked_fn({input:?})")); let t = MyTracked::new(db, input.field(db) * 2); tracked_fn_extra::specify(db, t, 2222); @@ -25,33 +22,14 @@ fn tracked_fn(db: &dyn Db, input: MyInput) -> u32 { } #[salsa::tracked(specify)] -fn tracked_fn_extra<'db>(db: &dyn Db, input: MyTracked<'db>) -> u32 { +fn tracked_fn_extra<'db>(db: &dyn LogDatabase, input: MyTracked<'db>) -> u32 { db.push_log(format!("tracked_fn_extra({input:?})")); 0 } -#[salsa::db] -#[derive(Default)] -struct Database { - storage: salsa::Storage, - logger: Logger, -} - -#[salsa::db] -impl salsa::Database for Database {} - -#[salsa::db] -impl Db for Database {} - -impl HasLogger for Database { - fn logger(&self) -> &Logger { - &self.logger - } -} - #[test] fn execute() { - let mut db = Database::default(); + let mut db: salsa::DatabaseImpl = salsa::DatabaseImpl::default(); let input = MyInput::new(&db, 22); assert_eq!(tracked_fn(&db, input), 2222); db.assert_logs(expect![[r#" diff --git a/tests/tracked_fn_return_ref.rs b/tests/tracked_fn_return_ref.rs index d4cab330..ecd91a17 100644 --- a/tests/tracked_fn_return_ref.rs +++ b/tests/tracked_fn_return_ref.rs @@ -1,4 +1,4 @@ -use salsa::Database as _; +use salsa::Database; #[salsa::input] struct Input { @@ -12,18 +12,9 @@ fn test(db: &dyn salsa::Database, input: Input) -> Vec { .collect() } -#[salsa::db] -#[derive(Default)] -struct Database { - storage: salsa::Storage, -} - -#[salsa::db] -impl salsa::Database for Database {} - #[test] fn invoke() { - Database::default().attach(|db| { + salsa::DatabaseImpl::new().attach(|db| { let input = Input::new(db, 3); let x: &Vec = test(db, input); expect_test::expect![[r#" diff --git a/tests/tracked_method.rs b/tests/tracked_method.rs index 10bc5ad6..0291a748 100644 --- a/tests/tracked_method.rs +++ b/tests/tracked_method.rs @@ -34,16 +34,7 @@ impl TrackedTrait for MyInput { #[test] fn execute() { - #[salsa::db] - #[derive(Default)] - struct Database { - storage: salsa::Storage, - } - - #[salsa::db] - impl salsa::Database for Database {} - - let mut db = Database::default(); + let mut db = salsa::DatabaseImpl::new(); let object = MyInput::new(&mut db, 22); // assert_eq!(object.tracked_fn(&db), 44); // assert_eq!(*object.tracked_fn_ref(&db), 66); diff --git a/tests/tracked_method_inherent_return_ref.rs b/tests/tracked_method_inherent_return_ref.rs index e6fa65a8..462a24da 100644 --- a/tests/tracked_method_inherent_return_ref.rs +++ b/tests/tracked_method_inherent_return_ref.rs @@ -1,4 +1,4 @@ -use salsa::Database as _; +use salsa::Database; #[salsa::input] struct Input { @@ -15,18 +15,9 @@ impl Input { } } -#[salsa::db] -#[derive(Default)] -struct Database { - storage: salsa::Storage, -} - -#[salsa::db] -impl salsa::Database for Database {} - #[test] fn invoke() { - Database::default().attach(|db| { + salsa::DatabaseImpl::new().attach(|db| { let input = Input::new(db, 3); let x: &Vec = input.test(db); expect_test::expect![[r#" diff --git a/tests/tracked_method_on_tracked_struct.rs b/tests/tracked_method_on_tracked_struct.rs index b50bd9d6..1febcfd3 100644 --- a/tests/tracked_method_on_tracked_struct.rs +++ b/tests/tracked_method_on_tracked_struct.rs @@ -43,7 +43,7 @@ impl<'db1> ItemName<'db1> for SourceTree<'db1> { #[test] fn test_inherent() { - salsa::default_database().attach(|db| { + salsa::DatabaseImpl::new().attach(|db| { let input = Input::new(db, "foo".to_string()); let source_tree = input.source_tree(db); expect_test::expect![[r#" @@ -55,7 +55,7 @@ fn test_inherent() { #[test] fn test_trait() { - salsa::default_database().attach(|db| { + salsa::DatabaseImpl::new().attach(|db| { let input = Input::new(db, "foo".to_string()); let source_tree = input.source_tree(db); expect_test::expect![[r#" diff --git a/tests/tracked_method_trait_return_ref.rs b/tests/tracked_method_trait_return_ref.rs index 80d4035c..3c9fa5cc 100644 --- a/tests/tracked_method_trait_return_ref.rs +++ b/tests/tracked_method_trait_return_ref.rs @@ -1,4 +1,4 @@ -use salsa::Database as _; +use salsa::Database; #[salsa::input] struct Input { @@ -19,18 +19,9 @@ impl Trait for Input { } } -#[salsa::db] -#[derive(Default)] -struct Database { - storage: salsa::Storage, -} - -#[salsa::db] -impl salsa::Database for Database {} - #[test] fn invoke() { - Database::default().attach(|db| { + salsa::DatabaseImpl::new().attach(|db| { let input = Input::new(db, 3); let x: &Vec = input.test(db); expect_test::expect![[r#" diff --git a/tests/tracked_struct_db1_lt.rs b/tests/tracked_struct_db1_lt.rs index 6931ea7e..e5de757c 100644 --- a/tests/tracked_struct_db1_lt.rs +++ b/tests/tracked_struct_db1_lt.rs @@ -20,14 +20,5 @@ struct MyTracked2<'db2> { field: u32, } -#[salsa::db] -#[derive(Default)] -struct Database { - storage: salsa::Storage, -} - -#[salsa::db] -impl salsa::Database for Database {} - #[test] fn create_db() {} diff --git a/tests/tracked_with_intern.rs b/tests/tracked_with_intern.rs index 508a93c1..a8a72e8c 100644 --- a/tests/tracked_with_intern.rs +++ b/tests/tracked_with_intern.rs @@ -3,15 +3,6 @@ use test_log::test; -#[salsa::db] -#[derive(Default)] -struct Database { - storage: salsa::Storage, -} - -#[salsa::db] -impl salsa::Database for Database {} - #[salsa::input] struct MyInput { field: String, diff --git a/tests/tracked_with_struct_db.rs b/tests/tracked_with_struct_db.rs index 232538c7..236edede 100644 --- a/tests/tracked_with_struct_db.rs +++ b/tests/tracked_with_struct_db.rs @@ -1,18 +1,9 @@ //! Test that a setting a field on a `#[salsa::input]` //! overwrites and returns the old value. -use salsa::Database as _; +use salsa::{Database, DatabaseImpl}; use test_log::test; -#[salsa::db] -#[derive(Default)] -struct Database { - storage: salsa::Storage, -} - -#[salsa::db] -impl salsa::Database for Database {} - #[salsa::input] struct MyInput { field: String, @@ -31,7 +22,7 @@ enum MyList<'db> { } #[salsa::tracked] -fn create_tracked_list(db: &dyn salsa::Database, input: MyInput) -> MyTracked<'_> { +fn create_tracked_list(db: &dyn Database, input: MyInput) -> MyTracked<'_> { let t0 = MyTracked::new(db, input, MyList::None); let t1 = MyTracked::new(db, input, MyList::Next(t0)); t1 @@ -39,7 +30,7 @@ fn create_tracked_list(db: &dyn salsa::Database, input: MyInput) -> MyTracked<'_ #[test] fn execute() { - Database::default().attach(|db| { + DatabaseImpl::new().attach(|db| { let input = MyInput::new(db, "foo".to_string()); let t0: MyTracked = create_tracked_list(db, input); let t1 = create_tracked_list(db, input);