mirror of
https://github.com/salsa-rs/salsa.git
synced 2025-02-02 09:46:06 +00:00
create macro-rules macros to encapsulate output
This is a new idea for how to manage procedural macros, which I kind of hate.
This commit is contained in:
parent
d666744704
commit
dde7341f97
8 changed files with 244 additions and 206 deletions
|
@ -18,6 +18,7 @@ log = "0.4.5"
|
||||||
orx-concurrent-vec = "1.10.0"
|
orx-concurrent-vec = "1.10.0"
|
||||||
parking_lot = "0.12.1"
|
parking_lot = "0.12.1"
|
||||||
rustc-hash = "1.1.0"
|
rustc-hash = "1.1.0"
|
||||||
|
salsa-macro-rules = { version = "0.1.0", path = "components/salsa-macro-rules" }
|
||||||
salsa-macros = { path = "components/salsa-macros" }
|
salsa-macros = { path = "components/salsa-macros" }
|
||||||
smallvec = "1.0.0"
|
smallvec = "1.0.0"
|
||||||
|
|
||||||
|
@ -32,4 +33,4 @@ test-log = "0.2.11"
|
||||||
trybuild = "1.0"
|
trybuild = "1.0"
|
||||||
|
|
||||||
[workspace]
|
[workspace]
|
||||||
members = ["components/salsa-macros"]
|
members = [ "components/salsa-macro-rules","components/salsa-macros"]
|
||||||
|
|
6
components/salsa-macro-rules/Cargo.toml
Normal file
6
components/salsa-macro-rules/Cargo.toml
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
[package]
|
||||||
|
name = "salsa-macro-rules"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
200
components/salsa-macro-rules/src/lib.rs
Normal file
200
components/salsa-macro-rules/src/lib.rs
Normal file
|
@ -0,0 +1,200 @@
|
||||||
|
//! This crate defines various `macro_rules` macros
|
||||||
|
//! used as part of Salsa's internal plumbing.
|
||||||
|
//!
|
||||||
|
//! The procedural macros typically emit calls to these
|
||||||
|
//! `macro_rules` macros.
|
||||||
|
//!
|
||||||
|
//! Modifying `macro_rules` macro definitions is generally
|
||||||
|
//! more ergonomic and also permits true hygiene.
|
||||||
|
|
||||||
|
// Macro that generates the body of the cycle recovery function
|
||||||
|
// for the case where no cycle recovery is possible. This has to be
|
||||||
|
// a macro because it can take a variadic number of arguments.
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! unexpected_cycle_recovery {
|
||||||
|
($db:ident, $cycle:ident, $($other_inputs:ident),*) => {
|
||||||
|
{
|
||||||
|
std::mem::drop($db);
|
||||||
|
std::mem::drop(($($other_inputs),*));
|
||||||
|
panic!("cannot recover from cycle `{:?}`", $cycle)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Macro for setting up a function that must intern its arguments.
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! setup_interned_fn {
|
||||||
|
(
|
||||||
|
// 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_ids: [$($input_id:ident),*],
|
||||||
|
|
||||||
|
// Patterns that the user gave for each argument EXCEPT the database.
|
||||||
|
// May be identifiers, but could be something else.
|
||||||
|
input_pats: [$($input_pat:pat),*],
|
||||||
|
|
||||||
|
// Types of the function arguments (may reference `$generics`).
|
||||||
|
input_tys: [$($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`
|
||||||
|
body: $body:block,
|
||||||
|
|
||||||
|
// 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,
|
||||||
|
$InternedData:ident,
|
||||||
|
$FN_CACHE:ident,
|
||||||
|
$INTERN_CACHE:ident,
|
||||||
|
$inner:ident,
|
||||||
|
]
|
||||||
|
) => {
|
||||||
|
$vis fn $fn_name<$db_lt>(
|
||||||
|
$db: &$db_lt dyn $Db,
|
||||||
|
$($input_id: $input_ty,)*
|
||||||
|
) -> $output_ty {
|
||||||
|
use salsa::plumbing as $zalsa;
|
||||||
|
|
||||||
|
struct $Configuration;
|
||||||
|
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
struct $InternedData<'db>(
|
||||||
|
std::ptr::NonNull<$zalsa::interned::ValueStruct<$Configuration>>,
|
||||||
|
std::marker::PhantomData<&'db $zalsa::interned::ValueStruct<$Configuration>>,
|
||||||
|
);
|
||||||
|
|
||||||
|
static $FN_CACHE: $zalsa::IngredientCache<$zalsa::function::IngredientImpl<$Configuration>> =
|
||||||
|
$zalsa::IngredientCache::new();
|
||||||
|
|
||||||
|
static $INTERN_CACHE: $zalsa::IngredientCache<$zalsa::interned::IngredientImpl<$Configuration>> =
|
||||||
|
$zalsa::IngredientCache::new();
|
||||||
|
|
||||||
|
impl $zalsa::SalsaStructInDb<dyn $Db> for $InternedData<'_> {
|
||||||
|
fn register_dependent_fn(_db: &dyn $Db, _index: $zalsa::IngredientIndex) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl $zalsa::function::Configuration for $Configuration {
|
||||||
|
const DEBUG_NAME: &'static str = stringify!($fn_name);
|
||||||
|
|
||||||
|
type DbView = dyn $Db;
|
||||||
|
|
||||||
|
type SalsaStruct<$db_lt> = $InternedData<$db_lt>;
|
||||||
|
|
||||||
|
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> {
|
||||||
|
$vis fn $inner<$db_lt>(
|
||||||
|
$db: &$db_lt dyn $Db,
|
||||||
|
$($input_pat: $input_ty,)*
|
||||||
|
) -> $output_ty {
|
||||||
|
$body
|
||||||
|
}
|
||||||
|
|
||||||
|
$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> {
|
||||||
|
let ingredient = $INTERN_CACHE.get_or_create(db.as_salsa_database(), || {
|
||||||
|
db.add_or_lookup_jar_by_type(&$Configuration) + 1
|
||||||
|
});
|
||||||
|
ingredient.data(key).clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl $zalsa::interned::Configuration for $Configuration {
|
||||||
|
const DEBUG_NAME: &'static str = "Configuration";
|
||||||
|
|
||||||
|
type Data<$db_lt> = ($($input_ty),*);
|
||||||
|
|
||||||
|
type Struct<$db_lt> = $InternedData<$db_lt>;
|
||||||
|
|
||||||
|
unsafe fn struct_from_raw<'db>(
|
||||||
|
ptr: std::ptr::NonNull<$zalsa::interned::ValueStruct<Self>>,
|
||||||
|
) -> Self::Struct<'db> {
|
||||||
|
$InternedData(ptr, std::marker::PhantomData)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deref_struct(s: Self::Struct<'_>) -> &$zalsa::interned::ValueStruct<Self> {
|
||||||
|
unsafe { s.0.as_ref() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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,
|
||||||
|
)),
|
||||||
|
Box::new(<$zalsa::interned::IngredientImpl<$Configuration>>::new(
|
||||||
|
first_index + 1,
|
||||||
|
)),
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let intern_ingredient = $INTERN_CACHE.get_or_create($db.as_salsa_database(), || {
|
||||||
|
$db.add_or_lookup_jar_by_type(&$Configuration) + 1
|
||||||
|
});
|
||||||
|
let key = intern_ingredient.intern_id($db.runtime(), ($($input_id),*));
|
||||||
|
|
||||||
|
let fn_ingredient = $FN_CACHE.get_or_create($db.as_salsa_database(), || {
|
||||||
|
$db.add_or_lookup_jar_by_type(&$Configuration)
|
||||||
|
});
|
||||||
|
fn_ingredient.fetch($db, key).clone()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! setup_fn {
|
||||||
|
() => {};
|
||||||
|
}
|
|
@ -5,7 +5,7 @@ use crossbeam::atomic::AtomicCell;
|
||||||
use crate::{
|
use crate::{
|
||||||
cycle::CycleRecoveryStrategy,
|
cycle::CycleRecoveryStrategy,
|
||||||
ingredient::{fmt_index, IngredientRequiresReset},
|
ingredient::{fmt_index, IngredientRequiresReset},
|
||||||
key::{DatabaseKeyIndex, DependencyIndex},
|
key::DatabaseKeyIndex,
|
||||||
runtime::local_state::QueryOrigin,
|
runtime::local_state::QueryOrigin,
|
||||||
salsa_struct::SalsaStructInDb,
|
salsa_struct::SalsaStructInDb,
|
||||||
storage::IngredientIndex,
|
storage::IngredientIndex,
|
||||||
|
@ -30,8 +30,6 @@ mod specify;
|
||||||
mod store;
|
mod store;
|
||||||
mod sync;
|
mod sync;
|
||||||
|
|
||||||
pub mod interned;
|
|
||||||
|
|
||||||
pub trait Configuration: Any {
|
pub trait Configuration: Any {
|
||||||
const DEBUG_NAME: &'static str;
|
const DEBUG_NAME: &'static str;
|
||||||
|
|
||||||
|
@ -75,7 +73,11 @@ pub trait Configuration: Any {
|
||||||
/// in a cycle to find out what value it should have.
|
/// in a cycle to find out what value it should have.
|
||||||
///
|
///
|
||||||
/// This invokes the recovery function given by the user.
|
/// This invokes the recovery function given by the user.
|
||||||
fn recover_from_cycle<'db>(db: &'db Self::DbView, cycle: &Cycle, key: Id) -> Self::Output<'db>;
|
fn recover_from_cycle<'db>(
|
||||||
|
db: &'db Self::DbView,
|
||||||
|
cycle: &Cycle,
|
||||||
|
input: Self::Input<'db>,
|
||||||
|
) -> Self::Output<'db>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Function ingredients are the "workhorse" of salsa.
|
/// Function ingredients are the "workhorse" of salsa.
|
||||||
|
|
|
@ -56,7 +56,7 @@ where
|
||||||
crate::cycle::CycleRecoveryStrategy::Fallback => {
|
crate::cycle::CycleRecoveryStrategy::Fallback => {
|
||||||
if let Some(c) = active_query.take_cycle() {
|
if let Some(c) = active_query.take_cycle() {
|
||||||
assert!(c.is(&cycle));
|
assert!(c.is(&cycle));
|
||||||
C::recover_from_cycle(db, &cycle, key)
|
C::recover_from_cycle(db, &cycle, C::id_to_input(db, key))
|
||||||
} else {
|
} else {
|
||||||
// we are not a participant in this cycle
|
// we are not a participant in this cycle
|
||||||
debug_assert!(!cycle
|
debug_assert!(!cycle
|
||||||
|
|
|
@ -1,88 +0,0 @@
|
||||||
//! Helper code for tracked functions that take arbitrary arguments.
|
|
||||||
//! These arguments must be interned to create a salsa id before the
|
|
||||||
//! salsa machinery can execute.
|
|
||||||
|
|
||||||
use std::{any::Any, fmt, hash::Hash, marker::PhantomData};
|
|
||||||
|
|
||||||
use crate::{
|
|
||||||
function, interned, plumbing::CycleRecoveryStrategy, salsa_struct::SalsaStructInDb, Cycle, Id,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub trait Configuration: Any + Copy {
|
|
||||||
const DEBUG_NAME: &'static str;
|
|
||||||
type DbView: ?Sized + crate::Database;
|
|
||||||
type SalsaStruct<'db>: SalsaStructInDb<Self::DbView>;
|
|
||||||
type Input<'db>: Send + Sync + Clone + Hash + Eq;
|
|
||||||
type Output<'db>: fmt::Debug + Send + Sync;
|
|
||||||
const CYCLE_STRATEGY: CycleRecoveryStrategy;
|
|
||||||
fn should_backdate_value(old_value: &Self::Output<'_>, new_value: &Self::Output<'_>) -> bool;
|
|
||||||
fn id_to_input<'db>(db: &'db Self::DbView, key: Id) -> Self::Input<'db>;
|
|
||||||
fn execute<'db>(db: &'db Self::DbView, input: Self::Input<'db>) -> Self::Output<'db>;
|
|
||||||
fn recover_from_cycle<'db>(db: &'db Self::DbView, cycle: &Cycle, key: Id) -> Self::Output<'db>;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct InterningConfiguration<C: Configuration> {
|
|
||||||
phantom: PhantomData<C>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
|
||||||
pub struct InternedData<'db, C: Configuration>(
|
|
||||||
std::ptr::NonNull<interned::ValueStruct<C>>,
|
|
||||||
std::marker::PhantomData<&'db interned::ValueStruct<C>>,
|
|
||||||
);
|
|
||||||
|
|
||||||
impl<C: Configuration> SalsaStructInDb<C::DbView> for InternedData<'_, C> {
|
|
||||||
fn register_dependent_fn(_db: &C::DbView, _index: crate::storage::IngredientIndex) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<C: Configuration> interned::Configuration for C {
|
|
||||||
const DEBUG_NAME: &'static str = C::DEBUG_NAME;
|
|
||||||
|
|
||||||
type Data<'db> = C::Input<'db>;
|
|
||||||
|
|
||||||
type Struct<'db> = InternedData<'db, C>;
|
|
||||||
|
|
||||||
unsafe fn struct_from_raw<'db>(
|
|
||||||
ptr: std::ptr::NonNull<interned::ValueStruct<Self>>,
|
|
||||||
) -> Self::Struct<'db> {
|
|
||||||
InternedData(ptr, std::marker::PhantomData)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn deref_struct(s: Self::Struct<'_>) -> &interned::ValueStruct<Self> {
|
|
||||||
unsafe { s.0.as_ref() }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<C: Configuration> function::Configuration for C {
|
|
||||||
const DEBUG_NAME: &'static str = C::DEBUG_NAME;
|
|
||||||
|
|
||||||
type DbView = C::DbView;
|
|
||||||
|
|
||||||
type SalsaStruct<'db> = InternedData<'db, C>;
|
|
||||||
|
|
||||||
type Input<'db> = C::Input<'db>;
|
|
||||||
|
|
||||||
type Output<'db> = C::Output<'db>;
|
|
||||||
|
|
||||||
const CYCLE_STRATEGY: crate::plumbing::CycleRecoveryStrategy = C::CYCLE_STRATEGY;
|
|
||||||
|
|
||||||
fn should_backdate_value(old_value: &Self::Output<'_>, new_value: &Self::Output<'_>) -> bool {
|
|
||||||
C::should_backdate_value(old_value, new_value)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn id_to_input<'db>(db: &'db Self::DbView, key: crate::Id) -> Self::Input<'db> {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn execute<'db>(db: &'db Self::DbView, input: Self::Input<'db>) -> Self::Output<'db> {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn recover_from_cycle<'db>(
|
|
||||||
db: &'db Self::DbView,
|
|
||||||
cycle: &crate::Cycle,
|
|
||||||
key: crate::Id,
|
|
||||||
) -> Self::Output<'db> {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -66,6 +66,9 @@ pub mod plumbing {
|
||||||
pub use crate::storage::IngredientIndex;
|
pub use crate::storage::IngredientIndex;
|
||||||
pub use crate::storage::Storage;
|
pub use crate::storage::Storage;
|
||||||
|
|
||||||
|
pub use salsa_macro_rules::setup_interned_fn;
|
||||||
|
pub use salsa_macro_rules::unexpected_cycle_recovery;
|
||||||
|
|
||||||
pub mod input {
|
pub mod input {
|
||||||
pub use crate::input::Configuration;
|
pub use crate::input::Configuration;
|
||||||
pub use crate::input::IngredientImpl;
|
pub use crate::input::IngredientImpl;
|
||||||
|
|
|
@ -30,119 +30,33 @@ impl HasLogger for Database {
|
||||||
}
|
}
|
||||||
|
|
||||||
// #[salsa::tracked]
|
// #[salsa::tracked]
|
||||||
// fn identity(db: &dyn Db, input: u32) -> u32 {
|
// fn final_result(db: &dyn Db, input: i32, (b, c): (i32, i32)) -> i32 {
|
||||||
// db.push_log(format!("final_result({:?})", input));
|
// db.push_log(format!("final_result({:?})", input));
|
||||||
// input
|
// input
|
||||||
// }
|
// }
|
||||||
|
|
||||||
fn identity(db: &dyn Db, input: u32) -> u32 {
|
salsa::plumbing::setup_interned_fn!(
|
||||||
use salsa::plumbing as zalsa;
|
vis: ,
|
||||||
|
fn_name: identity,
|
||||||
struct Configuration;
|
db_lt: 'db,
|
||||||
|
Db: Db,
|
||||||
#[derive(Copy, Clone)]
|
db: dbx,
|
||||||
struct InternedData<'db>(
|
input_ids: [input1, input2],
|
||||||
std::ptr::NonNull<zalsa::interned::ValueStruct<Configuration>>,
|
input_pats: [a, (b, c)],
|
||||||
std::marker::PhantomData<&'db zalsa::interned::ValueStruct<Configuration>>,
|
input_tys: [i32, (i32, i32)],
|
||||||
);
|
output_ty: i32,
|
||||||
|
body: {
|
||||||
static FN_CACHE: zalsa::IngredientCache<zalsa::function::IngredientImpl<Configuration>> =
|
dbx.push_log(format!("final_result({a}, {b}, {c})"));
|
||||||
zalsa::IngredientCache::new();
|
a + b * c
|
||||||
|
},
|
||||||
static INTERN_CACHE: zalsa::IngredientCache<zalsa::interned::IngredientImpl<Configuration>> =
|
cycle_recovery_fn: (salsa::plumbing::unexpected_cycle_recovery!),
|
||||||
zalsa::IngredientCache::new();
|
cycle_recovery_strategy: Panic,
|
||||||
|
unused_names: [
|
||||||
impl zalsa::SalsaStructInDb<dyn Db> for InternedData<'_> {
|
zalsa1,
|
||||||
fn register_dependent_fn(_db: &dyn Db, _index: zalsa::IngredientIndex) {}
|
Configuration1,
|
||||||
}
|
InternedData1,
|
||||||
|
FN_CACHE1,
|
||||||
impl zalsa::function::Configuration for Configuration {
|
INTERN_CACHE1,
|
||||||
const DEBUG_NAME: &'static str = "identity";
|
inner1,
|
||||||
|
]
|
||||||
type DbView = dyn Db;
|
);
|
||||||
|
|
||||||
type SalsaStruct<'db> = InternedData<'db>;
|
|
||||||
|
|
||||||
type Input<'db> = u32;
|
|
||||||
|
|
||||||
type Output<'db> = u32;
|
|
||||||
|
|
||||||
const CYCLE_STRATEGY: zalsa::CycleRecoveryStrategy = zalsa::CycleRecoveryStrategy::Panic;
|
|
||||||
|
|
||||||
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: u32) -> Self::Output<'db> {
|
|
||||||
fn inner(db: &dyn Db, input: u32) -> u32 {
|
|
||||||
db.push_log(format!("final_result({:?})", input));
|
|
||||||
input
|
|
||||||
}
|
|
||||||
|
|
||||||
inner(db, input)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn recover_from_cycle<'db>(
|
|
||||||
_db: &'db Self::DbView,
|
|
||||||
_cycle: &zalsa::Cycle,
|
|
||||||
_key: zalsa::Id,
|
|
||||||
) -> Self::Output<'db> {
|
|
||||||
panic!()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn id_to_input<'db>(db: &'db Self::DbView, key: salsa::Id) -> Self::Input<'db> {
|
|
||||||
let ingredient = INTERN_CACHE.get_or_create(db.as_salsa_database(), || {
|
|
||||||
db.add_or_lookup_jar_by_type(&Configuration) + 1
|
|
||||||
});
|
|
||||||
ingredient.data(key).clone()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl zalsa::interned::Configuration for Configuration {
|
|
||||||
const DEBUG_NAME: &'static str = "Configuration";
|
|
||||||
|
|
||||||
type Data<'db> = u32;
|
|
||||||
|
|
||||||
type Struct<'db> = InternedData<'db>;
|
|
||||||
|
|
||||||
unsafe fn struct_from_raw<'db>(
|
|
||||||
ptr: std::ptr::NonNull<zalsa::interned::ValueStruct<Self>>,
|
|
||||||
) -> Self::Struct<'db> {
|
|
||||||
InternedData(ptr, std::marker::PhantomData)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn deref_struct(s: Self::Struct<'_>) -> &zalsa::interned::ValueStruct<Self> {
|
|
||||||
unsafe { s.0.as_ref() }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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,
|
|
||||||
)),
|
|
||||||
Box::new(<zalsa::interned::IngredientImpl<Configuration>>::new(
|
|
||||||
first_index + 1,
|
|
||||||
)),
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let fn_ingredient = FN_CACHE.get_or_create(db.as_salsa_database(), || {
|
|
||||||
db.add_or_lookup_jar_by_type(&Configuration)
|
|
||||||
});
|
|
||||||
let intern_ingredient = INTERN_CACHE.get_or_create(db.as_salsa_database(), || {
|
|
||||||
db.add_or_lookup_jar_by_type(&Configuration) + 1
|
|
||||||
});
|
|
||||||
|
|
||||||
let key = intern_ingredient.intern_id(db.runtime(), input);
|
|
||||||
|
|
||||||
fn_ingredient.fetch(db, key).clone()
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in a new issue