mirror of
https://github.com/salsa-rs/salsa.git
synced 2024-10-23 04:46:35 +00:00
wip: iterate towards hello_world
Some checks failed
Book / Book (push) Has been cancelled
Test / Test (false, beta) (push) Has been cancelled
Test / Test (false, stable) (push) Has been cancelled
Test / Test (true, nightly) (push) Has been cancelled
Test / Miri (push) Has been cancelled
Book / Deploy (push) Has been cancelled
Some checks failed
Book / Book (push) Has been cancelled
Test / Test (false, beta) (push) Has been cancelled
Test / Test (false, stable) (push) Has been cancelled
Test / Test (true, nightly) (push) Has been cancelled
Test / Miri (push) Has been cancelled
Book / Deploy (push) Has been cancelled
This commit is contained in:
parent
231dc4f713
commit
57eb0c45b4
9 changed files with 162 additions and 19 deletions
|
@ -16,6 +16,7 @@ mod maybe_backdate;
|
|||
mod maybe_clone;
|
||||
mod setup_input;
|
||||
mod setup_interned_fn;
|
||||
mod setup_struct_fn;
|
||||
mod setup_tracked_struct;
|
||||
mod unexpected_cycle_recovery;
|
||||
|
||||
|
|
123
components/salsa-macro-rules/src/setup_struct_fn.rs
Normal file
123
components/salsa-macro-rules/src/setup_struct_fn.rs
Normal file
|
@ -0,0 +1,123 @@
|
|||
/// Macro for setting up a function that must intern its arguments.
|
||||
#[macro_export]
|
||||
macro_rules! setup_struct_fn {
|
||||
(
|
||||
// Attributes on the function
|
||||
attrs: [$(#[$attr:meta]),*],
|
||||
|
||||
// Visibility of the function
|
||||
vis: $vis:vis,
|
||||
|
||||
// Name of the function
|
||||
fn_name: $fn_name:ident,
|
||||
|
||||
// Name of the `'db` lifetime that the user gave; if they didn't, then defaults to `'db`
|
||||
db_lt: $db_lt:lifetime,
|
||||
|
||||
// Path to the database trait that the user's database parameter used
|
||||
Db: $Db:path,
|
||||
|
||||
// Name of the database parameter given by the user.
|
||||
db: $db:ident,
|
||||
|
||||
// An identifier for each function argument EXCEPT the database.
|
||||
// We prefer to use the identifier the user gave, but if the user gave a pattern
|
||||
// (e.g., `(a, b): (u32, u32)`) we will synthesize an identifier.
|
||||
input_id: $input_id:ident,
|
||||
|
||||
// Types of the function arguments (may reference `$generics`).
|
||||
input_ty: $input_ty:ty,
|
||||
|
||||
// Return type of the function (may reference `$generics`).
|
||||
output_ty: $output_ty:ty,
|
||||
|
||||
// Function body, may reference identifiers defined in `$input_pats` and the generics from `$generics`
|
||||
inner_fn: $inner_fn:item,
|
||||
|
||||
// Path to the cycle recovery function to use.
|
||||
cycle_recovery_fn: ($($cycle_recovery_fn:tt)*),
|
||||
|
||||
// Name of cycle recovery strategy variant to use.
|
||||
cycle_recovery_strategy: $cycle_recovery_strategy:ident,
|
||||
|
||||
// Annoyingly macro-rules hygiene does not extend to items defined in the macro.
|
||||
// We have the procedural macro generate names for those items that are
|
||||
// not used elsewhere in the user's code.
|
||||
unused_names: [
|
||||
$zalsa:ident,
|
||||
$Configuration:ident,
|
||||
$FN_CACHE:ident,
|
||||
$inner:ident,
|
||||
]
|
||||
) => {
|
||||
$(#[$attr])*
|
||||
$vis fn $fn_name<$db_lt>(
|
||||
$db: &$db_lt dyn $Db,
|
||||
$input_id: $input_ty,
|
||||
) -> $output_ty {
|
||||
use salsa::plumbing as $zalsa;
|
||||
|
||||
struct $Configuration;
|
||||
|
||||
static $FN_CACHE: $zalsa::IngredientCache<$zalsa::function::IngredientImpl<$Configuration>> =
|
||||
$zalsa::IngredientCache::new();
|
||||
|
||||
impl $zalsa::function::Configuration for $Configuration {
|
||||
const DEBUG_NAME: &'static str = stringify!($fn_name);
|
||||
|
||||
type DbView = dyn $Db;
|
||||
|
||||
type SalsaStruct<$db_lt> = $input_ty;
|
||||
|
||||
type Input<$db_lt> = $input_ty;
|
||||
|
||||
type Output<$db_lt> = $output_ty;
|
||||
|
||||
const CYCLE_STRATEGY: $zalsa::CycleRecoveryStrategy = $zalsa::CycleRecoveryStrategy::$cycle_recovery_strategy;
|
||||
|
||||
fn should_backdate_value(
|
||||
old_value: &Self::Output<'_>,
|
||||
new_value: &Self::Output<'_>,
|
||||
) -> bool {
|
||||
old_value == new_value
|
||||
}
|
||||
|
||||
fn execute<'db>($db: &'db Self::DbView, $input_id: $input_ty) -> Self::Output<'db> {
|
||||
$inner_fn
|
||||
|
||||
$inner($db, $input_id)
|
||||
}
|
||||
|
||||
fn recover_from_cycle<'db>(
|
||||
db: &$db_lt dyn $Db,
|
||||
cycle: &$zalsa::Cycle,
|
||||
$input_id: $input_ty,
|
||||
) -> Self::Output<'db> {
|
||||
$($cycle_recovery_fn)*(db, cycle, $input_id)
|
||||
}
|
||||
|
||||
fn id_to_input<'db>(db: &'db Self::DbView, key: salsa::Id) -> Self::Input<'db> {
|
||||
$zalsa::LookupId::lookup_id(key, db)
|
||||
}
|
||||
}
|
||||
|
||||
impl $zalsa::Jar for $Configuration {
|
||||
fn create_ingredients(
|
||||
&self,
|
||||
first_index: $zalsa::IngredientIndex,
|
||||
) -> Vec<Box<dyn $zalsa::Ingredient>> {
|
||||
vec![
|
||||
Box::new(<$zalsa::function::IngredientImpl<$Configuration>>::new(
|
||||
first_index,
|
||||
)),
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
let fn_ingredient = $FN_CACHE.get_or_create($db.as_salsa_database(), || {
|
||||
$db.add_or_lookup_jar_by_type(&$Configuration)
|
||||
});
|
||||
fn_ingredient.fetch($db, $input_id).clone()
|
||||
}
|
||||
};
|
||||
}
|
|
@ -129,11 +129,8 @@ macro_rules! setup_tracked_struct {
|
|||
}
|
||||
}
|
||||
|
||||
impl<$db_lt, $Db> $zalsa::LookupId<&$db_lt $Db> for $Struct<$db_lt>
|
||||
where
|
||||
$Db: ?Sized + $zalsa::Database,
|
||||
{
|
||||
fn lookup_id(id: salsa::Id, db: & $db_lt $Db) -> Self {
|
||||
impl<'db> $zalsa::LookupId<'db> for $Struct<$db_lt> {
|
||||
fn lookup_id(id: salsa::Id, db: &'db dyn Database) -> Self {
|
||||
$Configuration::ingredient(db).lookup_struct(db.runtime(), id)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -106,7 +106,29 @@ impl Macro {
|
|||
}],
|
||||
)),
|
||||
FunctionType::Constant => todo!(),
|
||||
FunctionType::SalsaStruct => todo!(),
|
||||
FunctionType::SalsaStruct => Ok(crate::debug::dump_tokens(
|
||||
fn_name,
|
||||
quote![salsa::plumbing::setup_struct_fn! {
|
||||
attrs: [#(#attrs),*],
|
||||
vis: #vis,
|
||||
fn_name: #fn_name,
|
||||
db_lt: #db_lt,
|
||||
Db: #db_path,
|
||||
db: #db_ident,
|
||||
input_id: #(#input_ids,)*
|
||||
input_ty: #(#input_tys,)*
|
||||
output_ty: #output_ty,
|
||||
inner_fn: #inner_fn,
|
||||
cycle_recovery_fn: #cycle_recovery_fn,
|
||||
cycle_recovery_strategy: #cycle_recovery_strategy,
|
||||
unused_names: [
|
||||
#zalsa,
|
||||
#Configuration,
|
||||
#FN_CACHE,
|
||||
#inner,
|
||||
]
|
||||
}],
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -339,9 +339,7 @@ impl TrackedStruct {
|
|||
let jar_ty = self.jar_ty();
|
||||
let tracked_struct_ingredient = self.tracked_struct_ingredient_index();
|
||||
parse_quote_spanned! { ident.span() =>
|
||||
impl<#db, #parameters> salsa::id::LookupId<& #db_lt #db> for #ident #type_generics
|
||||
where
|
||||
#db: ?Sized + salsa::DbWithJar<#jar_ty>,
|
||||
impl<#db, #parameters> salsa::id::LookupId<#db_lt> for #ident #type_generics
|
||||
#where_clause
|
||||
{
|
||||
fn lookup_id(id: salsa::Id, db: & #db_lt DB) -> Self {
|
||||
|
|
13
src/id.rs
13
src/id.rs
|
@ -2,6 +2,8 @@ use std::fmt::Debug;
|
|||
use std::hash::Hash;
|
||||
use std::num::NonZeroU32;
|
||||
|
||||
use crate::Database;
|
||||
|
||||
/// An Id is a newtype'd u32 ranging from `0..Id::MAX_U32`.
|
||||
/// The maximum range is smaller than a standard u32 to leave
|
||||
/// room for niches; currently there is only one niche, so that
|
||||
|
@ -74,7 +76,7 @@ pub trait AsId: Sized {
|
|||
/// up in the database to find it. This is different from
|
||||
/// [`AsId`][] where what we have is literally a *newtype*
|
||||
/// for an `Id`.
|
||||
pub trait LookupId<DB>: AsId {
|
||||
pub trait LookupId<'db>: AsId {
|
||||
/// Lookup from an `Id` to get an instance of the type.
|
||||
///
|
||||
/// # Panics
|
||||
|
@ -86,7 +88,7 @@ pub trait LookupId<DB>: AsId {
|
|||
/// dependency tracking typically ensures this does not
|
||||
/// occur, but it is possible for a user to violate this
|
||||
/// rule.
|
||||
fn lookup_id(id: Id, db: DB) -> Self;
|
||||
fn lookup_id(id: Id, db: &'db dyn Database) -> Self;
|
||||
}
|
||||
|
||||
/// Internal Salsa trait for types that are just a newtype'd [`Id`][].
|
||||
|
@ -124,11 +126,8 @@ impl FromId for () {
|
|||
}
|
||||
}
|
||||
|
||||
impl<DB, ID> LookupId<DB> for ID
|
||||
where
|
||||
ID: FromId,
|
||||
{
|
||||
fn lookup_id(id: Id, _db: DB) -> Self {
|
||||
impl<'db, ID: FromId> LookupId<'db> for ID {
|
||||
fn lookup_id(id: Id, _db: &'db dyn Database) -> Self {
|
||||
Self::from_id(id)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -288,10 +288,9 @@ where
|
|||
id.as_id()
|
||||
}
|
||||
|
||||
pub fn data_with_db<'db, DB>(&'db self, id: crate::Id, db: &'db DB) -> C::Data<'db>
|
||||
pub fn data_with_db<'db>(&'db self, id: crate::Id, db: &'db dyn Database) -> C::Data<'db>
|
||||
where
|
||||
DB: ?Sized,
|
||||
C::Data<'db>: LookupId<&'db DB>,
|
||||
C::Data<'db>: LookupId<'db>,
|
||||
{
|
||||
<C::Data<'db>>::lookup_id(id, db)
|
||||
}
|
||||
|
|
|
@ -60,6 +60,7 @@ pub mod plumbing {
|
|||
pub use crate::id::AsId;
|
||||
pub use crate::id::FromId;
|
||||
pub use crate::id::Id;
|
||||
pub use crate::id::LookupId;
|
||||
pub use crate::ingredient::Ingredient;
|
||||
pub use crate::ingredient::Jar;
|
||||
pub use crate::revision::Revision;
|
||||
|
@ -79,6 +80,7 @@ pub mod plumbing {
|
|||
pub use salsa_macro_rules::maybe_cloned_ty;
|
||||
pub use salsa_macro_rules::setup_input;
|
||||
pub use salsa_macro_rules::setup_interned_fn;
|
||||
pub use salsa_macro_rules::setup_struct_fn;
|
||||
pub use salsa_macro_rules::setup_tracked_struct;
|
||||
pub use salsa_macro_rules::unexpected_cycle_recovery;
|
||||
|
||||
|
|
|
@ -62,8 +62,10 @@ struct Database {
|
|||
logger: Logger,
|
||||
}
|
||||
|
||||
#[salsa::db]
|
||||
impl salsa::Database for Database {}
|
||||
|
||||
#[salsa::db]
|
||||
impl Db for Database {}
|
||||
|
||||
impl HasLogger for Database {
|
||||
|
|
Loading…
Reference in a new issue