Merge pull request #95 from nikomatsakis/no-dynamic-dispatch

No dynamic dispatch for constructing query descriptors
This commit is contained in:
Niko Matsakis 2018-12-13 06:20:24 -05:00 committed by GitHub
commit 31789ec7ef
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 34 additions and 21 deletions

View file

@ -1,6 +1,7 @@
//! Debugging APIs: these are meant for use when unit-testing or //! Debugging APIs: these are meant for use when unit-testing or
//! debugging your application but aren't ordinarily needed. //! debugging your application but aren't ordinarily needed.
use crate::plumbing;
use crate::plumbing::QueryStorageOps; use crate::plumbing::QueryStorageOps;
use crate::Database; use crate::Database;
use crate::Query; use crate::Query;
@ -27,7 +28,7 @@ pub trait DebugQueryTable {
impl<DB, Q> DebugQueryTable for QueryTable<'_, DB, Q> impl<DB, Q> DebugQueryTable for QueryTable<'_, DB, Q>
where where
DB: Database, DB: plumbing::GetQueryTable<Q>,
Q: Query<DB>, Q: Query<DB>,
{ {
type Key = Q::Key; type Key = Q::Key;

View file

@ -351,17 +351,16 @@ pub trait Query<DB: Database>: Debug + Default + Sized + 'static {
#[derive(new)] #[derive(new)]
pub struct QueryTable<'me, DB, Q> pub struct QueryTable<'me, DB, Q>
where where
DB: Database, DB: plumbing::GetQueryTable<Q>,
Q: Query<DB> + 'me, Q: Query<DB> + 'me,
{ {
db: &'me DB, db: &'me DB,
storage: &'me Q::Storage, storage: &'me Q::Storage,
descriptor_fn: fn(&DB, &Q::Key) -> DB::QueryDescriptor,
} }
impl<DB, Q> QueryTable<'_, DB, Q> impl<DB, Q> QueryTable<'_, DB, Q>
where where
DB: Database, DB: plumbing::GetQueryTable<Q>,
Q: Query<DB>, Q: Query<DB>,
{ {
/// Execute the query on a given input. Usually it's easier to /// Execute the query on a given input. Usually it's easier to
@ -387,7 +386,7 @@ where
} }
fn descriptor(&self, key: &Q::Key) -> DB::QueryDescriptor { fn descriptor(&self, key: &Q::Key) -> DB::QueryDescriptor {
(self.descriptor_fn)(self.db, key) <DB as plumbing::GetQueryTable<Q>>::descriptor(&self.db, key.clone())
} }
} }
@ -399,21 +398,20 @@ where
#[derive(new)] #[derive(new)]
pub struct QueryTableMut<'me, DB, Q> pub struct QueryTableMut<'me, DB, Q>
where where
DB: Database, DB: plumbing::GetQueryTable<Q>,
Q: Query<DB> + 'me, Q: Query<DB> + 'me,
{ {
db: &'me DB, db: &'me DB,
storage: &'me Q::Storage, storage: &'me Q::Storage,
descriptor_fn: fn(&DB, &Q::Key) -> DB::QueryDescriptor,
} }
impl<DB, Q> QueryTableMut<'_, DB, Q> impl<DB, Q> QueryTableMut<'_, DB, Q>
where where
DB: Database, DB: plumbing::GetQueryTable<Q>,
Q: Query<DB>, Q: Query<DB>,
{ {
fn descriptor(&self, key: &Q::Key) -> DB::QueryDescriptor { fn descriptor(&self, key: &Q::Key) -> DB::QueryDescriptor {
(self.descriptor_fn)(self.db, key) <DB as plumbing::GetQueryTable<Q>>::descriptor(&self.db, key.clone())
} }
/// Assign a value to an "input query". Must be used outside of /// Assign a value to an "input query". Must be used outside of
@ -885,12 +883,6 @@ macro_rules! database_storage {
&$crate::Database::salsa_runtime(db) &$crate::Database::salsa_runtime(db)
.storage() .storage()
.$query_method, .$query_method,
|_, key| {
let key = std::clone::Clone::clone(key);
__SalsaQueryDescriptor {
kind: __SalsaQueryDescriptorKind::$query_method(key),
}
},
) )
} }
@ -903,14 +895,17 @@ macro_rules! database_storage {
&$crate::Database::salsa_runtime(db) &$crate::Database::salsa_runtime(db)
.storage() .storage()
.$query_method, .$query_method,
|_, key| {
let key = std::clone::Clone::clone(key);
__SalsaQueryDescriptor {
kind: __SalsaQueryDescriptorKind::$query_method(key),
}
},
) )
} }
fn descriptor(
db: &Self,
key: <$QueryType as $crate::Query<Self>>::Key,
) -> <Self as $crate::plumbing::DatabaseStorageTypes>::QueryDescriptor {
__SalsaQueryDescriptor {
kind: __SalsaQueryDescriptorKind::$query_method(key),
}
}
} }
)* )*
)* )*

View file

@ -58,10 +58,27 @@ pub trait QueryFunction<DB: Database>: Query<DB> {
fn execute(db: &DB, key: Self::Key) -> Self::Value; fn execute(db: &DB, key: Self::Key) -> Self::Value;
} }
/// The `GetQueryTable` trait makes the connection the *database type*
/// `DB` and some specific *query type* `Q` that it supports. Note
/// that the `Database` trait itself is not specific to any query, and
/// the impls of the query trait are not specific to any *database*
/// (in particular, query groups are defined without knowing the final
/// database type). This trait then serves to put the query in the
/// context of the full database. It gives access to the storage for
/// the query and also to creating the query descriptor. For any given
/// database, impls of this trait are created by the
/// `database_storage` macro.
pub trait GetQueryTable<Q: Query<Self>>: Database { pub trait GetQueryTable<Q: Query<Self>>: Database {
/// Create a query table, which has access to the storage for the query
/// and offers methods like `get`.
fn get_query_table(db: &Self) -> QueryTable<'_, Self, Q>; fn get_query_table(db: &Self) -> QueryTable<'_, Self, Q>;
/// Create a mutable query table, which has access to the storage
/// for the query and offers methods like `set`.
fn get_query_table_mut(db: &mut Self) -> QueryTableMut<'_, Self, Q>; fn get_query_table_mut(db: &mut Self) -> QueryTableMut<'_, Self, Q>;
/// Create a query descriptor given a key for this query.
fn descriptor(db: &Self, key: Q::Key) -> Self::QueryDescriptor;
} }
pub trait QueryStorageOps<DB, Q>: Default pub trait QueryStorageOps<DB, Q>: Default