diff --git a/book/src/rfcs/RFC0006-Dynamic-Databases.md b/book/src/rfcs/RFC0006-Dynamic-Databases.md index 49e9cd5e..9b1fc2b5 100644 --- a/book/src/rfcs/RFC0006-Dynamic-Databases.md +++ b/book/src/rfcs/RFC0006-Dynamic-Databases.md @@ -310,8 +310,8 @@ Therefore `QueryFunction` for example can become: ```rust,ignore pub trait QueryFunction: Query { - fn execute(db: &Self::DynDb, key: Self::Key) -> Self::Value; - fn recover(db: &Self::DynDb, cycle: &[DB::DatabaseKey], key: &Self::Key) -> Option { + fn execute(db: &>::DynDb, key: Self::Key) -> Self::Value; + fn recover(db: &>::DynDb, cycle: &[DB::DatabaseKey], key: &Self::Key) -> Option { let _ = (db, cycle, key); None } @@ -455,7 +455,7 @@ we have to make a few changes: One downside of this proposal is that the `salsa::Database` trait now has a `'static` bound. This is a result of the lack of GATs -- in particular, the -queries expect a `Q::DynDb` as argument. In the query definition, we have +queries expect a `>::DynDb` as argument. In the query definition, we have something like `type DynDb = dyn QueryGroupDatabase`, which in turn defaults to `dyn::QueryGroupDatabase + 'static`. diff --git a/components/salsa-macros/src/query_group.rs b/components/salsa-macros/src/query_group.rs index a8944a7b..8fa219b1 100644 --- a/components/salsa-macros/src/query_group.rs +++ b/components/salsa-macros/src/query_group.rs @@ -262,7 +262,7 @@ pub(crate) fn query_group(args: TokenStream, input: TokenStream) -> TokenStream // query crate. Our experiments revealed that this makes a big // difference in total compilation time in rust-analyzer, though // it's not totally obvious why that should be. - fn __shim(db: &dyn #trait_name, #(#key_names: #keys),*) -> #value { + fn __shim(db: &(dyn #trait_name + '_), #(#key_names: #keys),*) -> #value { salsa::plumbing::get_query_table::<#qt>(db).get((#(#key_names),*)) } __shim(self, #(#key_names),*) @@ -461,23 +461,27 @@ pub(crate) fn query_group(args: TokenStream, input: TokenStream) -> TokenStream } } + impl<'d> salsa::QueryDb<'d> for #qt + { + type DynDb = #dyn_db + 'd; + type Group = #group_struct; + type GroupStorage = #group_storage; + } + // ANCHOR:Query_impl impl salsa::Query for #qt { type Key = (#(#keys),*); type Value = #value; type Storage = #storage; - type Group = #group_struct; - type GroupStorage = #group_storage; - type DynDb = #dyn_db; const QUERY_INDEX: u16 = #query_index; const QUERY_NAME: &'static str = #query_name; - fn query_storage( - group_storage: &Self::GroupStorage, - ) -> &std::sync::Arc { + fn query_storage<'a>( + group_storage: &'a >::GroupStorage, + ) -> &'a std::sync::Arc { &group_storage.#fn_name } } @@ -499,7 +503,7 @@ pub(crate) fn query_group(args: TokenStream, input: TokenStream) -> TokenStream let recover = if let Some(cycle_recovery_fn) = &query.cycle { quote! { - fn recover(db: &Self::DynDb, cycle: &[salsa::DatabaseKeyIndex], #key_pattern: &::Key) + fn recover(db: &>::DynDb, cycle: &[salsa::DatabaseKeyIndex], #key_pattern: &::Key) -> Option<::Value> { Some(#cycle_recovery_fn( db, @@ -516,7 +520,7 @@ pub(crate) fn query_group(args: TokenStream, input: TokenStream) -> TokenStream // ANCHOR:QueryFunction_impl impl salsa::plumbing::QueryFunction for #qt { - fn execute(db: &Self::DynDb, #key_pattern: ::Key) + fn execute(db: &>::DynDb, #key_pattern: ::Key) -> ::Value { #invoke(db, #(#key_names),*) } @@ -580,7 +584,7 @@ pub(crate) fn query_group(args: TokenStream, input: TokenStream) -> TokenStream impl #group_storage { #trait_vis fn fmt_index( &self, - db: &#dyn_db, + db: &(#dyn_db + '_), input: salsa::DatabaseKeyIndex, fmt: &mut std::fmt::Formatter<'_>, ) -> std::fmt::Result { @@ -592,7 +596,7 @@ pub(crate) fn query_group(args: TokenStream, input: TokenStream) -> TokenStream #trait_vis fn maybe_changed_since( &self, - db: &#dyn_db, + db: &(#dyn_db + '_), input: salsa::DatabaseKeyIndex, revision: salsa::Revision, ) -> bool { diff --git a/examples/compiler/compiler.rs b/examples/compiler/compiler.rs index f0d5592a..319cc241 100644 --- a/examples/compiler/compiler.rs +++ b/examples/compiler/compiler.rs @@ -28,7 +28,7 @@ pub trait Compiler: Interner { /// dolor,sit,amet, /// consectetur,adipiscing,elit /// ``` -fn all_classes(db: &dyn Compiler) -> Arc> { +fn all_classes<'d>(db: &(dyn Compiler + 'd)) -> Arc> { let string = db.input_string(); let rows = string.split('\n'); @@ -53,13 +53,13 @@ fn all_classes(db: &dyn Compiler) -> Arc> { Arc::new(classes) } -fn fields(db: &dyn Compiler, class: Class) -> Arc> { +fn fields<'d>(db: &(dyn Compiler + 'd), class: Class) -> Arc> { let class = db.lookup_intern_class(class); let fields = class.fields.clone(); Arc::new(fields) } -fn all_fields(db: &dyn Compiler) -> Arc> { +fn all_fields<'d>(db: &(dyn Compiler + 'd)) -> Arc> { Arc::new( db.all_classes() .iter() diff --git a/src/debug.rs b/src/debug.rs index f95516ab..f5f06973 100644 --- a/src/debug.rs +++ b/src/debug.rs @@ -49,9 +49,10 @@ impl TableEntry { } } -impl DebugQueryTable for QueryTable<'_, Q> +impl<'d, Q> DebugQueryTable for QueryTable<'_, Q> where Q: Query, + Q::Storage: QueryStorageOps, { type Key = Q::Key; type Value = Q::Value; diff --git a/src/derived.rs b/src/derived.rs index aa972c30..c469918b 100644 --- a/src/derived.rs +++ b/src/derived.rs @@ -7,7 +7,7 @@ use crate::plumbing::QueryFunction; use crate::plumbing::QueryStorageMassOps; use crate::plumbing::QueryStorageOps; use crate::runtime::{FxIndexMap, StampedValue}; -use crate::{CycleError, Database, DatabaseKeyIndex, Revision, Runtime, SweepStrategy}; +use crate::{CycleError, Database, DatabaseKeyIndex, QueryDb, Revision, Runtime, SweepStrategy}; use parking_lot::RwLock; use std::convert::TryFrom; use std::marker::PhantomData; @@ -48,7 +48,7 @@ where { } -pub trait MemoizationPolicy: Send + Sync + 'static +pub trait MemoizationPolicy: Send + Sync where Q: QueryFunction, { @@ -126,7 +126,7 @@ where fn fmt_index( &self, - _db: &Q::DynDb, + _db: &>::DynDb, index: DatabaseKeyIndex, fmt: &mut std::fmt::Formatter<'_>, ) -> std::fmt::Result { @@ -139,7 +139,7 @@ where fn maybe_changed_since( &self, - db: &Q::DynDb, + db: &>::DynDb, input: DatabaseKeyIndex, revision: Revision, ) -> bool { @@ -157,7 +157,7 @@ where fn try_fetch( &self, - db: &Q::DynDb, + db: &>::DynDb, key: &Q::Key, ) -> Result> { let slot = self.slot(key); @@ -177,11 +177,11 @@ where Ok(value) } - fn durability(&self, db: &Q::DynDb, key: &Q::Key) -> Durability { + fn durability(&self, db: &>::DynDb, key: &Q::Key) -> Durability { self.slot(key).durability(db) } - fn entries(&self, _db: &Q::DynDb) -> C + fn entries(&self, _db: &>::DynDb) -> C where C: std::iter::FromIterator>, { @@ -226,7 +226,7 @@ where Q: QueryFunction, MP: MemoizationPolicy, { - fn invalidate(&self, db: &mut Q::DynDb, key: &Q::Key) { + fn invalidate(&self, db: &mut >::DynDb, key: &Q::Key) { db.salsa_runtime_mut() .with_incremented_revision(&mut |_new_revision| { let map_read = self.slot_map.read(); diff --git a/src/derived/slot.rs b/src/derived/slot.rs index ac750a76..0900ed79 100644 --- a/src/derived/slot.rs +++ b/src/derived/slot.rs @@ -11,7 +11,8 @@ use crate::runtime::Runtime; use crate::runtime::RuntimeId; use crate::runtime::StampedValue; use crate::{ - CycleError, Database, DatabaseKeyIndex, DiscardIf, DiscardWhat, Event, EventKind, SweepStrategy, + CycleError, Database, DatabaseKeyIndex, DiscardIf, DiscardWhat, Event, EventKind, QueryDb, + SweepStrategy, }; use log::{debug, info}; use parking_lot::Mutex; @@ -125,7 +126,7 @@ where pub(super) fn read( &self, - db: &Q::DynDb, + db: &>::DynDb, ) -> Result, CycleError> { let runtime = db.salsa_runtime(); @@ -153,7 +154,7 @@ where /// shows a potentially out of date value. fn read_upgrade( &self, - db: &Q::DynDb, + db: &>::DynDb, revision_now: Revision, ) -> Result, CycleError> { let runtime = db.salsa_runtime(); @@ -326,7 +327,7 @@ where /// Note that in case `ProbeState::UpToDate`, the lock will have been released. fn probe( &self, - db: &Q::DynDb, + db: &>::DynDb, state: StateGuard, runtime: &Runtime, revision_now: Revision, @@ -419,7 +420,7 @@ where ProbeState::StaleOrAbsent(state) } - pub(super) fn durability(&self, db: &Q::DynDb) -> Durability { + pub(super) fn durability(&self, db: &>::DynDb) -> Durability { match &*self.state.read() { QueryState::NotComputed => Durability::LOW, QueryState::InProgress { .. } => panic!("query in progress"), @@ -532,7 +533,11 @@ where } } - pub(super) fn maybe_changed_since(&self, db: &Q::DynDb, revision: Revision) -> bool { + pub(super) fn maybe_changed_since( + &self, + db: &>::DynDb, + revision: Revision, + ) -> bool { let runtime = db.salsa_runtime(); let revision_now = runtime.current_revision(); @@ -721,7 +726,7 @@ where /// computed (but first drop the lock on the map). fn register_with_in_progress_thread( &self, - _db: &Q::DynDb, + _db: &>::DynDb, runtime: &Runtime, other_id: RuntimeId, waiting: &Mutex>; 2]>>, @@ -886,7 +891,7 @@ where { fn validate_memoized_value( &mut self, - db: &Q::DynDb, + db: &>::DynDb, revision_now: Revision, ) -> Option> { // If we don't have a memoized value, nothing to validate. @@ -1032,8 +1037,8 @@ where #[allow(dead_code)] fn check_static() where - Q: QueryFunction, - MP: MemoizationPolicy, + Q: QueryFunction + 'static, + MP: MemoizationPolicy + 'static, Q::Key: 'static, Q::Value: 'static, { diff --git a/src/input.rs b/src/input.rs index c7c8ddb0..9738dc39 100644 --- a/src/input.rs +++ b/src/input.rs @@ -8,7 +8,7 @@ use crate::runtime::{FxIndexMap, StampedValue}; use crate::CycleError; use crate::Database; use crate::Query; -use crate::{DatabaseKeyIndex, Runtime, SweepStrategy}; +use crate::{DatabaseKeyIndex, QueryDb, Runtime, SweepStrategy}; use indexmap::map::Entry; use log::debug; use parking_lot::RwLock; @@ -65,7 +65,7 @@ where fn fmt_index( &self, - _db: &Q::DynDb, + _db: &>::DynDb, index: DatabaseKeyIndex, fmt: &mut std::fmt::Formatter<'_>, ) -> std::fmt::Result { @@ -78,7 +78,7 @@ where fn maybe_changed_since( &self, - db: &Q::DynDb, + db: &>::DynDb, input: DatabaseKeyIndex, revision: Revision, ) -> bool { @@ -96,7 +96,7 @@ where fn try_fetch( &self, - db: &Q::DynDb, + db: &>::DynDb, key: &Q::Key, ) -> Result> { let slot = self @@ -115,14 +115,14 @@ where Ok(value) } - fn durability(&self, _db: &Q::DynDb, key: &Q::Key) -> Durability { + fn durability(&self, _db: &>::DynDb, key: &Q::Key) -> Durability { match self.slot(key) { Some(slot) => slot.stamped_value.read().durability, None => panic!("no value set for {:?}({:?})", Q::default(), key), } } - fn entries(&self, _db: &Q::DynDb) -> C + fn entries(&self, _db: &>::DynDb) -> C where C: std::iter::FromIterator>, { @@ -143,7 +143,7 @@ impl Slot where Q: Query, { - fn maybe_changed_since(&self, _db: &Q::DynDb, revision: Revision) -> bool { + fn maybe_changed_since(&self, _db: &>::DynDb, revision: Revision) -> bool { debug!( "maybe_changed_since(slot={:?}, revision={:?})", self, revision, @@ -171,7 +171,13 @@ impl InputQueryStorageOps for InputStorage where Q: Query, { - fn set(&self, db: &mut Q::DynDb, key: &Q::Key, value: Q::Value, durability: Durability) { + fn set( + &self, + db: &mut >::DynDb, + key: &Q::Key, + value: Q::Value, + durability: Durability, + ) { log::debug!( "{:?}({:?}) = {:?} ({:?})", Q::default(), @@ -257,7 +263,7 @@ where #[allow(dead_code)] fn check_static() where - Q: Query, + Q: Query + 'static, Q::Key: 'static, Q::Value: 'static, { diff --git a/src/interned.rs b/src/interned.rs index ab1c5f30..74073cc5 100644 --- a/src/interned.rs +++ b/src/interned.rs @@ -6,7 +6,7 @@ use crate::plumbing::QueryStorageMassOps; use crate::plumbing::QueryStorageOps; use crate::revision::Revision; use crate::Query; -use crate::{CycleError, Database, DatabaseKeyIndex, DiscardIf, Runtime, SweepStrategy}; +use crate::{CycleError, Database, DatabaseKeyIndex, DiscardIf, QueryDb, Runtime, SweepStrategy}; use crossbeam_utils::atomic::AtomicCell; use parking_lot::RwLock; use rustc_hash::FxHashMap; @@ -35,13 +35,6 @@ where Q: Query, Q::Key: InternKey, Q::Value: Eq + Hash, - IQ: Query< - Key = Q::Value, - Value = Q::Key, - Group = Q::Group, - DynDb = Q::DynDb, - GroupStorage = Q::GroupStorage, - >, { phantom: std::marker::PhantomData<(Q::Key, IQ)>, } @@ -186,7 +179,7 @@ where /// In either case, the `accessed_at` field of the slot is updated /// to the current revision, ensuring that the slot cannot be GC'd /// while the current queries execute. - fn intern_index(&self, db: &Q::DynDb, key: &Q::Key) -> Arc> { + fn intern_index(&self, db: &>::DynDb, key: &Q::Key) -> Arc> { if let Some(i) = self.intern_check(db, key) { return i; } @@ -268,7 +261,11 @@ where slot } - fn intern_check(&self, db: &Q::DynDb, key: &Q::Key) -> Option>> { + fn intern_check( + &self, + db: &>::DynDb, + key: &Q::Key, + ) -> Option>> { let revision_now = db.salsa_runtime().current_revision(); let slot = self.tables.read().slot_for_key(key, revision_now)?; Some(slot) @@ -276,7 +273,7 @@ where /// Given an index, lookup and clone its value, updating the /// `accessed_at` time if necessary. - fn lookup_value(&self, db: &Q::DynDb, index: InternId) -> Arc> { + fn lookup_value(&self, db: &>::DynDb, index: InternId) -> Arc> { let revision_now = db.salsa_runtime().current_revision(); self.tables.read().slot_for_index(index, revision_now) } @@ -296,7 +293,7 @@ where fn fmt_index( &self, - db: &Q::DynDb, + db: &>::DynDb, index: DatabaseKeyIndex, fmt: &mut std::fmt::Formatter<'_>, ) -> std::fmt::Result { @@ -309,7 +306,7 @@ where fn maybe_changed_since( &self, - db: &Q::DynDb, + db: &>::DynDb, input: DatabaseKeyIndex, revision: Revision, ) -> bool { @@ -322,7 +319,7 @@ where fn try_fetch( &self, - db: &Q::DynDb, + db: &>::DynDb, key: &Q::Key, ) -> Result> { let slot = self.intern_index(db, key); @@ -336,11 +333,11 @@ where Ok(::from_intern_id(index)) } - fn durability(&self, _db: &Q::DynDb, _key: &Q::Key) -> Durability { + fn durability(&self, _db: &>::DynDb, _key: &Q::Key) -> Durability { INTERN_DURABILITY } - fn entries(&self, _db: &Q::DynDb) -> C + fn entries(&self, _db: &>::DynDb) -> C where C: std::iter::FromIterator>, { @@ -412,19 +409,46 @@ where } } +// Workaround for +// ``` +// IQ: for<'d> QueryDb< +// 'd, +// DynDb = >::DynDb, +// Group = >::Group, +// GroupStorage = >::GroupStorage, +// >, +// ``` +// not working to make rustc know DynDb, Group and GroupStorage being the same in `Q` and `IQ` +#[doc(hidden)] +pub trait EqualDynDb<'d, IQ>: QueryDb<'d> +where + IQ: QueryDb<'d>, +{ + fn convert_db(d: &Self::DynDb) -> &IQ::DynDb; + fn convert_group_storage(d: &Self::GroupStorage) -> &IQ::GroupStorage; +} + +impl<'d, IQ, Q> EqualDynDb<'d, IQ> for Q +where + Q: QueryDb<'d, DynDb = IQ::DynDb, Group = IQ::Group, GroupStorage = IQ::GroupStorage>, + Q::DynDb: HasQueryGroup, + IQ: QueryDb<'d>, +{ + fn convert_db(d: &Self::DynDb) -> &IQ::DynDb { + d + } + fn convert_group_storage(d: &Self::GroupStorage) -> &IQ::GroupStorage { + d + } +} + impl QueryStorageOps for LookupInternedStorage where Q: Query, Q::Key: InternKey, Q::Value: Eq + Hash, - IQ: Query< - Key = Q::Value, - Value = Q::Key, - Storage = InternedStorage, - Group = Q::Group, - DynDb = Q::DynDb, - GroupStorage = Q::GroupStorage, - >, + IQ: Query>, + for<'d> Q: EqualDynDb<'d, IQ>, { fn new(_group_index: u16) -> Self { LookupInternedStorage { @@ -434,35 +458,38 @@ where fn fmt_index( &self, - db: &Q::DynDb, + db: &>::DynDb, index: DatabaseKeyIndex, fmt: &mut std::fmt::Formatter<'_>, ) -> std::fmt::Result { - let group_storage = >::group_storage(db); - let interned_storage = IQ::query_storage(group_storage); - interned_storage.fmt_index(db, index, fmt) + let group_storage = + <>::DynDb as HasQueryGroup>::group_storage(db); + let interned_storage = IQ::query_storage(Q::convert_group_storage(group_storage)); + interned_storage.fmt_index(Q::convert_db(db), index, fmt) } fn maybe_changed_since( &self, - db: &Q::DynDb, + db: &>::DynDb, input: DatabaseKeyIndex, revision: Revision, ) -> bool { - let group_storage = >::group_storage(db); - let interned_storage = IQ::query_storage(group_storage); - interned_storage.maybe_changed_since(db, input, revision) + let group_storage = + <>::DynDb as HasQueryGroup>::group_storage(db); + let interned_storage = IQ::query_storage(Q::convert_group_storage(group_storage)); + interned_storage.maybe_changed_since(Q::convert_db(db), input, revision) } fn try_fetch( &self, - db: &Q::DynDb, + db: &>::DynDb, key: &Q::Key, ) -> Result> { let index = key.as_intern_id(); - let group_storage = >::group_storage(db); - let interned_storage = IQ::query_storage(group_storage); - let slot = interned_storage.lookup_value(db, index); + let group_storage = + <>::DynDb as HasQueryGroup>::group_storage(db); + let interned_storage = IQ::query_storage(Q::convert_group_storage(group_storage)); + let slot = interned_storage.lookup_value(Q::convert_db(db), index); let value = slot.value.clone(); let interned_at = slot.interned_at; db.salsa_runtime().report_query_read( @@ -473,16 +500,17 @@ where Ok(value) } - fn durability(&self, _db: &Q::DynDb, _key: &Q::Key) -> Durability { + fn durability(&self, _db: &>::DynDb, _key: &Q::Key) -> Durability { INTERN_DURABILITY } - fn entries(&self, db: &Q::DynDb) -> C + fn entries(&self, db: &>::DynDb) -> C where C: std::iter::FromIterator>, { - let group_storage = >::group_storage(db); - let interned_storage = IQ::query_storage(group_storage); + let group_storage = + <>::DynDb as HasQueryGroup>::group_storage(db); + let interned_storage = IQ::query_storage(Q::convert_group_storage(group_storage)); let tables = interned_storage.tables.read(); tables .map @@ -499,13 +527,7 @@ where Q: Query, Q::Key: InternKey, Q::Value: Eq + Hash, - IQ: Query< - Key = Q::Value, - Value = Q::Key, - Group = Q::Group, - DynDb = Q::DynDb, - GroupStorage = Q::GroupStorage, - >, + IQ: Query, { fn sweep(&self, _: &Runtime, _strategy: SweepStrategy) {} fn purge(&self) {} diff --git a/src/lib.rs b/src/lib.rs index 6c175fde..47a0849e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -45,7 +45,7 @@ pub use crate::storage::Storage; /// The base trait which your "query context" must implement. Gives /// access to the salsa runtime, which you must embed into your query /// context (along with whatever other state you may require). -pub trait Database: 'static + plumbing::DatabaseOps { +pub trait Database: plumbing::DatabaseOps { /// Iterates through all query storage and removes any values that /// have not been used since the last revision was created. The /// intended use-cycle is that you first execute all of your @@ -421,7 +421,22 @@ where /// Trait implements by all of the "special types" associated with /// each of your queries. -pub trait Query: Debug + Default + Sized + 'static { +/// +/// Base trait of `Query` that has a lifetime parameter to allow the `DynDb` to be non-'static. +pub trait QueryDb<'d>: Sized { + /// Dyn version of the associated trait for this query group. + type DynDb: ?Sized + Database + HasQueryGroup + 'd; + + /// Associate query group struct. + type Group: plumbing::QueryGroup; + + /// Generated struct that contains storage for all queries in a group. + type GroupStorage; +} + +/// Trait implements by all of the "special types" associated with +/// each of your queries. +pub trait Query: Debug + Default + Sized + for<'d> QueryDb<'d> { /// Type that you you give as a parameter -- for queries with zero /// or more than one input, this will be a tuple. type Key: Clone + Debug + Hash + Eq; @@ -430,16 +445,8 @@ pub trait Query: Debug + Default + Sized + 'static { type Value: Clone + Debug; /// Internal struct storing the values for the query. - type Storage: plumbing::QueryStorageOps; - - /// Associate query group struct. - type Group: plumbing::QueryGroup; - - /// Generated struct that contains storage for all queries in a group. - type GroupStorage; - - /// Dyn version of the associated trait for this query group. - type DynDb: ?Sized + Database + HasQueryGroup; + // type Storage: plumbing::QueryStorageOps; + type Storage; /// A unique index identifying this query within the group. const QUERY_INDEX: u16; @@ -448,7 +455,9 @@ pub trait Query: Debug + Default + Sized + 'static { const QUERY_NAME: &'static str; /// Extact storage for this query from the storage for its group. - fn query_storage(group_storage: &Self::GroupStorage) -> &Arc; + fn query_storage<'a>( + group_storage: &'a >::GroupStorage, + ) -> &'a Arc; } /// Return value from [the `query` method] on `Database`. @@ -457,18 +466,19 @@ pub trait Query: Debug + Default + Sized + 'static { /// [the `query` method]: trait.Database.html#method.query pub struct QueryTable<'me, Q> where - Q: Query + 'me, + Q: Query, { - db: &'me Q::DynDb, + db: &'me >::DynDb, storage: &'me Q::Storage, } impl<'me, Q> QueryTable<'me, Q> where Q: Query, + Q::Storage: QueryStorageOps, { /// Constructs a new `QueryTable`. - pub fn new(db: &'me Q::DynDb, storage: &'me Q::Storage) -> Self { + pub fn new(db: &'me >::DynDb, storage: &'me Q::Storage) -> Self { Self { db, storage } } @@ -514,7 +524,7 @@ pub struct QueryTableMut<'me, Q> where Q: Query + 'me, { - db: &'me mut Q::DynDb, + db: &'me mut >::DynDb, storage: Arc, } @@ -523,7 +533,7 @@ where Q: Query, { /// Constructs a new `QueryTableMut`. - pub fn new(db: &'me mut Q::DynDb, storage: Arc) -> Self { + pub fn new(db: &'me mut >::DynDb, storage: Arc) -> Self { Self { db, storage } } diff --git a/src/plumbing.rs b/src/plumbing.rs index 50532b85..06aad2cc 100644 --- a/src/plumbing.rs +++ b/src/plumbing.rs @@ -17,7 +17,7 @@ pub use crate::derived::MemoizedStorage; pub use crate::input::InputStorage; pub use crate::interned::InternedStorage; pub use crate::interned::LookupInternedStorage; -pub use crate::{revision::Revision, DatabaseKeyIndex, Runtime}; +pub use crate::{revision::Revision, DatabaseKeyIndex, QueryDb, Runtime}; #[derive(Clone, Debug)] pub struct CycleDetected { @@ -72,10 +72,10 @@ pub trait QueryStorageMassOps { pub trait DatabaseKey: Clone + Debug + Eq + Hash {} pub trait QueryFunction: Query { - fn execute(db: &Self::DynDb, key: Self::Key) -> Self::Value; + fn execute(db: &>::DynDb, key: Self::Key) -> Self::Value; fn recover( - db: &Self::DynDb, + db: &>::DynDb, cycle: &[DatabaseKeyIndex], key: &Self::Key, ) -> Option { @@ -86,9 +86,10 @@ pub trait QueryFunction: Query { /// Create a query table, which has access to the storage for the query /// and offers methods like `get`. -pub fn get_query_table(db: &Q::DynDb) -> QueryTable<'_, Q> +pub fn get_query_table<'me, Q>(db: &'me >::DynDb) -> QueryTable<'me, Q> where - Q: Query, + Q: Query + 'me, + Q::Storage: QueryStorageOps, { let group_storage: &Q::GroupStorage = HasQueryGroup::group_storage(db); let query_storage: &Q::Storage = Q::query_storage(group_storage); @@ -97,7 +98,7 @@ where /// Create a mutable query table, which has access to the storage /// for the query and offers methods like `set`. -pub fn get_query_table_mut(db: &mut Q::DynDb) -> QueryTableMut<'_, Q> +pub fn get_query_table_mut<'me, Q>(db: &'me mut >::DynDb) -> QueryTableMut<'me, Q> where Q: Query, { @@ -133,7 +134,7 @@ where /// Format a database key index in a suitable way. fn fmt_index( &self, - db: &Q::DynDb, + db: &>::DynDb, index: DatabaseKeyIndex, fmt: &mut std::fmt::Formatter<'_>, ) -> std::fmt::Result; @@ -142,7 +143,7 @@ where /// changed since the given revision. fn maybe_changed_since( &self, - db: &Q::DynDb, + db: &>::DynDb, input: DatabaseKeyIndex, revision: Revision, ) -> bool; @@ -156,15 +157,15 @@ where /// itself. fn try_fetch( &self, - db: &Q::DynDb, + db: &>::DynDb, key: &Q::Key, ) -> Result>; /// Returns the durability associated with a given key. - fn durability(&self, db: &Q::DynDb, key: &Q::Key) -> Durability; + fn durability(&self, db: &>::DynDb, key: &Q::Key) -> Durability; /// Get the (current) set of the entries in the query storage - fn entries(&self, db: &Q::DynDb) -> C + fn entries(&self, db: &>::DynDb) -> C where C: std::iter::FromIterator>; } @@ -176,7 +177,13 @@ pub trait InputQueryStorageOps where Q: Query, { - fn set(&self, db: &mut Q::DynDb, key: &Q::Key, new_value: Q::Value, durability: Durability); + fn set( + &self, + db: &mut >::DynDb, + key: &Q::Key, + new_value: Q::Value, + durability: Durability, + ); } /// An optional trait that is implemented for "user mutable" storage: @@ -190,5 +197,5 @@ pub trait DerivedQueryStorageOps where Q: Query, { - fn invalidate(&self, db: &mut Q::DynDb, key: &Q::Key); + fn invalidate(&self, db: &mut >::DynDb, key: &Q::Key); }