add transparent storage and ability to select it in macro

This commit is contained in:
Niko Matsakis 2018-09-29 04:27:27 -04:00
parent ed92e0f408
commit fe21e28b8c
2 changed files with 137 additions and 5 deletions

View file

@ -23,6 +23,7 @@ use std::hash::Hash;
pub mod dyn_descriptor;
pub mod memoized;
pub mod transparent;
pub trait BaseQueryContext: Sized {
/// A "query descriptor" packages up all the possible queries and a key.
@ -167,13 +168,79 @@ macro_rules! query_prototype {
/// trait.
#[macro_export]
macro_rules! query_definition {
// Step 1. Filtering the attributes to look for the special ones
// we consume.
(
$(#[$attr:meta])*
$v:vis $name:ident($query:tt : &impl $query_trait:path, $key:tt : $key_ty:ty) -> $value_ty:ty {
@filter_attrs {
input { #[storage(memoized)] $(#[$attr:meta])* };
storage { $storage:tt };
other_attrs { $($other_attrs:tt)* };
tokens { $($tokens:tt)* };
}
) => {
$crate::query_definition! {
@filter_attrs {
input { $(#[$attr])* };
storage { memoized };
other_attrs { $($other_attrs)* };
tokens { $($tokens)* };
}
}
};
(
@filter_attrs {
input { #[storage(transparent)] $(#[$attr:meta])* };
storage { $storage:tt };
other_attrs { $($other_attrs:tt)* };
tokens { $($tokens:tt)* };
}
) => {
$crate::query_definition! {
@filter_attrs {
input { $(#[$attr])* };
storage { transparent };
other_attrs { $($other_attrs)* };
tokens { $($tokens)* };
}
}
};
(
@filter_attrs {
input { #[$attr:meta] $(#[$attrs:meta])* };
storage { $storage:tt };
other_attrs { $($other_attrs:tt)* };
tokens { $($tokens:tt)* };
}
) => {
$crate::query_definition! {
@filter_attrs {
input { $(#[$attrs])* };
storage { $storage };
other_attrs { $($other_attrs)* #[$attr] };
tokens { $($tokens)* };
}
}
};
(
@filter_attrs {
input { };
storage { $storage:tt };
other_attrs { $($attrs:tt)* };
tokens {
$v:vis $name:ident(
$query:tt : &impl $query_trait:path,
$key:tt : $key_ty:ty $(,)*
) -> $value_ty:ty {
$($body:tt)*
}
};
}
) => {
#[derive(Default, Debug)]
$(#[$attrs])*
$v struct $name;
impl<QC> $crate::Query<QC> for $name
@ -182,13 +249,38 @@ macro_rules! query_definition {
{
type Key = $key_ty;
type Value = $value_ty;
type Storage = $crate::memoized::MemoizedStorage<QC, Self>;
type Storage = $crate::query_definition! { @storage_ty[QC, Self, $storage] };
fn execute($query: &QC, $key: $key_ty) -> $value_ty {
$($body)*
}
}
};
(
@storage_ty[$QC:ident, $Self:ident, memoized]
) => {
$crate::memoized::MemoizedStorage<$QC, $Self>
};
(
@storage_ty[$QC:ident, $Self:ident, transparent]
) => {
$crate::transparent::TransparentStorage
};
(
$(#[$attr:meta])* $($tokens:tt)*
) => {
$crate::query_definition! {
@filter_attrs {
input { $(#[$attr])* };
storage { memoized };
other_attrs { };
tokens { $($tokens)* };
}
}
};
}
#[macro_export]

40
src/transparent.rs Normal file
View file

@ -0,0 +1,40 @@
use crate::BaseQueryContext;
use crate::CycleDetected;
use crate::Query;
use crate::QueryStorageOps;
use crate::QueryTable;
use parking_lot::{RwLock, RwLockUpgradableReadGuard};
use rustc_hash::FxHashMap;
use std::any::Any;
use std::cell::RefCell;
use std::collections::hash_map::Entry;
use std::fmt::Debug;
use std::fmt::Display;
use std::fmt::Write;
use std::hash::Hash;
// The master implementation that knits together all the queries
// contains a certain amount of boilerplate. This file aims to
// reduce that.
#[derive(Default)]
pub struct TransparentStorage;
impl<QC, Q> QueryStorageOps<QC, Q> for TransparentStorage
where
Q: Query<QC>,
QC: BaseQueryContext,
{
fn try_fetch<'q>(
&self,
query: &'q QC,
key: &Q::Key,
descriptor: impl FnOnce() -> QC::QueryDescriptor,
) -> Result<Q::Value, CycleDetected> {
// FIXME: Should we even call `execute_query_implementation`
// here? Or should we just call `Q::execute`, and maybe
// separate out the `push`/`pop` operations.
let descriptor = descriptor();
Ok(query.execute_query_implementation::<Q>(descriptor, key))
}
}