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 your application but aren't ordinarily needed.
use crate::plumbing;
use crate::plumbing::QueryStorageOps;
use crate::Database;
use crate::Query;
@ -27,7 +28,7 @@ pub trait DebugQueryTable {
impl<DB, Q> DebugQueryTable for QueryTable<'_, DB, Q>
where
DB: Database,
DB: plumbing::GetQueryTable<Q>,
Q: Query<DB>,
{
type Key = Q::Key;

View file

@ -351,17 +351,16 @@ pub trait Query<DB: Database>: Debug + Default + Sized + 'static {
#[derive(new)]
pub struct QueryTable<'me, DB, Q>
where
DB: Database,
DB: plumbing::GetQueryTable<Q>,
Q: Query<DB> + 'me,
{
db: &'me DB,
storage: &'me Q::Storage,
descriptor_fn: fn(&DB, &Q::Key) -> DB::QueryDescriptor,
}
impl<DB, Q> QueryTable<'_, DB, Q>
where
DB: Database,
DB: plumbing::GetQueryTable<Q>,
Q: Query<DB>,
{
/// 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 {
(self.descriptor_fn)(self.db, key)
<DB as plumbing::GetQueryTable<Q>>::descriptor(&self.db, key.clone())
}
}
@ -399,21 +398,20 @@ where
#[derive(new)]
pub struct QueryTableMut<'me, DB, Q>
where
DB: Database,
DB: plumbing::GetQueryTable<Q>,
Q: Query<DB> + 'me,
{
db: &'me DB,
storage: &'me Q::Storage,
descriptor_fn: fn(&DB, &Q::Key) -> DB::QueryDescriptor,
}
impl<DB, Q> QueryTableMut<'_, DB, Q>
where
DB: Database,
DB: plumbing::GetQueryTable<Q>,
Q: Query<DB>,
{
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
@ -885,12 +883,6 @@ macro_rules! database_storage {
&$crate::Database::salsa_runtime(db)
.storage()
.$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)
.storage()
.$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;
}
/// 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 {
/// 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>;
/// 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>;
/// 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