mirror of
https://github.com/salsa-rs/salsa.git
synced 2024-12-25 05:29:43 +00:00
change #[salsa::query_group]
attribute to take a struct name
This commit is contained in:
parent
690a118472
commit
9b5c7eeb5e
23 changed files with 133 additions and 111 deletions
|
@ -1,6 +1,5 @@
|
||||||
use heck::SnakeCase;
|
use heck::SnakeCase;
|
||||||
use proc_macro::TokenStream;
|
use proc_macro::TokenStream;
|
||||||
use proc_macro2::Span;
|
|
||||||
use syn::parse::{Parse, ParseStream};
|
use syn::parse::{Parse, ParseStream};
|
||||||
use syn::punctuated::Punctuated;
|
use syn::punctuated::Punctuated;
|
||||||
use syn::{Ident, ItemStruct, Path, Token};
|
use syn::{Ident, ItemStruct, Path, Token};
|
||||||
|
@ -18,21 +17,29 @@ pub(crate) fn database(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||||
let mut output = proc_macro2::TokenStream::new();
|
let mut output = proc_macro2::TokenStream::new();
|
||||||
output.extend(quote! { #input });
|
output.extend(quote! { #input });
|
||||||
|
|
||||||
let query_group_names_camel: Vec<_> = query_groups
|
let query_group_names_snake: Vec<_> = query_groups
|
||||||
.iter()
|
.iter()
|
||||||
.map(|query_group| {
|
.map(|query_group| {
|
||||||
let group_storage = query_group.query_group.clone();
|
let group_name = query_group.name();
|
||||||
group_storage.segments.last().unwrap().value().ident.clone()
|
Ident::new(&group_name.to_string().to_snake_case(), group_name.span())
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let query_group_names_snake: Vec<_> = query_group_names_camel
|
let query_group_storage_names: Vec<_> = query_groups
|
||||||
.iter()
|
.iter()
|
||||||
.map(|query_group_name_camel| {
|
.map(|QueryGroup { group_path }| {
|
||||||
Ident::new(
|
quote! {
|
||||||
&query_group_name_camel.to_string().to_snake_case(),
|
<#group_path as salsa::plumbing::QueryGroup<#database_name>>::GroupStorage
|
||||||
query_group_name_camel.span(),
|
}
|
||||||
)
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let query_group_key_names: Vec<_> = query_groups
|
||||||
|
.iter()
|
||||||
|
.map(|QueryGroup { group_path }| {
|
||||||
|
quote! {
|
||||||
|
<#group_path as salsa::plumbing::QueryGroup<#database_name>>::GroupKey
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
|
@ -40,21 +47,25 @@ pub(crate) fn database(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||||
// `foo::MyGroupGroupStorage`
|
// `foo::MyGroupGroupStorage`
|
||||||
let mut storage_fields = proc_macro2::TokenStream::new();
|
let mut storage_fields = proc_macro2::TokenStream::new();
|
||||||
let mut has_group_impls = proc_macro2::TokenStream::new();
|
let mut has_group_impls = proc_macro2::TokenStream::new();
|
||||||
for (query_group, query_group_name_snake) in query_groups.iter().zip(&query_group_names_snake) {
|
for (((query_group, group_name_snake), group_storage), group_key) in query_groups
|
||||||
|
.iter()
|
||||||
|
.zip(&query_group_names_snake)
|
||||||
|
.zip(&query_group_storage_names)
|
||||||
|
.zip(&query_group_key_names)
|
||||||
|
{
|
||||||
|
let group_path = &query_group.group_path;
|
||||||
let group_name = query_group.name();
|
let group_name = query_group.name();
|
||||||
let group_storage = query_group.group_storage();
|
|
||||||
let group_key = query_group.group_key();
|
|
||||||
|
|
||||||
// rewrite the last identifier (`MyGroup`, above) to
|
// rewrite the last identifier (`MyGroup`, above) to
|
||||||
// (e.g.) `MyGroupGroupStorage`.
|
// (e.g.) `MyGroupGroupStorage`.
|
||||||
storage_fields.extend(quote! { #query_group_name_snake: #group_storage<#database_name>, });
|
storage_fields.extend(quote! {
|
||||||
|
#group_name_snake: #group_storage,
|
||||||
|
});
|
||||||
has_group_impls.extend(quote! {
|
has_group_impls.extend(quote! {
|
||||||
impl ::salsa::plumbing::HasQueryGroup<#group_storage<#database_name>, #group_key>
|
impl ::salsa::plumbing::HasQueryGroup<#group_path> for #database_name {
|
||||||
for #database_name
|
fn group_storage(db: &Self) -> &#group_storage {
|
||||||
{
|
|
||||||
fn group_storage(db: &Self) -> &#group_storage<#database_name> {
|
|
||||||
let runtime = ::salsa::Database::salsa_runtime(db);
|
let runtime = ::salsa::Database::salsa_runtime(db);
|
||||||
&runtime.storage().#query_group_name_snake
|
&runtime.storage().#group_name_snake
|
||||||
}
|
}
|
||||||
|
|
||||||
fn database_key(group_key: #group_key) -> __SalsaDatabaseKey {
|
fn database_key(group_key: #group_key) -> __SalsaDatabaseKey {
|
||||||
|
@ -90,9 +101,8 @@ pub(crate) fn database(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||||
// foo(<FooType as ::salsa::Query<#database_name>>::Key),
|
// foo(<FooType as ::salsa::Query<#database_name>>::Key),
|
||||||
// ```
|
// ```
|
||||||
let mut variants = proc_macro2::TokenStream::new();
|
let mut variants = proc_macro2::TokenStream::new();
|
||||||
for query_group in query_groups {
|
for (query_group, group_key) in query_groups.iter().zip(&query_group_key_names) {
|
||||||
let group_name = query_group.name();
|
let group_name = query_group.name();
|
||||||
let group_key = query_group.group_key();
|
|
||||||
variants.extend(quote!(
|
variants.extend(quote!(
|
||||||
#group_name(#group_key),
|
#group_name(#group_key),
|
||||||
));
|
));
|
||||||
|
@ -114,11 +124,12 @@ pub(crate) fn database(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||||
|
|
||||||
//
|
//
|
||||||
let mut for_each_ops = proc_macro2::TokenStream::new();
|
let mut for_each_ops = proc_macro2::TokenStream::new();
|
||||||
for query_group in query_groups {
|
for (QueryGroup { group_path }, group_storage) in
|
||||||
let group_storage = query_group.group_storage();
|
query_groups.iter().zip(&query_group_storage_names)
|
||||||
|
{
|
||||||
for_each_ops.extend(quote! {
|
for_each_ops.extend(quote! {
|
||||||
let storage: &#group_storage<#database_name> =
|
let storage: &#group_storage =
|
||||||
::salsa::plumbing::HasQueryGroup::group_storage(self);
|
<Self as salsa::plumbing::HasQueryGroup<#group_path>>::group_storage(self);
|
||||||
storage.for_each_query(self, &mut op);
|
storage.for_each_query(self, &mut op);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -184,13 +195,13 @@ impl Parse for QueryGroupList {
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
struct QueryGroup {
|
struct QueryGroup {
|
||||||
query_group: Path,
|
group_path: Path,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl QueryGroup {
|
impl QueryGroup {
|
||||||
/// The name of the query group trait.
|
/// The name of the query group trait.
|
||||||
fn name(&self) -> Ident {
|
fn name(&self) -> Ident {
|
||||||
self.query_group
|
self.group_path
|
||||||
.segments
|
.segments
|
||||||
.last()
|
.last()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
@ -198,35 +209,6 @@ impl QueryGroup {
|
||||||
.ident
|
.ident
|
||||||
.clone()
|
.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Construct the path to the group storage for a query group. For
|
|
||||||
/// a query group at the path `foo::MyQuery`, this would be
|
|
||||||
/// `foo::MyQueryGroupStorage`.
|
|
||||||
fn group_storage(&self) -> Path {
|
|
||||||
self.path_with_suffix("GroupStorage")
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Construct the path to the group storage for a query group. For
|
|
||||||
/// a query group at the path `foo::MyQuery`, this would be
|
|
||||||
/// `foo::MyQueryGroupDatabaseKey`.
|
|
||||||
fn group_key(&self) -> Path {
|
|
||||||
self.path_with_suffix("GroupKey")
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Construct a path leading to the query group, but with some
|
|
||||||
/// suffix. So, for a query group at the path `foo::MyQuery`,
|
|
||||||
/// this would be `foo::MyQueryXXX` where `XXX` is the provided
|
|
||||||
/// suffix.
|
|
||||||
fn path_with_suffix(&self, suffix: &str) -> Path {
|
|
||||||
let mut group_storage = self.query_group.clone();
|
|
||||||
let last_ident = &group_storage.segments.last().unwrap().value().ident;
|
|
||||||
let storage_ident = Ident::new(
|
|
||||||
&format!("{}{}", last_ident.to_string(), suffix),
|
|
||||||
Span::call_site(),
|
|
||||||
);
|
|
||||||
group_storage.segments.last_mut().unwrap().value_mut().ident = storage_ident;
|
|
||||||
group_storage
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for QueryGroup {
|
impl Parse for QueryGroup {
|
||||||
|
@ -234,8 +216,8 @@ impl Parse for QueryGroup {
|
||||||
/// impl HelloWorldDatabase;
|
/// impl HelloWorldDatabase;
|
||||||
/// ```
|
/// ```
|
||||||
fn parse(input: ParseStream) -> syn::Result<Self> {
|
fn parse(input: ParseStream) -> syn::Result<Self> {
|
||||||
let query_group: Path = input.parse()?;
|
let group_path: Path = input.parse()?;
|
||||||
Ok(QueryGroup { query_group })
|
Ok(QueryGroup { group_path })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,12 +3,12 @@ use heck::CamelCase;
|
||||||
use proc_macro::TokenStream;
|
use proc_macro::TokenStream;
|
||||||
use proc_macro2::Span;
|
use proc_macro2::Span;
|
||||||
use quote::ToTokens;
|
use quote::ToTokens;
|
||||||
use syn::{parse_macro_input, AttributeArgs, FnArg, Ident, ItemTrait, ReturnType, TraitItem};
|
use syn::{parse_macro_input, FnArg, Ident, ItemTrait, ReturnType, TraitItem};
|
||||||
|
|
||||||
/// Implementation for `[salsa::query_group]` decorator.
|
/// Implementation for `[salsa::query_group]` decorator.
|
||||||
pub(crate) fn query_group(args: TokenStream, input: TokenStream) -> TokenStream {
|
pub(crate) fn query_group(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||||
let _args = parse_macro_input!(args as AttributeArgs);
|
let group_struct: Ident = parse_macro_input!(args as Ident);
|
||||||
let input = parse_macro_input!(input as ItemTrait);
|
let input: ItemTrait = parse_macro_input!(input as ItemTrait);
|
||||||
// println!("args: {:#?}", args);
|
// println!("args: {:#?}", args);
|
||||||
// println!("input: {:#?}", input);
|
// println!("input: {:#?}", input);
|
||||||
|
|
||||||
|
@ -121,12 +121,12 @@ pub(crate) fn query_group(args: TokenStream, input: TokenStream) -> TokenStream
|
||||||
}
|
}
|
||||||
|
|
||||||
let group_key = Ident::new(
|
let group_key = Ident::new(
|
||||||
&format!("{}GroupKey", trait_name.to_string()),
|
&format!("{}GroupKey__", trait_name.to_string()),
|
||||||
Span::call_site(),
|
Span::call_site(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let group_storage = Ident::new(
|
let group_storage = Ident::new(
|
||||||
&format!("{}GroupStorage", trait_name.to_string()),
|
&format!("{}GroupStorage__", trait_name.to_string()),
|
||||||
Span::call_site(),
|
Span::call_site(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -235,6 +235,19 @@ pub(crate) fn query_group(args: TokenStream, input: TokenStream) -> TokenStream
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Emit the query group struct and impl of `QueryGroup`.
|
||||||
|
output.extend(quote! {
|
||||||
|
/// Representative struct for the query group.
|
||||||
|
#trait_vis struct #group_struct { }
|
||||||
|
|
||||||
|
impl<DB__> salsa::plumbing::QueryGroup<DB__> for #group_struct
|
||||||
|
where DB__: #trait_name
|
||||||
|
{
|
||||||
|
type GroupStorage = #group_storage<DB__>;
|
||||||
|
type GroupKey = #group_key;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Emit an impl of the trait
|
// Emit an impl of the trait
|
||||||
output.extend({
|
output.extend({
|
||||||
let bounds = &input.supertraits;
|
let bounds = &input.supertraits;
|
||||||
|
@ -242,7 +255,7 @@ pub(crate) fn query_group(args: TokenStream, input: TokenStream) -> TokenStream
|
||||||
impl<T> #trait_name for T
|
impl<T> #trait_name for T
|
||||||
where
|
where
|
||||||
T: #bounds,
|
T: #bounds,
|
||||||
T: ::salsa::plumbing::HasQueryGroup<#group_storage<T>, #group_key>,
|
T: ::salsa::plumbing::HasQueryGroup<#group_struct>
|
||||||
{
|
{
|
||||||
#query_fn_definitions
|
#query_fn_definitions
|
||||||
}
|
}
|
||||||
|
@ -277,6 +290,7 @@ pub(crate) fn query_group(args: TokenStream, input: TokenStream) -> TokenStream
|
||||||
type Key = (#(#keys),*);
|
type Key = (#(#keys),*);
|
||||||
type Value = #value;
|
type Value = #value;
|
||||||
type Storage = salsa::plumbing::#storage<DB, Self>;
|
type Storage = salsa::plumbing::#storage<DB, Self>;
|
||||||
|
type Group = #group_struct;
|
||||||
type GroupStorage = #group_storage<DB>;
|
type GroupStorage = #group_storage<DB>;
|
||||||
type GroupKey = #group_key;
|
type GroupKey = #group_key;
|
||||||
|
|
||||||
|
@ -335,7 +349,7 @@ pub(crate) fn query_group(args: TokenStream, input: TokenStream) -> TokenStream
|
||||||
) -> bool
|
) -> bool
|
||||||
where
|
where
|
||||||
DB__: #trait_name,
|
DB__: #trait_name,
|
||||||
DB__: ::salsa::plumbing::HasQueryGroup<#group_storage<DB__>, #group_key>,
|
DB__: ::salsa::plumbing::HasQueryGroup<#group_struct>,
|
||||||
{
|
{
|
||||||
match self {
|
match self {
|
||||||
#query_descriptor_maybe_change
|
#query_descriptor_maybe_change
|
||||||
|
@ -361,7 +375,7 @@ pub(crate) fn query_group(args: TokenStream, input: TokenStream) -> TokenStream
|
||||||
impl<DB__> #group_storage<DB__>
|
impl<DB__> #group_storage<DB__>
|
||||||
where
|
where
|
||||||
DB__: #trait_name,
|
DB__: #trait_name,
|
||||||
DB__: ::salsa::plumbing::HasQueryGroup<#group_storage<DB__>, #group_key>,
|
DB__: ::salsa::plumbing::HasQueryGroup<#group_struct>,
|
||||||
{
|
{
|
||||||
#trait_vis fn for_each_query(
|
#trait_vis fn for_each_query(
|
||||||
&self,
|
&self,
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::compiler;
|
use crate::compiler;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
#[salsa::query_group]
|
#[salsa::query_group(ClassTable)]
|
||||||
pub trait ClassTableDatabase: compiler::CompilerDatabase {
|
pub trait ClassTableDatabase: compiler::CompilerDatabase {
|
||||||
/// Get the fields.
|
/// Get the fields.
|
||||||
fn fields(&self, class: DefId) -> Arc<Vec<DefId>>;
|
fn fields(&self, class: DefId) -> Arc<Vec<DefId>>;
|
||||||
|
|
|
@ -13,7 +13,7 @@ use crate::compiler::{CompilerDatabase, Interner};
|
||||||
/// to your context (e.g., a shared counter or some such thing). If
|
/// to your context (e.g., a shared counter or some such thing). If
|
||||||
/// mutations to that shared state affect the results of your queries,
|
/// mutations to that shared state affect the results of your queries,
|
||||||
/// that's going to mess up the incremental results.
|
/// that's going to mess up the incremental results.
|
||||||
#[salsa::database(class_table::ClassTableDatabase)]
|
#[salsa::database(class_table::ClassTable)]
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct DatabaseImpl {
|
pub struct DatabaseImpl {
|
||||||
runtime: salsa::Runtime<DatabaseImpl>,
|
runtime: salsa::Runtime<DatabaseImpl>,
|
||||||
|
|
|
@ -4,14 +4,23 @@ use std::sync::Arc;
|
||||||
// Step 1. Define the query group
|
// Step 1. Define the query group
|
||||||
|
|
||||||
// A **query group** is a collection of queries (both inputs and
|
// A **query group** is a collection of queries (both inputs and
|
||||||
// functions) that are defined in one particular spot. Each query group
|
// functions) that are defined in one particular spot. Each query
|
||||||
// represents some subset of the full set of queries you will use in your
|
// group is defined by a representative struct (used internally by
|
||||||
// application. Query groups can also depend on one another: so you might
|
// Salsa) as well as a representative trait. By convention, for a
|
||||||
// have some basic query group A and then another query group B that uses
|
// query group `Foo`, the struct is named `Foo` and the trait is named
|
||||||
// the queries from A and adds a few more. (These relationships must form
|
// `FooDatabase`. The name `FooDatabase` reflects the fact that the
|
||||||
// a DAG at present, but that is due to Rust's restrictions around
|
// trait is implemented by **the database**, which stores all the data
|
||||||
// supertraits, which are likely to be lifted.)
|
// in the system. Each query group thus represents a subset of the
|
||||||
#[salsa::query_group]
|
// full data.
|
||||||
|
//
|
||||||
|
// To define a query group, you annotate a trait definition with the
|
||||||
|
// `#[salsa::query_group(Foo)]` attribute macro. In addition to the
|
||||||
|
// trait definition, the macro will generate a struct with the name
|
||||||
|
// `Foo` that you provide, as well as various other bits of glue.
|
||||||
|
//
|
||||||
|
// Note that one query group can "include" another by listing the
|
||||||
|
// trait for that query group as a supertrait.
|
||||||
|
#[salsa::query_group(HelloWorld)]
|
||||||
trait HelloWorldDatabase: salsa::Database {
|
trait HelloWorldDatabase: salsa::Database {
|
||||||
// For each query, we give the name, some input keys (here, we
|
// For each query, we give the name, some input keys (here, we
|
||||||
// have one key, `()`) and the output type `Arc<String>`. We can
|
// have one key, `()`) and the output type `Arc<String>`. We can
|
||||||
|
@ -52,15 +61,17 @@ fn length(db: &impl HelloWorldDatabase, (): ()) -> usize {
|
||||||
// Step 3. Define the database struct
|
// Step 3. Define the database struct
|
||||||
|
|
||||||
// Define the actual database struct. This struct needs to be
|
// Define the actual database struct. This struct needs to be
|
||||||
// annotated with `#[salsa::database(..)]`, which contains a list of
|
// annotated with `#[salsa::database(..)]`. The list `..` will be the
|
||||||
// query groups that this database supports. This attribute macro will
|
// paths leading to the query group structs for each query group that
|
||||||
// generate the necessary impls so that the database implements all of
|
// this database supports. This attribute macro will generate the
|
||||||
// those traits.
|
// necessary impls so that the database implements the corresponding
|
||||||
|
// traits as well (so, here, `DatabaseStruct` will implement the
|
||||||
|
// `HelloWorldDatabase` trait).
|
||||||
//
|
//
|
||||||
// The database struct can contain basically anything you need, but it
|
// The database struct can contain basically anything you need, but it
|
||||||
// must have a `runtime` field as shown, and you must implement the
|
// must have a `runtime` field as shown, and you must implement the
|
||||||
// `salsa::Database` trait (as shown below).
|
// `salsa::Database` trait (as shown below).
|
||||||
#[salsa::database(HelloWorldDatabase)]
|
#[salsa::database(HelloWorld)]
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
struct DatabaseStruct {
|
struct DatabaseStruct {
|
||||||
runtime: salsa::Runtime<DatabaseStruct>,
|
runtime: salsa::Runtime<DatabaseStruct>,
|
||||||
|
|
|
@ -349,6 +349,13 @@ pub trait Query<DB: Database>: Debug + Default + Sized + 'static {
|
||||||
/// Internal struct storing the values for the query.
|
/// Internal struct storing the values for the query.
|
||||||
type Storage: plumbing::QueryStorageOps<DB, Self> + Send + Sync;
|
type Storage: plumbing::QueryStorageOps<DB, Self> + Send + Sync;
|
||||||
|
|
||||||
|
/// Associate query group struct.
|
||||||
|
type Group: plumbing::QueryGroup<
|
||||||
|
DB,
|
||||||
|
GroupStorage = Self::GroupStorage,
|
||||||
|
GroupKey = Self::GroupKey,
|
||||||
|
>;
|
||||||
|
|
||||||
/// Generated struct that contains storage for all queries in a group.
|
/// Generated struct that contains storage for all queries in a group.
|
||||||
type GroupStorage;
|
type GroupStorage;
|
||||||
|
|
||||||
|
|
|
@ -86,7 +86,7 @@ impl<DB, Q> GetQueryTable<Q> for DB
|
||||||
where
|
where
|
||||||
DB: Database,
|
DB: Database,
|
||||||
Q: Query<DB>,
|
Q: Query<DB>,
|
||||||
DB: HasQueryGroup<Q::GroupStorage, Q::GroupKey>,
|
DB: HasQueryGroup<Q::Group>,
|
||||||
{
|
{
|
||||||
fn get_query_table(db: &DB) -> QueryTable<'_, DB, Q> {
|
fn get_query_table(db: &DB) -> QueryTable<'_, DB, Q> {
|
||||||
let group_storage: &Q::GroupStorage = HasQueryGroup::group_storage(db);
|
let group_storage: &Q::GroupStorage = HasQueryGroup::group_storage(db);
|
||||||
|
@ -106,18 +106,26 @@ where
|
||||||
key: <Q as Query<DB>>::Key,
|
key: <Q as Query<DB>>::Key,
|
||||||
) -> <DB as DatabaseStorageTypes>::DatabaseKey {
|
) -> <DB as DatabaseStorageTypes>::DatabaseKey {
|
||||||
let group_key = Q::group_key(key);
|
let group_key = Q::group_key(key);
|
||||||
<DB as HasQueryGroup<_, _>>::database_key(group_key)
|
<DB as HasQueryGroup<_>>::database_key(group_key)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait QueryGroup<DB: Database> {
|
||||||
|
type GroupStorage;
|
||||||
|
type GroupKey;
|
||||||
|
}
|
||||||
|
|
||||||
/// Trait implemented by a database for each group that it supports.
|
/// Trait implemented by a database for each group that it supports.
|
||||||
/// `S` and `K` are the types for *group storage* and *group key*, respectively.
|
/// `S` and `K` are the types for *group storage* and *group key*, respectively.
|
||||||
pub trait HasQueryGroup<S, K>: Database {
|
pub trait HasQueryGroup<G>: Database
|
||||||
|
where
|
||||||
|
G: QueryGroup<Self>,
|
||||||
|
{
|
||||||
/// Access the group storage struct from the database.
|
/// Access the group storage struct from the database.
|
||||||
fn group_storage(db: &Self) -> &S;
|
fn group_storage(db: &Self) -> &G::GroupStorage;
|
||||||
|
|
||||||
/// "Upcast" a group key into a database key.
|
/// "Upcast" a group key into a database key.
|
||||||
fn database_key(group_key: K) -> Self::DatabaseKey;
|
fn database_key(group_key: G::GroupKey) -> Self::DatabaseKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait QueryStorageOps<DB, Q>: Default
|
pub trait QueryStorageOps<DB, Q>: Default
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#[salsa::database(Database)]
|
#[salsa::database(GroupStruct)]
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
struct DatabaseImpl {
|
struct DatabaseImpl {
|
||||||
runtime: salsa::Runtime<DatabaseImpl>,
|
runtime: salsa::Runtime<DatabaseImpl>,
|
||||||
|
@ -10,7 +10,7 @@ impl salsa::Database for DatabaseImpl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[salsa::query_group]
|
#[salsa::query_group(GroupStruct)]
|
||||||
trait Database: salsa::Database {
|
trait Database: salsa::Database {
|
||||||
// `a` and `b` depend on each other and form a cycle
|
// `a` and `b` depend on each other and form a cycle
|
||||||
fn memoized_a(&self) -> ();
|
fn memoized_a(&self) -> ();
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::group;
|
use crate::group;
|
||||||
use crate::log::{HasLog, Log};
|
use crate::log::{HasLog, Log};
|
||||||
|
|
||||||
#[salsa::database(group::GcDatabase)]
|
#[salsa::database(group::Gc)]
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub(crate) struct DatabaseImpl {
|
pub(crate) struct DatabaseImpl {
|
||||||
runtime: salsa::Runtime<DatabaseImpl>,
|
runtime: salsa::Runtime<DatabaseImpl>,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::log::HasLog;
|
use crate::log::HasLog;
|
||||||
|
|
||||||
#[salsa::query_group]
|
#[salsa::query_group(Gc)]
|
||||||
pub(crate) trait GcDatabase: salsa::Database + HasLog {
|
pub(crate) trait GcDatabase: salsa::Database + HasLog {
|
||||||
#[salsa::input]
|
#[salsa::input]
|
||||||
fn min(&self) -> usize;
|
fn min(&self) -> usize;
|
||||||
|
|
|
@ -2,7 +2,7 @@ use crate::implementation::{TestContext, TestContextImpl};
|
||||||
use salsa::debug::DebugQueryTable;
|
use salsa::debug::DebugQueryTable;
|
||||||
use salsa::Database;
|
use salsa::Database;
|
||||||
|
|
||||||
#[salsa::query_group]
|
#[salsa::query_group(Constants)]
|
||||||
pub(crate) trait ConstantsDatabase: TestContext {
|
pub(crate) trait ConstantsDatabase: TestContext {
|
||||||
#[salsa::input]
|
#[salsa::input]
|
||||||
fn input(&self, key: char) -> usize;
|
fn input(&self, key: char) -> usize;
|
||||||
|
|
|
@ -11,10 +11,10 @@ pub(crate) trait TestContext: salsa::Database {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[salsa::database(
|
#[salsa::database(
|
||||||
constants::ConstantsDatabase,
|
constants::Constants,
|
||||||
memoized_dep_inputs::MemoizedDepInputsContext,
|
memoized_dep_inputs::MemoizedDepInputs,
|
||||||
memoized_inputs::MemoizedInputsContext,
|
memoized_inputs::MemoizedInputs,
|
||||||
memoized_volatile::MemoizedVolatileContext
|
memoized_volatile::MemoizedVolatile
|
||||||
)]
|
)]
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub(crate) struct TestContextImpl {
|
pub(crate) struct TestContextImpl {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::implementation::{TestContext, TestContextImpl};
|
use crate::implementation::{TestContext, TestContextImpl};
|
||||||
use salsa::Database;
|
use salsa::Database;
|
||||||
|
|
||||||
#[salsa::query_group]
|
#[salsa::query_group(MemoizedDepInputs)]
|
||||||
pub(crate) trait MemoizedDepInputsContext: TestContext {
|
pub(crate) trait MemoizedDepInputsContext: TestContext {
|
||||||
fn dep_memoized2(&self) -> usize;
|
fn dep_memoized2(&self) -> usize;
|
||||||
fn dep_memoized1(&self) -> usize;
|
fn dep_memoized1(&self) -> usize;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::implementation::{TestContext, TestContextImpl};
|
use crate::implementation::{TestContext, TestContextImpl};
|
||||||
use salsa::Database;
|
use salsa::Database;
|
||||||
|
|
||||||
#[salsa::query_group]
|
#[salsa::query_group(MemoizedInputs)]
|
||||||
pub(crate) trait MemoizedInputsContext: TestContext {
|
pub(crate) trait MemoizedInputsContext: TestContext {
|
||||||
fn max(&self) -> usize;
|
fn max(&self) -> usize;
|
||||||
#[salsa::input]
|
#[salsa::input]
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::implementation::{TestContext, TestContextImpl};
|
use crate::implementation::{TestContext, TestContextImpl};
|
||||||
use salsa::Database;
|
use salsa::Database;
|
||||||
|
|
||||||
#[salsa::query_group]
|
#[salsa::query_group(MemoizedVolatile)]
|
||||||
pub(crate) trait MemoizedVolatileContext: TestContext {
|
pub(crate) trait MemoizedVolatileContext: TestContext {
|
||||||
// Queries for testing a "volatile" value wrapped by
|
// Queries for testing a "volatile" value wrapped by
|
||||||
// memoization.
|
// memoization.
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#[salsa::query_group]
|
#[salsa::query_group(MyStruct)]
|
||||||
trait MyDatabase: salsa::Database {
|
trait MyDatabase: salsa::Database {
|
||||||
#[salsa::invoke(another_module::another_name)]
|
#[salsa::invoke(another_module::another_name)]
|
||||||
fn my_query(&self, key: ()) -> ();
|
fn my_query(&self, key: ()) -> ();
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use salsa::{Database, ParallelDatabase, Snapshot};
|
use salsa::{Database, ParallelDatabase, Snapshot};
|
||||||
use std::panic::{self, AssertUnwindSafe};
|
use std::panic::{self, AssertUnwindSafe};
|
||||||
|
|
||||||
#[salsa::query_group]
|
#[salsa::query_group(PanicSafelyStruct)]
|
||||||
trait PanicSafelyDatabase: salsa::Database {
|
trait PanicSafelyDatabase: salsa::Database {
|
||||||
#[salsa::input]
|
#[salsa::input]
|
||||||
fn one(&self) -> usize;
|
fn one(&self) -> usize;
|
||||||
|
@ -13,7 +13,7 @@ fn panic_safely(db: &impl PanicSafelyDatabase) -> () {
|
||||||
assert_eq!(db.one(), 1);
|
assert_eq!(db.one(), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[salsa::database(PanicSafelyDatabase)]
|
#[salsa::database(PanicSafelyStruct)]
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
struct DatabaseStruct {
|
struct DatabaseStruct {
|
||||||
runtime: salsa::Runtime<DatabaseStruct>,
|
runtime: salsa::Runtime<DatabaseStruct>,
|
||||||
|
|
|
@ -5,7 +5,7 @@ use salsa::Snapshot;
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
#[salsa::query_group]
|
#[salsa::query_group(Par)]
|
||||||
pub(crate) trait ParDatabase: Knobs + salsa::ParallelDatabase {
|
pub(crate) trait ParDatabase: Knobs + salsa::ParallelDatabase {
|
||||||
#[salsa::input]
|
#[salsa::input]
|
||||||
fn input(&self, key: char) -> usize;
|
fn input(&self, key: char) -> usize;
|
||||||
|
@ -184,7 +184,7 @@ fn snapshot_me(db: &impl ParDatabase) {
|
||||||
db.snapshot();
|
db.snapshot();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[salsa::database(ParDatabase)]
|
#[salsa::database(Par)]
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub(crate) struct ParDatabaseImpl {
|
pub(crate) struct ParDatabaseImpl {
|
||||||
runtime: salsa::Runtime<ParDatabaseImpl>,
|
runtime: salsa::Runtime<ParDatabaseImpl>,
|
||||||
|
|
|
@ -12,7 +12,7 @@ const N_READER_OPS: usize = 100;
|
||||||
struct Canceled;
|
struct Canceled;
|
||||||
type Cancelable<T> = Result<T, Canceled>;
|
type Cancelable<T> = Result<T, Canceled>;
|
||||||
|
|
||||||
#[salsa::query_group]
|
#[salsa::query_group(Stress)]
|
||||||
trait StressDatabase: salsa::Database {
|
trait StressDatabase: salsa::Database {
|
||||||
#[salsa::input]
|
#[salsa::input]
|
||||||
fn a(&self, key: usize) -> usize;
|
fn a(&self, key: usize) -> usize;
|
||||||
|
@ -33,7 +33,7 @@ fn c(db: &impl StressDatabase, key: usize) -> Cancelable<usize> {
|
||||||
db.b(key)
|
db.b(key)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[salsa::database(StressDatabase)]
|
#[salsa::database(Stress)]
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
struct StressDatabaseImpl {
|
struct StressDatabaseImpl {
|
||||||
runtime: salsa::Runtime<StressDatabaseImpl>,
|
runtime: salsa::Runtime<StressDatabaseImpl>,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use salsa::Database;
|
use salsa::Database;
|
||||||
|
|
||||||
#[salsa::query_group]
|
#[salsa::query_group(HelloWorldStruct)]
|
||||||
trait HelloWorldDatabase: salsa::Database {
|
trait HelloWorldDatabase: salsa::Database {
|
||||||
#[salsa::input]
|
#[salsa::input]
|
||||||
fn input(&self) -> String;
|
fn input(&self) -> String;
|
||||||
|
@ -20,7 +20,7 @@ fn double_length(db: &impl HelloWorldDatabase) -> usize {
|
||||||
db.length() * 2
|
db.length() * 2
|
||||||
}
|
}
|
||||||
|
|
||||||
#[salsa::database(HelloWorldDatabase)]
|
#[salsa::database(HelloWorldStruct)]
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
struct DatabaseStruct {
|
struct DatabaseStruct {
|
||||||
runtime: salsa::Runtime<DatabaseStruct>,
|
runtime: salsa::Runtime<DatabaseStruct>,
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::queries;
|
use crate::queries;
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
|
|
||||||
#[salsa::database(queries::Database)]
|
#[salsa::database(queries::GroupStruct)]
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub(crate) struct DatabaseImpl {
|
pub(crate) struct DatabaseImpl {
|
||||||
runtime: salsa::Runtime<DatabaseImpl>,
|
runtime: salsa::Runtime<DatabaseImpl>,
|
||||||
|
|
|
@ -2,7 +2,7 @@ pub(crate) trait Counter: salsa::Database {
|
||||||
fn increment(&self) -> usize;
|
fn increment(&self) -> usize;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[salsa::query_group]
|
#[salsa::query_group(GroupStruct)]
|
||||||
pub(crate) trait Database: Counter {
|
pub(crate) trait Database: Counter {
|
||||||
fn memoized(&self) -> usize;
|
fn memoized(&self) -> usize;
|
||||||
#[salsa::volatile]
|
#[salsa::volatile]
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use salsa::Database;
|
use salsa::Database;
|
||||||
|
|
||||||
#[salsa::query_group]
|
#[salsa::query_group(HelloWorld)]
|
||||||
trait HelloWorldDatabase: salsa::Database {
|
trait HelloWorldDatabase: salsa::Database {
|
||||||
#[salsa::input]
|
#[salsa::input]
|
||||||
fn input(&self, a: u32, b: u32) -> u32;
|
fn input(&self, a: u32, b: u32) -> u32;
|
||||||
|
@ -30,7 +30,7 @@ fn trailing(_db: &impl HelloWorldDatabase, a: u32, b: u32) -> u32 {
|
||||||
a - b
|
a - b
|
||||||
}
|
}
|
||||||
|
|
||||||
#[salsa::database(HelloWorldDatabase)]
|
#[salsa::database(HelloWorld)]
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
struct DatabaseStruct {
|
struct DatabaseStruct {
|
||||||
runtime: salsa::Runtime<DatabaseStruct>,
|
runtime: salsa::Runtime<DatabaseStruct>,
|
||||||
|
|
Loading…
Reference in a new issue