mirror of
https://github.com/salsa-rs/salsa.git
synced 2025-02-02 09:46:06 +00:00
make query_prototype
also define queries, remove query_definition
This commit is contained in:
parent
cd5622c6de
commit
0ee6f3884d
10 changed files with 101 additions and 289 deletions
|
@ -34,7 +34,7 @@ Using salsa is as easy as 1, 2, 3...
|
||||||
and queries you will need. We'll start with one such trait, but
|
and queries you will need. We'll start with one such trait, but
|
||||||
later on you can use more than one to break up your system into
|
later on you can use more than one to break up your system into
|
||||||
components (or spread your code across crates).
|
components (or spread your code across crates).
|
||||||
2. **Implement the queries** using the `query_definition!` macro.
|
2. **Implement the query functions** where appropriate.
|
||||||
3. Define the **database struct**, which contains the storage for all
|
3. Define the **database struct**, which contains the storage for all
|
||||||
the inputs/queries you will be using. The query struct will contain
|
the inputs/queries you will be using. The query struct will contain
|
||||||
the storage for all of the inputs/queries and may also contain
|
the storage for all of the inputs/queries and may also contain
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::compiler;
|
use crate::compiler;
|
||||||
use salsa::{query_definition, query_prototype};
|
use salsa::query_prototype;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
query_prototype! {
|
query_prototype! {
|
||||||
|
@ -24,20 +24,20 @@ query_prototype! {
|
||||||
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
|
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
|
||||||
pub struct DefId(usize);
|
pub struct DefId(usize);
|
||||||
|
|
||||||
query_definition! {
|
impl<DB: ClassTableDatabase> salsa::QueryFunction<DB> for AllClasses {
|
||||||
pub AllClasses(_: &impl ClassTableDatabase, (): ()) -> Arc<Vec<DefId>> {
|
fn execute(_: &DB, (): ()) -> Arc<Vec<DefId>> {
|
||||||
Arc::new(vec![DefId(0), DefId(10)]) // dummy impl
|
Arc::new(vec![DefId(0), DefId(10)]) // dummy impl
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
query_definition! {
|
impl<DB: ClassTableDatabase> salsa::QueryFunction<DB> for Fields {
|
||||||
pub Fields(_: &impl ClassTableDatabase, class: DefId) -> Arc<Vec<DefId>> {
|
fn execute(_: &DB, class: DefId) -> Arc<Vec<DefId>> {
|
||||||
Arc::new(vec![DefId(class.0 + 1), DefId(class.0 + 2)]) // dummy impl
|
Arc::new(vec![DefId(class.0 + 1), DefId(class.0 + 2)]) // dummy impl
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
query_definition! {
|
impl<DB: ClassTableDatabase> salsa::QueryFunction<DB> for AllFields {
|
||||||
pub AllFields(db: &impl ClassTableDatabase, (): ()) -> Arc<Vec<DefId>> {
|
fn execute(db: &DB, (): ()) -> Arc<Vec<DefId>> {
|
||||||
Arc::new(
|
Arc::new(
|
||||||
db.all_classes(())
|
db.all_classes(())
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -45,8 +45,7 @@ query_definition! {
|
||||||
.flat_map(|def_id| {
|
.flat_map(|def_id| {
|
||||||
let fields = db.fields(def_id);
|
let fields = db.fields(def_id);
|
||||||
(0..fields.len()).map(move |i| fields[i])
|
(0..fields.len()).map(move |i| fields[i])
|
||||||
})
|
}).collect(),
|
||||||
.collect()
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,18 +20,24 @@ example. It defines exactly two queries: `input_string` and
|
||||||
names of the queries as methods (e.g., `input_string()`) and also a
|
names of the queries as methods (e.g., `input_string()`) and also a
|
||||||
path to a type that will define the query (`InputString`). It doesn't
|
path to a type that will define the query (`InputString`). It doesn't
|
||||||
give many other details: those are specified in the query definition
|
give many other details: those are specified in the query definition
|
||||||
that comes later.
|
that comes later. XXX out of date
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
salsa::query_prototype! {
|
salsa::query_prototype! {
|
||||||
trait HelloWorldDatabase: salsa::Database {
|
trait HelloWorldDatabase: salsa::Database {
|
||||||
fn input_string() for InputString;
|
fn input_string(key: ()) -> Arc<String> {
|
||||||
fn length() for Length;
|
type InputString;
|
||||||
|
storage input;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn length(key: ()) -> usize {
|
||||||
|
type Length;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Step 2: Define the queries
|
### Step 2: Define the query bodies
|
||||||
|
|
||||||
The actual query definitions are made using the
|
The actual query definitions are made using the
|
||||||
`salsa::query_definition` macro. For an **input query**, such as
|
`salsa::query_definition` macro. For an **input query**, such as
|
||||||
|
|
|
@ -13,7 +13,9 @@ salsa::query_prototype! {
|
||||||
trait HelloWorldDatabase: salsa::Database {
|
trait HelloWorldDatabase: salsa::Database {
|
||||||
fn input_string(key: ()) -> Arc<String> {
|
fn input_string(key: ()) -> Arc<String> {
|
||||||
type InputString;
|
type InputString;
|
||||||
|
storage input;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn length(key: ()) -> usize {
|
fn length(key: ()) -> usize {
|
||||||
type Length;
|
type Length;
|
||||||
}
|
}
|
||||||
|
@ -23,21 +25,14 @@ salsa::query_prototype! {
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// Step 2. Define the queries.
|
// Step 2. Define the queries.
|
||||||
|
|
||||||
// Define an **input query**. Like all queries, it is a map from a key
|
|
||||||
// (of type `()`) to a value (of type `Arc<String>`). All values begin
|
|
||||||
// as `Default::default` but you can assign them new values.
|
|
||||||
salsa::query_definition! {
|
|
||||||
InputString: Map<(), Arc<String>>;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Define a **function query**. It too has a key and value type, but
|
// Define a **function query**. It too has a key and value type, but
|
||||||
// it is defined with a function that -- given the key -- computes the
|
// it is defined with a function that -- given the key -- computes the
|
||||||
// value. This function is supplied with a context (an `&impl
|
// value. This function is supplied with a context (an `&impl
|
||||||
// HelloWorldDatabase`) that gives access to other queries. The runtime
|
// HelloWorldDatabase`) that gives access to other queries. The runtime
|
||||||
// will track which queries you use so that we can incrementally
|
// will track which queries you use so that we can incrementally
|
||||||
// update memoized results.
|
// update memoized results.
|
||||||
salsa::query_definition! {
|
impl<DB: HelloWorldDatabase> salsa::QueryFunction<DB> for Length {
|
||||||
Length(db: &impl HelloWorldDatabase, _key: ()) -> usize {
|
fn execute(db: &DB, _key: ()) -> usize {
|
||||||
// Read the input string:
|
// Read the input string:
|
||||||
let input_string = db.input_string(());
|
let input_string = db.input_string(());
|
||||||
|
|
||||||
|
|
249
src/lib.rs
249
src/lib.rs
|
@ -208,14 +208,14 @@ impl DefaultKey for () {
|
||||||
/// queries need to execute, as well as defining the queries
|
/// queries need to execute, as well as defining the queries
|
||||||
/// themselves that are exported for others to use.
|
/// themselves that are exported for others to use.
|
||||||
///
|
///
|
||||||
/// This macro declares the "prototype" for a single query. This will
|
/// This macro declares the "prototype" for a group of queries. It will
|
||||||
/// expand into a `fn` item. This prototype specifies name of the
|
/// expand into a trait and a set of structs, one per query.
|
||||||
/// method (in the example below, that would be `my_query`) and
|
///
|
||||||
/// connects it to query definition type (`MyQuery`, in the example
|
/// For each query, you give the name of the accessor method to invoke
|
||||||
/// below). These typically have the same name but a distinct
|
/// the query (e.g., `my_query`, below), as well as its input/output
|
||||||
/// capitalization convention. Note that the actual input/output type
|
/// types. You also give the name for a query type (e.g., `MyQuery`,
|
||||||
/// of the query are given only in the query definition (see the
|
/// below) that represents the query, and optionally other details,
|
||||||
/// `query_definition` macro for more details).
|
/// such as its storage.
|
||||||
///
|
///
|
||||||
/// ### Examples
|
/// ### Examples
|
||||||
///
|
///
|
||||||
|
@ -225,26 +225,10 @@ impl DefaultKey for () {
|
||||||
/// trait TypeckDatabase {
|
/// trait TypeckDatabase {
|
||||||
/// query_prototype! {
|
/// query_prototype! {
|
||||||
/// /// Comments or other attributes can go here
|
/// /// Comments or other attributes can go here
|
||||||
/// fn my_query() for MyQuery;
|
/// fn my_query(input: u32) -> u64 {
|
||||||
/// }
|
/// type MyQuery;
|
||||||
/// }
|
/// storage memoized; // optional, this is the default
|
||||||
/// ```
|
/// }
|
||||||
///
|
|
||||||
/// This just expands to something like:
|
|
||||||
///
|
|
||||||
/// ```ignore
|
|
||||||
/// fn my_query(&self) -> QueryTable<'_, Self, $query_type>;
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// This permits us to invoke the query via `query.my_query().of(key)`.
|
|
||||||
///
|
|
||||||
/// You can also include more than one query if you prefer:
|
|
||||||
///
|
|
||||||
/// ```ignore
|
|
||||||
/// trait TypeckDatabase {
|
|
||||||
/// query_prototype! {
|
|
||||||
/// fn my_query() for MyQuery;
|
|
||||||
/// fn my_other_query() for MyOtherQuery;
|
|
||||||
/// }
|
/// }
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
@ -273,25 +257,40 @@ macro_rules! query_prototype {
|
||||||
// Base case: found the trait body
|
// Base case: found the trait body
|
||||||
(
|
(
|
||||||
attr[$($trait_attr:tt)*];
|
attr[$($trait_attr:tt)*];
|
||||||
headers[$v:vis, $name:ident, $($header:tt)*];
|
headers[$v:vis, $query_trait:ident, $($header:tt)*];
|
||||||
tokens[{
|
tokens[{
|
||||||
$(
|
$(
|
||||||
$(#[$method_attr:meta])*
|
$(#[$method_attr:meta])*
|
||||||
fn $method_name:ident($key_name:ident: $key:ty) -> $value:ty {
|
fn $method_name:ident($key_name:ident: $key_ty:ty) -> $value_ty:ty {
|
||||||
type $QueryType:ty;
|
type $QueryType:ident;
|
||||||
|
$(storage $storage:ident;)* // FIXME(rust-lang/rust#48075) should be `?`
|
||||||
}
|
}
|
||||||
)*
|
)*
|
||||||
}];
|
}];
|
||||||
) => {
|
) => {
|
||||||
$($trait_attr)* $v trait $name: $($crate::GetQueryTable<$QueryType> +)* $($header)* {
|
$($trait_attr)* $v trait $query_trait: $($crate::GetQueryTable<$QueryType> +)* $($header)* {
|
||||||
$(
|
$(
|
||||||
$(#[$method_attr])*
|
$(#[$method_attr])*
|
||||||
fn $method_name(&self, key: $key) -> $value {
|
fn $method_name(&self, key: $key_ty) -> $value_ty {
|
||||||
<Self as $crate::GetQueryTable<$QueryType>>::get_query_table(self)
|
<Self as $crate::GetQueryTable<$QueryType>>::get_query_table(self)
|
||||||
.get(key)
|
.get(key)
|
||||||
}
|
}
|
||||||
)*
|
)*
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$(
|
||||||
|
#[derive(Default, Debug)]
|
||||||
|
$v struct $QueryType;
|
||||||
|
|
||||||
|
impl<DB> $crate::Query<DB> for $QueryType
|
||||||
|
where
|
||||||
|
DB: $query_trait,
|
||||||
|
{
|
||||||
|
type Key = $key_ty;
|
||||||
|
type Value = $value_ty;
|
||||||
|
type Storage = $crate::query_prototype! { @storage_ty[DB, Self, $($storage)*] };
|
||||||
|
}
|
||||||
|
)*
|
||||||
};
|
};
|
||||||
|
|
||||||
// Recursive case: found some more part of the trait header.
|
// Recursive case: found some more part of the trait header.
|
||||||
|
@ -307,143 +306,13 @@ macro_rules! query_prototype {
|
||||||
tokens[$($tokens)*];
|
tokens[$($tokens)*];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates a **Query Definition** type. This defines the input (key)
|
// Generate storage type
|
||||||
/// of the query, the output key (value), and the query context trait
|
|
||||||
/// that the query requires.
|
|
||||||
///
|
|
||||||
/// Example:
|
|
||||||
///
|
|
||||||
/// ```ignore
|
|
||||||
/// query_definition! {
|
|
||||||
/// pub MyQuery(db: &impl MyDatabase, key: MyKey) -> MyValue {
|
|
||||||
/// ... // fn body specifies what happens when query is invoked
|
|
||||||
/// }
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// Here, the query context trait would be `MyDatabase` -- this
|
|
||||||
/// should be a trait containing all the other queries that the
|
|
||||||
/// definition needs to invoke (as well as any other methods that you
|
|
||||||
/// may want).
|
|
||||||
///
|
|
||||||
/// The `MyKey` type is the **key** to the query -- it must be Clone,
|
|
||||||
/// Debug, Hash, Eq, and Send, as specified in the `Query` trait.
|
|
||||||
///
|
|
||||||
/// The `MyKey` type is the **value** to the query -- it too must be
|
|
||||||
/// Clone, Debug, Hash, Eq, and Send, as specified in the `Query`
|
|
||||||
/// trait.
|
|
||||||
#[macro_export]
|
|
||||||
macro_rules! query_definition {
|
|
||||||
// Step 1. Filtering the attributes to look for the special ones
|
|
||||||
// we consume.
|
|
||||||
(
|
(
|
||||||
@filter_attrs {
|
// Default case:
|
||||||
input { #[storage(memoized)] $($input:tt)* };
|
@storage_ty[$DB:ident, $Self:ident, ]
|
||||||
storage { $storage:tt };
|
|
||||||
other_attrs { $($other_attrs:tt)* };
|
|
||||||
}
|
|
||||||
) => {
|
) => {
|
||||||
$crate::query_definition! {
|
$crate::query_prototype! { @storage_ty[$DB, $Self, memoized] }
|
||||||
@filter_attrs {
|
|
||||||
input { $($input)* };
|
|
||||||
storage { memoized };
|
|
||||||
other_attrs { $($other_attrs)* };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
(
|
|
||||||
@filter_attrs {
|
|
||||||
input { #[storage(volatile)] $($input:tt)* };
|
|
||||||
storage { $storage:tt };
|
|
||||||
other_attrs { $($other_attrs:tt)* };
|
|
||||||
}
|
|
||||||
) => {
|
|
||||||
$crate::query_definition! {
|
|
||||||
@filter_attrs {
|
|
||||||
input { $($input)* };
|
|
||||||
storage { volatile };
|
|
||||||
other_attrs { $($other_attrs)* };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
(
|
|
||||||
@filter_attrs {
|
|
||||||
input { #[storage(dependencies)] $($input:tt)* };
|
|
||||||
storage { $storage:tt };
|
|
||||||
other_attrs { $($other_attrs:tt)* };
|
|
||||||
}
|
|
||||||
) => {
|
|
||||||
$crate::query_definition! {
|
|
||||||
@filter_attrs {
|
|
||||||
input { $($input)* };
|
|
||||||
storage { dependencies };
|
|
||||||
other_attrs { $($other_attrs)* };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
(
|
|
||||||
@filter_attrs {
|
|
||||||
input { #[$attr:meta] $($input:tt)* };
|
|
||||||
storage { $storage:tt };
|
|
||||||
other_attrs { $($other_attrs:tt)* };
|
|
||||||
}
|
|
||||||
) => {
|
|
||||||
$crate::query_definition! {
|
|
||||||
@filter_attrs {
|
|
||||||
input { $($input)* };
|
|
||||||
storage { $storage };
|
|
||||||
other_attrs { $($other_attrs)* #[$attr] };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Accept a "fn-like" query definition
|
|
||||||
(
|
|
||||||
@filter_attrs {
|
|
||||||
input {
|
|
||||||
$v:vis $name:ident(
|
|
||||||
$db:tt : &impl $query_trait:path,
|
|
||||||
$key:tt : $key_ty:ty $(,)*
|
|
||||||
) -> $value_ty:ty {
|
|
||||||
$($body:tt)*
|
|
||||||
}
|
|
||||||
};
|
|
||||||
storage { $storage:tt };
|
|
||||||
other_attrs { $($attrs:tt)* };
|
|
||||||
}
|
|
||||||
) => {
|
|
||||||
#[derive(Default, Debug)]
|
|
||||||
$($attrs)*
|
|
||||||
$v struct $name;
|
|
||||||
|
|
||||||
impl<DB> $crate::Query<DB> for $name
|
|
||||||
where
|
|
||||||
DB: $query_trait,
|
|
||||||
{
|
|
||||||
type Key = $key_ty;
|
|
||||||
type Value = $value_ty;
|
|
||||||
type Storage = $crate::query_definition! { @storage_ty[DB, Self, $storage] };
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<DB> $crate::QueryFunction<DB> for $name
|
|
||||||
where
|
|
||||||
DB: $query_trait,
|
|
||||||
{
|
|
||||||
fn execute($db: &DB, $key: $key_ty) -> $value_ty {
|
|
||||||
$($body)*
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
(
|
|
||||||
@storage_ty[$DB:ident, $Self:ident, default]
|
|
||||||
) => {
|
|
||||||
$crate::query_definition! { @storage_ty[$DB, $Self, memoized] }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
(
|
(
|
||||||
|
@ -464,52 +333,10 @@ macro_rules! query_definition {
|
||||||
$crate::dependencies::DependencyStorage<$DB, $Self>
|
$crate::dependencies::DependencyStorage<$DB, $Self>
|
||||||
};
|
};
|
||||||
|
|
||||||
// Accept a "field-like" query definition (input)
|
|
||||||
(
|
(
|
||||||
@filter_attrs {
|
@storage_ty[$DB:ident, $Self:ident, input]
|
||||||
input {
|
|
||||||
$v:vis $name:ident: Map<$key_ty:ty, $value_ty:ty>;
|
|
||||||
};
|
|
||||||
storage { default };
|
|
||||||
other_attrs { $($attrs:tt)* };
|
|
||||||
}
|
|
||||||
) => {
|
) => {
|
||||||
#[derive(Default, Debug)]
|
$crate::input::InputStorage<DB, Self>
|
||||||
$($attrs)*
|
|
||||||
$v struct $name;
|
|
||||||
|
|
||||||
impl<DB> $crate::Query<DB> for $name
|
|
||||||
where
|
|
||||||
DB: $crate::Database
|
|
||||||
{
|
|
||||||
type Key = $key_ty;
|
|
||||||
type Value = $value_ty;
|
|
||||||
type Storage = $crate::input::InputStorage<DB, Self>;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Various legal start states:
|
|
||||||
(
|
|
||||||
# $($tokens:tt)*
|
|
||||||
) => {
|
|
||||||
$crate::query_definition! {
|
|
||||||
@filter_attrs {
|
|
||||||
input { # $($tokens)* };
|
|
||||||
storage { default };
|
|
||||||
other_attrs { };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
(
|
|
||||||
$v:vis $name:ident $($tokens:tt)*
|
|
||||||
) => {
|
|
||||||
$crate::query_definition! {
|
|
||||||
@filter_attrs {
|
|
||||||
input { $v $name $($tokens)* };
|
|
||||||
storage { default };
|
|
||||||
other_attrs { };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,35 +33,35 @@ salsa::query_prototype! {
|
||||||
}
|
}
|
||||||
fn volatile_a(key: ()) -> () {
|
fn volatile_a(key: ()) -> () {
|
||||||
type VolatileA;
|
type VolatileA;
|
||||||
|
storage volatile;
|
||||||
}
|
}
|
||||||
fn volatile_b(key: ()) -> () {
|
fn volatile_b(key: ()) -> () {
|
||||||
type VolatileB;
|
type VolatileB;
|
||||||
|
storage volatile;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
salsa::query_definition! {
|
impl<DB: Database> salsa::QueryFunction<DB> for MemoizedA {
|
||||||
crate MemoizedA(db: &impl Database, (): ()) -> () {
|
fn execute(db: &DB, (): ()) -> () {
|
||||||
db.memoized_b(())
|
db.memoized_b(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
salsa::query_definition! {
|
impl<DB: Database> salsa::QueryFunction<DB> for MemoizedB {
|
||||||
crate MemoizedB(db: &impl Database, (): ()) -> () {
|
fn execute(db: &DB, (): ()) -> () {
|
||||||
db.memoized_a(())
|
db.memoized_a(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
salsa::query_definition! {
|
impl<DB: Database> salsa::QueryFunction<DB> for VolatileA {
|
||||||
#[storage(volatile)]
|
fn execute(db: &DB, (): ()) -> () {
|
||||||
crate VolatileA(db: &impl Database, (): ()) -> () {
|
|
||||||
db.volatile_b(())
|
db.volatile_b(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
salsa::query_definition! {
|
impl<DB: Database> salsa::QueryFunction<DB> for VolatileB {
|
||||||
#[storage(volatile)]
|
fn execute(db: &DB, (): ()) -> () {
|
||||||
crate VolatileB(db: &impl Database, (): ()) -> () {
|
|
||||||
db.volatile_a(())
|
db.volatile_a(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,46 +11,40 @@ salsa::query_prototype! {
|
||||||
}
|
}
|
||||||
fn dep_derived1(key: ()) -> usize {
|
fn dep_derived1(key: ()) -> usize {
|
||||||
type Derived1;
|
type Derived1;
|
||||||
|
storage dependencies;
|
||||||
}
|
}
|
||||||
fn dep_input1(key: ()) -> usize {
|
fn dep_input1(key: ()) -> usize {
|
||||||
type Input1;
|
type Input1;
|
||||||
|
storage input;
|
||||||
}
|
}
|
||||||
fn dep_input2(key: ()) -> usize {
|
fn dep_input2(key: ()) -> usize {
|
||||||
type Input2;
|
type Input2;
|
||||||
|
storage input;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
salsa::query_definition! {
|
impl<DB: MemoizedDepInputsContext> salsa::QueryFunction<DB> for Memoized2 {
|
||||||
crate Memoized2(db: &impl MemoizedDepInputsContext, (): ()) -> usize {
|
fn execute(db: &DB, (): ()) -> usize {
|
||||||
db.log().add("Memoized2 invoked");
|
db.log().add("Memoized2 invoked");
|
||||||
db.dep_memoized1(())
|
db.dep_memoized1(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
salsa::query_definition! {
|
impl<DB: MemoizedDepInputsContext> salsa::QueryFunction<DB> for Memoized1 {
|
||||||
crate Memoized1(db: &impl MemoizedDepInputsContext, (): ()) -> usize {
|
fn execute(db: &DB, (): ()) -> usize {
|
||||||
db.log().add("Memoized1 invoked");
|
db.log().add("Memoized1 invoked");
|
||||||
db.dep_derived1(()) * 2
|
db.dep_derived1(()) * 2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
salsa::query_definition! {
|
impl<DB: MemoizedDepInputsContext> salsa::QueryFunction<DB> for Derived1 {
|
||||||
#[storage(dependencies)]
|
fn execute(db: &DB, (): ()) -> usize {
|
||||||
crate Derived1(db: &impl MemoizedDepInputsContext, (): ()) -> usize {
|
|
||||||
db.log().add("Derived1 invoked");
|
db.log().add("Derived1 invoked");
|
||||||
db.dep_input1(()) / 2
|
db.dep_input1(()) / 2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
salsa::query_definition! {
|
|
||||||
crate Input1: Map<(), usize>;
|
|
||||||
}
|
|
||||||
|
|
||||||
salsa::query_definition! {
|
|
||||||
crate Input2: Map<(), usize>;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn revalidate() {
|
fn revalidate() {
|
||||||
let db = &TestContextImpl::default();
|
let db = &TestContextImpl::default();
|
||||||
|
|
|
@ -8,31 +8,22 @@ salsa::query_prototype! {
|
||||||
}
|
}
|
||||||
fn input1(key: ()) -> usize {
|
fn input1(key: ()) -> usize {
|
||||||
type Input1;
|
type Input1;
|
||||||
|
storage input;
|
||||||
}
|
}
|
||||||
fn input2(key: ()) -> usize {
|
fn input2(key: ()) -> usize {
|
||||||
type Input2;
|
type Input2;
|
||||||
|
storage input;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
salsa::query_definition! {
|
impl<DB: MemoizedInputsContext> salsa::QueryFunction<DB> for Max {
|
||||||
crate Max(db: &impl MemoizedInputsContext, (): ()) -> usize {
|
fn execute(db: &DB, (): ()) -> usize {
|
||||||
db.log().add("Max invoked");
|
db.log().add("Max invoked");
|
||||||
std::cmp::max(
|
std::cmp::max(db.input1(()), db.input2(()))
|
||||||
db.input1(()),
|
|
||||||
db.input2(()),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
salsa::query_definition! {
|
|
||||||
crate Input1: Map<(), usize>;
|
|
||||||
}
|
|
||||||
|
|
||||||
salsa::query_definition! {
|
|
||||||
crate Input2: Map<(), usize>;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn revalidate() {
|
fn revalidate() {
|
||||||
let db = &TestContextImpl::default();
|
let db = &TestContextImpl::default();
|
||||||
|
|
|
@ -13,28 +13,28 @@ salsa::query_prototype! {
|
||||||
}
|
}
|
||||||
fn volatile(key: ()) -> usize {
|
fn volatile(key: ()) -> usize {
|
||||||
type Volatile;
|
type Volatile;
|
||||||
|
storage volatile;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
salsa::query_definition! {
|
impl<DB: MemoizedVolatileContext> salsa::QueryFunction<DB> for Memoized2 {
|
||||||
crate Memoized2(db: &impl MemoizedVolatileContext, (): ()) -> usize {
|
fn execute(db: &DB, (): ()) -> usize {
|
||||||
db.log().add("Memoized2 invoked");
|
db.log().add("Memoized2 invoked");
|
||||||
db.memoized1(())
|
db.memoized1(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
salsa::query_definition! {
|
impl<DB: MemoizedVolatileContext> salsa::QueryFunction<DB> for Memoized1 {
|
||||||
crate Memoized1(db: &impl MemoizedVolatileContext, (): ()) -> usize {
|
fn execute(db: &DB, (): ()) -> usize {
|
||||||
db.log().add("Memoized1 invoked");
|
db.log().add("Memoized1 invoked");
|
||||||
let v = db.volatile(());
|
let v = db.volatile(());
|
||||||
v / 2
|
v / 2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
salsa::query_definition! {
|
impl<DB: MemoizedVolatileContext> salsa::QueryFunction<DB> for Volatile {
|
||||||
#[storage(volatile)]
|
fn execute(db: &DB, (): ()) -> usize {
|
||||||
crate Volatile(db: &impl MemoizedVolatileContext, (): ()) -> usize {
|
|
||||||
db.log().add("Volatile invoked");
|
db.log().add("Volatile invoked");
|
||||||
db.clock().increment()
|
db.clock().increment()
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,23 +9,23 @@ salsa::query_prototype! {
|
||||||
}
|
}
|
||||||
fn volatile(key: ()) -> usize {
|
fn volatile(key: ()) -> usize {
|
||||||
type Volatile;
|
type Volatile;
|
||||||
|
storage volatile;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
salsa::query_definition! {
|
/// Because this query is memoized, we only increment the counter
|
||||||
/// Because this query is memoized, we only increment the counter
|
/// the first time it is invoked.
|
||||||
/// the first time it is invoked.
|
impl<DB: Database> salsa::QueryFunction<DB> for Memoized {
|
||||||
crate Memoized(db: &impl Database, (): ()) -> usize {
|
fn execute(db: &DB, (): ()) -> usize {
|
||||||
db.increment()
|
db.increment()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
salsa::query_definition! {
|
/// Because this query is volatile, each time it is invoked,
|
||||||
/// Because this query is volatile, each time it is invoked,
|
/// we will increment the counter.
|
||||||
/// we will increment the counter.
|
impl<DB: Database> salsa::QueryFunction<DB> for Volatile {
|
||||||
#[storage(volatile)]
|
fn execute(db: &DB, (): ()) -> usize {
|
||||||
crate Volatile(db: &impl Database, (): ()) -> usize {
|
|
||||||
db.increment()
|
db.increment()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue