369: Try to fix issue#340 r=XFFXFF a=zjp-CN

(WIP) 

Follow the instructions from https://github.com/salsa-rs/salsa/issues/340#issuecomment-1210153085.

Still not sure what to do with `fmt_index`...

Fix #340

Co-authored-by: zjp <jiping_zhou@foxmail.com>
Co-authored-by: Niko Matsakis <niko@alum.mit.edu>
This commit is contained in:
bors[bot] 2022-08-22 13:42:18 +00:00 committed by GitHub
commit d3f0077d21
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
23 changed files with 244 additions and 155 deletions

View file

@ -248,8 +248,8 @@ fn fix_bad_variable_in_function() {
"#]], "#]],
expect![[r#" expect![[r#"
[ [
"Event: Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: DependencyIndex { ingredient_index: IngredientIndex(15), key_index: Some(Id { value: 1 }) } } }", "Event: Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: parse_statements(0) } }",
"Event: Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: DependencyIndex { ingredient_index: IngredientIndex(18), key_index: Some(Id { value: 1 }) } } }", "Event: Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: type_check_function(0) } }",
] ]
"#]], "#]],
)], )],

View file

@ -48,7 +48,7 @@ fn accumulator_contents(
let struct_ty = &parse_quote! {#struct_name}; let struct_ty = &parse_quote! {#struct_name};
let inherent_impl = inherent_impl(args, struct_ty, data_ty); let inherent_impl = inherent_impl(args, struct_ty, data_ty);
let ingredients_for_impl = ingredients_for_impl(args, struct_ty, data_ty); let ingredients_for_impl = ingredients_for_impl(args, struct_name, data_ty);
let struct_item_out = struct_item_out(args, struct_item, data_ty); let struct_item_out = struct_item_out(args, struct_item, data_ty);
let accumulator_impl = accumulator_impl(args, struct_ty, data_ty); let accumulator_impl = accumulator_impl(args, struct_ty, data_ty);
@ -61,23 +61,20 @@ fn accumulator_contents(
} }
fn data_ty(struct_item: &syn::ItemStruct) -> syn::Result<&syn::Type> { fn data_ty(struct_item: &syn::ItemStruct) -> syn::Result<&syn::Type> {
match &struct_item.fields { if let syn::Fields::Unnamed(fields) = &struct_item.fields {
syn::Fields::Unnamed(fields) => { if fields.unnamed.len() != 1 {
if fields.unnamed.len() != 1 { Err(syn::Error::new(
return Err(syn::Error::new(
struct_item.ident.span(),
"accumulator structs should have only one anonymous field",
));
} else {
Ok(&fields.unnamed[0].ty)
}
}
_ => {
return Err(syn::Error::new(
struct_item.ident.span(), struct_item.ident.span(),
"accumulator structs should have only one anonymous field", "accumulator structs should have only one anonymous field",
)); ))
} else {
Ok(&fields.unnamed[0].ty)
} }
} else {
Err(syn::Error::new(
struct_item.ident.span(),
"accumulator structs should have only one anonymous field",
))
} }
} }
@ -109,10 +106,15 @@ fn inherent_impl(args: &Args, struct_ty: &syn::Type, data_ty: &syn::Type) -> syn
} }
} }
fn ingredients_for_impl(args: &Args, struct_ty: &syn::Type, data_ty: &syn::Type) -> syn::ItemImpl { fn ingredients_for_impl(
args: &Args,
struct_name: &syn::Ident,
data_ty: &syn::Type,
) -> syn::ItemImpl {
let jar_ty = args.jar_ty(); let jar_ty = args.jar_ty();
let debug_name = crate::literal(struct_name);
parse_quote! { parse_quote! {
impl salsa::storage::IngredientsFor for #struct_ty { impl salsa::storage::IngredientsFor for #struct_name {
type Ingredients = salsa::accumulator::AccumulatorIngredient<#data_ty>; type Ingredients = salsa::accumulator::AccumulatorIngredient<#data_ty>;
type Jar = #jar_ty; type Jar = #jar_ty;
@ -130,7 +132,7 @@ fn ingredients_for_impl(args: &Args, struct_ty: &syn::Type, data_ty: &syn::Type)
<_ as salsa::storage::HasIngredientsFor<Self>>::ingredient_mut(jar) <_ as salsa::storage::HasIngredientsFor<Self>>::ingredient_mut(jar)
}, },
); );
salsa::accumulator::AccumulatorIngredient::new(index) salsa::accumulator::AccumulatorIngredient::new(index, #debug_name)
} }
} }
} }

View file

@ -55,10 +55,10 @@ impl syn::parse::Parse for Args {
} }
fn find_storage_field(input: &syn::ItemStruct) -> Result<syn::Ident, &'static str> { fn find_storage_field(input: &syn::ItemStruct) -> Result<syn::Ident, &'static str> {
let storage = format!("storage"); let storage = "storage";
for field in input.fields.iter() { for field in input.fields.iter() {
if let Some(i) = &field.ident { if let Some(i) = &field.ident {
if i.to_string() == storage { if i == storage {
return Ok(i.clone()); return Ok(i.clone());
} }
} else { } else {
@ -159,6 +159,10 @@ fn has_jars_dyn_impl(input: &syn::ItemStruct, storage: &syn::Ident) -> syn::Item
let ingredient = self.#storage.ingredient(ingredient); let ingredient = self.#storage.ingredient(ingredient);
ingredient.salsa_struct_deleted(self, id); ingredient.salsa_struct_deleted(self, id);
} }
fn fmt_index(&self, index: salsa::key::DependencyIndex, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let ingredient = self.#storage.ingredient(index.ingredient_index());
ingredient.fmt_index(index.key_index(), fmt)
}
} }
} }
} }

View file

@ -130,11 +130,14 @@ impl InputStruct {
/// The entity's ingredients include both the main entity ingredient along with a /// The entity's ingredients include both the main entity ingredient along with a
/// function ingredient for each of the value fields. /// function ingredient for each of the value fields.
fn input_ingredients(&self) -> syn::ItemImpl { fn input_ingredients(&self) -> syn::ItemImpl {
use crate::literal;
let ident = self.id_ident(); let ident = self.id_ident();
let field_ty = self.all_field_tys(); let field_ty = self.all_field_tys();
let jar_ty = self.jar_ty(); let jar_ty = self.jar_ty();
let all_field_indices: Vec<Literal> = self.all_field_indices(); let all_field_indices: Vec<Literal> = self.all_field_indices();
let input_index: Literal = self.input_index(); let input_index: Literal = self.input_index();
let debug_name_struct = literal(self.id_ident());
let debug_name_fields: Vec<_> = self.all_field_names().into_iter().map(literal).collect();
parse_quote! { parse_quote! {
impl salsa::storage::IngredientsFor for #ident { impl salsa::storage::IngredientsFor for #ident {
@ -167,7 +170,7 @@ impl InputStruct {
&mut ingredients.#all_field_indices &mut ingredients.#all_field_indices
}, },
); );
salsa::input_field::InputFieldIngredient::new(index) salsa::input_field::InputFieldIngredient::new(index, #debug_name_fields)
}, },
)* )*
{ {
@ -183,7 +186,7 @@ impl InputStruct {
&mut ingredients.#input_index &mut ingredients.#input_index
}, },
); );
salsa::input::InputIngredient::new(index) salsa::input::InputIngredient::new(index, #debug_name_struct)
}, },
) )
} }

View file

@ -120,6 +120,7 @@ impl InternedStruct {
/// For a memoized type, the only ingredient is an `InternedIngredient`. /// For a memoized type, the only ingredient is an `InternedIngredient`.
fn ingredients_for_impl(&self) -> syn::ItemImpl { fn ingredients_for_impl(&self) -> syn::ItemImpl {
let id_ident = self.id_ident(); let id_ident = self.id_ident();
let debug_name = crate::literal(id_ident);
let jar_ty = self.jar_ty(); let jar_ty = self.jar_ty();
let data_ident = self.data_ident(); let data_ident = self.data_ident();
parse_quote! { parse_quote! {
@ -143,7 +144,7 @@ impl InternedStruct {
<_ as salsa::storage::HasIngredientsFor<Self>>::ingredient_mut(jar) <_ as salsa::storage::HasIngredientsFor<Self>>::ingredient_mut(jar)
}, },
); );
salsa::interned::InternedIngredient::new(index) salsa::interned::InternedIngredient::new(index, #debug_name)
} }
} }
} }

View file

@ -25,6 +25,11 @@ macro_rules! parse_quote_spanned {
} }
} }
/// Convert a single Ident to Literal: useful when &'static str is needed.
pub(crate) fn literal(ident: &proc_macro2::Ident) -> proc_macro2::Literal {
proc_macro2::Literal::string(&ident.to_string())
}
mod accumulator; mod accumulator;
mod configuration; mod configuration;
mod db; mod db;

View file

@ -12,7 +12,7 @@ pub(crate) fn tracked(
let args = syn::parse_macro_input!(args as Args); let args = syn::parse_macro_input!(args as Args);
match tracked_fn(args, item_fn) { match tracked_fn(args, item_fn) {
Ok(p) => p.into(), Ok(p) => p.into(),
Err(e) => return e.into_compile_error().into(), Err(e) => e.into_compile_error().into(),
} }
} }
@ -145,7 +145,7 @@ fn fn_configuration(args: &Args, item_fn: &syn::ItemFn) -> Configuration {
let fn_ty = item_fn.sig.ident.clone(); let fn_ty = item_fn.sig.ident.clone();
let indices = (0..item_fn.sig.inputs.len() - 1).map(|i| Literal::usize_unsuffixed(i)); let indices = (0..item_fn.sig.inputs.len() - 1).map(Literal::usize_unsuffixed);
let (cycle_strategy, recover_fn) = if let Some(recovery_fn) = &args.recovery_fn { let (cycle_strategy, recover_fn) = if let Some(recovery_fn) = &args.recovery_fn {
// Create the `recover_from_cycle` function, which (a) maps from the interned id to the actual // Create the `recover_from_cycle` function, which (a) maps from the interned id to the actual
// keys and then (b) invokes the recover function itself. // keys and then (b) invokes the recover function itself.
@ -181,7 +181,7 @@ fn fn_configuration(args: &Args, item_fn: &syn::ItemFn) -> Configuration {
// Create the `execute` function, which (a) maps from the interned id to the actual // Create the `execute` function, which (a) maps from the interned id to the actual
// keys and then (b) invokes the function itself (which we embed within). // keys and then (b) invokes the function itself (which we embed within).
let indices = (0..item_fn.sig.inputs.len() - 1).map(|i| Literal::usize_unsuffixed(i)); let indices = (0..item_fn.sig.inputs.len() - 1).map(Literal::usize_unsuffixed);
let execute_fn = parse_quote! { let execute_fn = parse_quote! {
fn execute(__db: &salsa::function::DynDb<Self>, __id: Self::Key) -> Self::Value { fn execute(__db: &salsa::function::DynDb<Self>, __id: Self::Key) -> Self::Value {
#inner_fn #inner_fn
@ -212,6 +212,7 @@ fn ingredients_for_impl(
config_ty: &syn::Type, config_ty: &syn::Type,
) -> syn::ItemImpl { ) -> syn::ItemImpl {
let jar_ty = args.jar_ty(); let jar_ty = args.jar_ty();
let debug_name = crate::literal(&item_fn.sig.ident);
let intern_map: syn::Expr = if requires_interning(item_fn) { let intern_map: syn::Expr = if requires_interning(item_fn) {
parse_quote! { parse_quote! {
@ -230,7 +231,7 @@ fn ingredients_for_impl(
&mut ingredients.intern_map &mut ingredients.intern_map
} }
); );
salsa::interned::InternedIngredient::new(index) salsa::interned::InternedIngredient::new(index, #debug_name)
} }
} }
} else { } else {
@ -242,6 +243,9 @@ fn ingredients_for_impl(
// set 0 as default to disable LRU // set 0 as default to disable LRU
let lru = args.lru.unwrap_or(0); let lru = args.lru.unwrap_or(0);
// get the name of the function as a string literal
let debug_name = crate::literal(&item_fn.sig.ident);
parse_quote! { parse_quote! {
impl salsa::storage::IngredientsFor for #config_ty { impl salsa::storage::IngredientsFor for #config_ty {
type Ingredients = Self; type Ingredients = Self;
@ -268,7 +272,7 @@ fn ingredients_for_impl(
<_ as salsa::storage::HasIngredientsFor<Self::Ingredients>>::ingredient_mut(jar); <_ as salsa::storage::HasIngredientsFor<Self::Ingredients>>::ingredient_mut(jar);
&mut ingredients.function &mut ingredients.function
}); });
let ingredient = salsa::function::FunctionIngredient::new(index); let ingredient = salsa::function::FunctionIngredient::new(index, #debug_name);
ingredient.set_capacity(#lru); ingredient.set_capacity(#lru);
ingredient ingredient
} }
@ -520,9 +524,7 @@ fn make_fn_return_ref(mut ref_getter_fn: syn::ItemFn) -> syn::Result<syn::ItemFn
/// then modifies the item function so that it is called `'__db` and returns that. /// then modifies the item function so that it is called `'__db` and returns that.
fn db_lifetime_and_ty(func: &mut syn::ItemFn) -> syn::Result<(syn::Lifetime, &syn::Type)> { fn db_lifetime_and_ty(func: &mut syn::ItemFn) -> syn::Result<(syn::Lifetime, &syn::Type)> {
match &mut func.sig.inputs[0] { match &mut func.sig.inputs[0] {
syn::FnArg::Receiver(r) => { syn::FnArg::Receiver(r) => Err(syn::Error::new(r.span(), "expected database, not self")),
return Err(syn::Error::new(r.span(), "expected database, not self"))
}
syn::FnArg::Typed(pat_ty) => match &mut *pat_ty.ty { syn::FnArg::Typed(pat_ty) => match &mut *pat_ty.ty {
syn::Type::Reference(ty) => match &ty.lifetime { syn::Type::Reference(ty) => match &ty.lifetime {
Some(lt) => Ok((lt.clone(), &pat_ty.ty)), Some(lt) => Ok((lt.clone(), &pat_ty.ty)),
@ -550,12 +552,10 @@ fn db_lifetime_and_ty(func: &mut syn::ItemFn) -> syn::Result<(syn::Lifetime, &sy
Ok((db_lifetime, &pat_ty.ty)) Ok((db_lifetime, &pat_ty.ty))
} }
}, },
_ => { _ => Err(syn::Error::new(
return Err(syn::Error::new( pat_ty.span(),
pat_ty.span(), "expected database to be a `&` type",
"expected database to be a `&` type", )),
))
}
}, },
} }
} }
@ -607,7 +607,7 @@ fn accumulated_fn(
/// * the name(s) of the key arguments /// * the name(s) of the key arguments
fn fn_args(item_fn: &syn::ItemFn) -> syn::Result<(proc_macro2::Ident, Vec<proc_macro2::Ident>)> { fn fn_args(item_fn: &syn::ItemFn) -> syn::Result<(proc_macro2::Ident, Vec<proc_macro2::Ident>)> {
// Check that we have no receiver and that all argments have names // Check that we have no receiver and that all argments have names
if item_fn.sig.inputs.len() == 0 { if item_fn.sig.inputs.is_empty() {
return Err(syn::Error::new( return Err(syn::Error::new(
item_fn.sig.span(), item_fn.sig.span(),
"method needs a database argument", "method needs a database argument",

View file

@ -153,12 +153,15 @@ impl TrackedStruct {
/// The tracked struct's ingredients include both the main tracked struct ingredient along with a /// The tracked struct's ingredients include both the main tracked struct ingredient along with a
/// function ingredient for each of the value fields. /// function ingredient for each of the value fields.
fn tracked_struct_ingredients(&self, config_structs: &[syn::ItemStruct]) -> syn::ItemImpl { fn tracked_struct_ingredients(&self, config_structs: &[syn::ItemStruct]) -> syn::ItemImpl {
use crate::literal;
let ident = self.id_ident(); let ident = self.id_ident();
let jar_ty = self.jar_ty(); let jar_ty = self.jar_ty();
let id_field_tys: Vec<&syn::Type> = self.id_fields().map(SalsaField::ty).collect(); let id_field_tys: Vec<&syn::Type> = self.id_fields().map(SalsaField::ty).collect();
let value_field_indices: Vec<Literal> = self.value_field_indices(); let value_field_indices: Vec<Literal> = self.value_field_indices();
let tracked_struct_index: Literal = self.tracked_struct_index(); let tracked_struct_index: Literal = self.tracked_struct_index();
let config_struct_names = config_structs.iter().map(|s| &s.ident); let config_struct_names = config_structs.iter().map(|s| &s.ident);
let debug_name_struct = literal(self.id_ident());
let debug_name_fields: Vec<_> = self.all_field_names().into_iter().map(literal).collect();
parse_quote! { parse_quote! {
impl salsa::storage::IngredientsFor for #ident { impl salsa::storage::IngredientsFor for #ident {
@ -191,7 +194,7 @@ impl TrackedStruct {
&mut ingredients.#value_field_indices &mut ingredients.#value_field_indices
}, },
); );
salsa::function::FunctionIngredient::new(index) salsa::function::FunctionIngredient::new(index, #debug_name_fields)
}, },
)* )*
{ {
@ -207,7 +210,7 @@ impl TrackedStruct {
&mut ingredients.#tracked_struct_index &mut ingredients.#tracked_struct_index
}, },
); );
salsa::tracked_struct::TrackedStructIngredient::new(index) salsa::tracked_struct::TrackedStructIngredient::new(index, #debug_name_struct)
}, },
) )
} }
@ -279,14 +282,14 @@ impl TrackedStruct {
/// of the function ingredients within that tuple. /// of the function ingredients within that tuple.
fn value_field_indices(&self) -> Vec<Literal> { fn value_field_indices(&self) -> Vec<Literal> {
(0..self.value_fields().count()) (0..self.value_fields().count())
.map(|i| Literal::usize_unsuffixed(i)) .map(Literal::usize_unsuffixed)
.collect() .collect()
} }
/// Indices of each of the id fields /// Indices of each of the id fields
fn id_field_indices(&self) -> Vec<Literal> { fn id_field_indices(&self) -> Vec<Literal> {
(0..self.id_fields().count()) (0..self.id_fields().count())
.map(|i| Literal::usize_unsuffixed(i)) .map(Literal::usize_unsuffixed)
.collect() .collect()
} }
} }

View file

@ -1,9 +1,11 @@
//! Basic test of accumulator functionality. //! Basic test of accumulator functionality.
use std::fmt;
use crate::{ use crate::{
cycle::CycleRecoveryStrategy, cycle::CycleRecoveryStrategy,
hash::FxDashMap, hash::FxDashMap,
ingredient::{Ingredient, IngredientRequiresReset}, ingredient::{fmt_index, Ingredient, IngredientRequiresReset},
key::DependencyIndex, key::DependencyIndex,
runtime::local_state::QueryOrigin, runtime::local_state::QueryOrigin,
storage::HasJar, storage::HasJar,
@ -21,6 +23,7 @@ pub trait Accumulator {
pub struct AccumulatorIngredient<Data: Clone> { pub struct AccumulatorIngredient<Data: Clone> {
index: IngredientIndex, index: IngredientIndex,
map: FxDashMap<DatabaseKeyIndex, AccumulatedValues<Data>>, map: FxDashMap<DatabaseKeyIndex, AccumulatedValues<Data>>,
debug_name: &'static str,
} }
struct AccumulatedValues<Data> { struct AccumulatedValues<Data> {
@ -29,10 +32,11 @@ struct AccumulatedValues<Data> {
} }
impl<Data: Clone> AccumulatorIngredient<Data> { impl<Data: Clone> AccumulatorIngredient<Data> {
pub fn new(index: IngredientIndex) -> Self { pub fn new(index: IngredientIndex, debug_name: &'static str) -> Self {
Self { Self {
map: FxDashMap::default(), map: FxDashMap::default(),
index, index,
debug_name,
} }
} }
@ -148,6 +152,10 @@ where
fn salsa_struct_deleted(&self, _db: &DB, _id: crate::Id) { fn salsa_struct_deleted(&self, _db: &DB, _id: crate::Id) {
panic!("unexpected call: accumulator is not registered as a dependent fn"); panic!("unexpected call: accumulator is not registered as a dependent fn");
} }
fn fmt_index(&self, index: Option<crate::Id>, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt_index(self.debug_name, index, fmt)
}
} }
impl<Data> IngredientRequiresReset for AccumulatorIngredient<Data> impl<Data> IngredientRequiresReset for AccumulatorIngredient<Data>

View file

@ -1,11 +1,11 @@
use std::sync::Arc; use std::{fmt, sync::Arc};
use arc_swap::ArcSwap; use arc_swap::ArcSwap;
use crossbeam::{atomic::AtomicCell, queue::SegQueue}; use crossbeam::{atomic::AtomicCell, queue::SegQueue};
use crate::{ use crate::{
cycle::CycleRecoveryStrategy, cycle::CycleRecoveryStrategy,
ingredient::IngredientRequiresReset, ingredient::{fmt_index, IngredientRequiresReset},
jar::Jar, jar::Jar,
key::{DatabaseKeyIndex, DependencyIndex}, key::{DatabaseKeyIndex, DependencyIndex},
runtime::local_state::QueryOrigin, runtime::local_state::QueryOrigin,
@ -71,6 +71,8 @@ pub struct FunctionIngredient<C: Configuration> {
/// Set to true once we invoke `register_dependent_fn` for `C::SalsaStruct`. /// Set to true once we invoke `register_dependent_fn` for `C::SalsaStruct`.
/// Prevents us from registering more than once. /// Prevents us from registering more than once.
registered: AtomicCell<bool>, registered: AtomicCell<bool>,
debug_name: &'static str,
} }
pub trait Configuration { pub trait Configuration {
@ -87,7 +89,7 @@ pub trait Configuration {
type Key: AsId; type Key: AsId;
/// The value computed by the function. /// The value computed by the function.
type Value: std::fmt::Debug; type Value: fmt::Debug;
/// Determines whether this function can recover from being a participant in a cycle /// Determines whether this function can recover from being a participant in a cycle
/// (and, if so, how). /// (and, if so, how).
@ -137,7 +139,7 @@ impl<C> FunctionIngredient<C>
where where
C: Configuration, C: Configuration,
{ {
pub fn new(index: IngredientIndex) -> Self { pub fn new(index: IngredientIndex, debug_name: &'static str) -> Self {
Self { Self {
index, index,
memo_map: memo::MemoMap::default(), memo_map: memo::MemoMap::default(),
@ -145,6 +147,7 @@ where
sync_map: Default::default(), sync_map: Default::default(),
deleted_entries: Default::default(), deleted_entries: Default::default(),
registered: Default::default(), registered: Default::default(),
debug_name,
} }
} }
@ -269,6 +272,10 @@ where
} }
} }
} }
fn fmt_index(&self, index: Option<crate::Id>, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt_index(self.debug_name, index, fmt)
}
} }
impl<C> IngredientRequiresReset for FunctionIngredient<C> impl<C> IngredientRequiresReset for FunctionIngredient<C>

View file

@ -1,3 +1,5 @@
use std::fmt;
use crate::{ use crate::{
cycle::CycleRecoveryStrategy, key::DependencyIndex, runtime::local_state::QueryOrigin, cycle::CycleRecoveryStrategy, key::DependencyIndex, runtime::local_state::QueryOrigin,
DatabaseKeyIndex, Id, DatabaseKeyIndex, Id,
@ -7,11 +9,13 @@ use super::Revision;
/// "Ingredients" are the bits of data that are stored within the database to make salsa work. /// "Ingredients" are the bits of data that are stored within the database to make salsa work.
/// Each jar will define some number of ingredients that it requires. /// Each jar will define some number of ingredients that it requires.
/// Each use salsa macro (e.g., `#[salsa::tracked]`, `#[salsa::interned]`) adds one or more ingredients to the jar struct /// Each use salsa macro (e.g., `#[salsa::tracked]`, `#[salsa::interned]`) adds one or more
/// that together are used to create the salsa concept. /// ingredients to the jar struct that together are used to create the salsa concept.
/// For example, a tracked struct defines a [`crate::interned::InternedIngredient`] to store its identity /// For example, a tracked struct defines a [`crate::interned::InternedIngredient`] to store
/// plus [`crate::function::FunctionIngredient`] values to store its fields. /// its identity plus [`crate::function::FunctionIngredient`] values to store its fields.
/// The exact ingredients are determined by [`IngredientsFor`](`crate::storage::IngredientsFor`) implementations generated by the macro. /// The exact ingredients are determined by
/// [`IngredientsFor`](`crate::storage::IngredientsFor`) implementations generated by the
/// macro.
pub trait Ingredient<DB: ?Sized> { pub trait Ingredient<DB: ?Sized> {
/// If this ingredient is a participant in a cycle, what is its cycle recovery strategy? /// If this ingredient is a participant in a cycle, what is its cycle recovery strategy?
/// (Really only relevant to [`crate::function::FunctionIngredient`], /// (Really only relevant to [`crate::function::FunctionIngredient`],
@ -25,7 +29,8 @@ pub trait Ingredient<DB: ?Sized> {
fn origin(&self, key_index: Id) -> Option<QueryOrigin>; fn origin(&self, key_index: Id) -> Option<QueryOrigin>;
/// Invoked when the value `output_key` should be marked as valid in the current revision. /// Invoked when the value `output_key` should be marked as valid in the current revision.
/// This occurs because the value for `executor`, which generated it, was marked as valid in the current revision. /// This occurs because the value for `executor`, which generated it, was marked as valid
/// in the current revision.
fn mark_validated_output(&self, db: &DB, executor: DatabaseKeyIndex, output_key: Option<Id>); fn mark_validated_output(&self, db: &DB, executor: DatabaseKeyIndex, output_key: Option<Id>);
/// Invoked when the value `stale_output` was output by `executor` in a previous /// Invoked when the value `stale_output` was output by `executor` in a previous
@ -46,19 +51,36 @@ pub trait Ingredient<DB: ?Sized> {
fn salsa_struct_deleted(&self, db: &DB, id: Id); fn salsa_struct_deleted(&self, db: &DB, id: Id);
/// Invoked when a new revision is about to start. /// Invoked when a new revision is about to start.
/// This moment is important because it means that we have an `&mut`-reference to the database, /// This moment is important because it means that we have an `&mut`-reference to the
/// and hence any pre-existing `&`-references must have expired. /// database, and hence any pre-existing `&`-references must have expired.
/// Many ingredients, given an `&'db`-reference to the database, /// Many ingredients, given an `&'db`-reference to the database,
/// use unsafe code to return `&'db`-references to internal values. /// use unsafe code to return `&'db`-references to internal values.
/// The backing memory for those values can only be freed once an `&mut`-reference to the database is created. /// The backing memory for those values can only be freed once an `&mut`-reference to the
/// database is created.
/// ///
/// **Important:** to actually receive resets, the ingredient must set /// **Important:** to actually receive resets, the ingredient must set
/// [`IngredientRequiresReset::RESET_ON_NEW_REVISION`] to true. /// [`IngredientRequiresReset::RESET_ON_NEW_REVISION`] to true.
fn reset_for_new_revision(&mut self); fn reset_for_new_revision(&mut self);
fn fmt_index(&self, index: Option<crate::Id>, fmt: &mut fmt::Formatter<'_>) -> fmt::Result;
}
/// A helper function to show human readable fmt.
pub(crate) fn fmt_index(
debug_name: &str,
id: Option<Id>,
fmt: &mut fmt::Formatter<'_>,
) -> fmt::Result {
if let Some(i) = id {
write!(fmt, "{}({})", debug_name, u32::from(i))
} else {
write!(fmt, "{}()", debug_name)
}
} }
/// Defines a const indicating if an ingredient needs to be reset each round. /// Defines a const indicating if an ingredient needs to be reset each round.
/// This const probably *should* be a member of `Ingredient` trait but then `Ingredient` would not be dyn-safe. /// This const probably *should* be a member of `Ingredient` trait but then `Ingredient` would
/// not be dyn-safe.
pub trait IngredientRequiresReset { pub trait IngredientRequiresReset {
/// If this is true, then `reset_for_new_revision` will be called every new revision. /// If this is true, then `reset_for_new_revision` will be called every new revision.
const RESET_ON_NEW_REVISION: bool; const RESET_ON_NEW_REVISION: bool;

View file

@ -1,6 +1,8 @@
use std::fmt;
use crate::{ use crate::{
cycle::CycleRecoveryStrategy, cycle::CycleRecoveryStrategy,
ingredient::{Ingredient, IngredientRequiresReset}, ingredient::{fmt_index, Ingredient, IngredientRequiresReset},
key::{DatabaseKeyIndex, DependencyIndex}, key::{DatabaseKeyIndex, DependencyIndex},
runtime::{local_state::QueryOrigin, Runtime}, runtime::{local_state::QueryOrigin, Runtime},
AsId, IngredientIndex, Revision, AsId, IngredientIndex, Revision,
@ -15,6 +17,7 @@ where
{ {
ingredient_index: IngredientIndex, ingredient_index: IngredientIndex,
counter: u32, counter: u32,
debug_name: &'static str,
_phantom: std::marker::PhantomData<Id>, _phantom: std::marker::PhantomData<Id>,
} }
@ -22,10 +25,11 @@ impl<Id> InputIngredient<Id>
where where
Id: InputId, Id: InputId,
{ {
pub fn new(index: IngredientIndex) -> Self { pub fn new(index: IngredientIndex, debug_name: &'static str) -> Self {
Self { Self {
ingredient_index: index, ingredient_index: index,
counter: Default::default(), counter: Default::default(),
debug_name,
_phantom: std::marker::PhantomData, _phantom: std::marker::PhantomData,
} }
} }
@ -95,6 +99,10 @@ where
"unexpected call: input ingredients do not register for salsa struct deletion events" "unexpected call: input ingredients do not register for salsa struct deletion events"
); );
} }
fn fmt_index(&self, index: Option<crate::Id>, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt_index(self.debug_name, index, fmt)
}
} }
impl<Id> IngredientRequiresReset for InputIngredient<Id> impl<Id> IngredientRequiresReset for InputIngredient<Id>

View file

@ -1,10 +1,11 @@
use crate::cycle::CycleRecoveryStrategy; use crate::cycle::CycleRecoveryStrategy;
use crate::ingredient::{Ingredient, IngredientRequiresReset}; use crate::ingredient::{fmt_index, Ingredient, IngredientRequiresReset};
use crate::key::DependencyIndex; use crate::key::DependencyIndex;
use crate::runtime::local_state::QueryOrigin; use crate::runtime::local_state::QueryOrigin;
use crate::runtime::StampedValue; use crate::runtime::StampedValue;
use crate::{AsId, DatabaseKeyIndex, Durability, Id, IngredientIndex, Revision, Runtime}; use crate::{AsId, DatabaseKeyIndex, Durability, Id, IngredientIndex, Revision, Runtime};
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
use std::fmt;
use std::hash::Hash; use std::hash::Hash;
/// Ingredient used to represent the fields of a `#[salsa::input]`. /// Ingredient used to represent the fields of a `#[salsa::input]`.
@ -15,16 +16,18 @@ use std::hash::Hash;
pub struct InputFieldIngredient<K, F> { pub struct InputFieldIngredient<K, F> {
index: IngredientIndex, index: IngredientIndex,
map: FxHashMap<K, StampedValue<F>>, map: FxHashMap<K, StampedValue<F>>,
debug_name: &'static str,
} }
impl<K, F> InputFieldIngredient<K, F> impl<K, F> InputFieldIngredient<K, F>
where where
K: Eq + Hash + AsId, K: Eq + Hash + AsId,
{ {
pub fn new(index: IngredientIndex) -> Self { pub fn new(index: IngredientIndex, debug_name: &'static str) -> Self {
Self { Self {
index, index,
map: Default::default(), map: Default::default(),
debug_name,
} }
} }
@ -113,6 +116,10 @@ where
fn reset_for_new_revision(&mut self) { fn reset_for_new_revision(&mut self) {
panic!("unexpected call: input fields don't register for resets"); panic!("unexpected call: input fields don't register for resets");
} }
fn fmt_index(&self, index: Option<crate::Id>, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt_index(self.debug_name, index, fmt)
}
} }
impl<K, F> IngredientRequiresReset for InputFieldIngredient<K, F> impl<K, F> IngredientRequiresReset for InputFieldIngredient<K, F>

View file

@ -1,11 +1,12 @@
use crossbeam::atomic::AtomicCell; use crossbeam::atomic::AtomicCell;
use crossbeam::queue::SegQueue; use crossbeam::queue::SegQueue;
use std::fmt;
use std::hash::Hash; use std::hash::Hash;
use std::marker::PhantomData; use std::marker::PhantomData;
use crate::durability::Durability; use crate::durability::Durability;
use crate::id::AsId; use crate::id::AsId;
use crate::ingredient::IngredientRequiresReset; use crate::ingredient::{fmt_index, IngredientRequiresReset};
use crate::key::DependencyIndex; use crate::key::DependencyIndex;
use crate::runtime::local_state::QueryOrigin; use crate::runtime::local_state::QueryOrigin;
use crate::runtime::Runtime; use crate::runtime::Runtime;
@ -54,6 +55,8 @@ pub struct InternedIngredient<Id: InternedId, Data: InternedData> {
/// `&db` reference. This queue itself is not freed until we have an `&mut db` reference, /// `&db` reference. This queue itself is not freed until we have an `&mut db` reference,
/// guaranteeing that there are no more references to it. /// guaranteeing that there are no more references to it.
deleted_entries: SegQueue<Box<Data>>, deleted_entries: SegQueue<Box<Data>>,
debug_name: &'static str,
} }
impl<Id, Data> InternedIngredient<Id, Data> impl<Id, Data> InternedIngredient<Id, Data>
@ -61,7 +64,7 @@ where
Id: InternedId, Id: InternedId,
Data: InternedData, Data: InternedData,
{ {
pub fn new(ingredient_index: IngredientIndex) -> Self { pub fn new(ingredient_index: IngredientIndex, debug_name: &'static str) -> Self {
Self { Self {
ingredient_index, ingredient_index,
key_map: Default::default(), key_map: Default::default(),
@ -69,6 +72,7 @@ where
counter: AtomicCell::default(), counter: AtomicCell::default(),
reset_at: Revision::start(), reset_at: Revision::start(),
deleted_entries: Default::default(), deleted_entries: Default::default(),
debug_name,
} }
} }
@ -234,6 +238,10 @@ where
fn salsa_struct_deleted(&self, _db: &DB, _id: crate::Id) { fn salsa_struct_deleted(&self, _db: &DB, _id: crate::Id) {
panic!("unexpected call: interned ingredients do not register for salsa struct deletion events"); panic!("unexpected call: interned ingredients do not register for salsa struct deletion events");
} }
fn fmt_index(&self, index: Option<crate::Id>, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt_index(self.debug_name, index, fmt)
}
} }
impl<Id, Data> IngredientRequiresReset for InternedIngredient<Id, Data> impl<Id, Data> IngredientRequiresReset for InternedIngredient<Id, Data>

View file

@ -38,8 +38,8 @@ impl<Db> crate::debug::DebugWithDb<Db> for DependencyIndex
where where
Db: ?Sized + Database, Db: ?Sized + Database,
{ {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>, _db: &Db) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>, db: &Db) -> std::fmt::Result {
write!(f, "{:?}", *self) // FIXME db.fmt_index(*self, f)
} }
} }

View file

@ -1,4 +1,4 @@
use std::sync::Arc; use std::{fmt, sync::Arc};
use parking_lot::Condvar; use parking_lot::Condvar;
@ -220,6 +220,8 @@ pub trait HasJarsDyn {
/// as a dependent function using /// as a dependent function using
/// [`SalsaStructInDb::register_dependent_fn`](`crate::salsa_struct::SalsaStructInDb::register_dependent_fn`). /// [`SalsaStructInDb::register_dependent_fn`](`crate::salsa_struct::SalsaStructInDb::register_dependent_fn`).
fn salsa_struct_deleted(&self, ingredient: IngredientIndex, id: Id); fn salsa_struct_deleted(&self, ingredient: IngredientIndex, id: Id);
fn fmt_index(&self, index: DependencyIndex, fmt: &mut fmt::Formatter<'_>) -> fmt::Result;
} }
// ANCHOR_END: HasJarsDyn // ANCHOR_END: HasJarsDyn

View file

@ -1,6 +1,8 @@
use std::fmt;
use crate::{ use crate::{
cycle::CycleRecoveryStrategy, cycle::CycleRecoveryStrategy,
ingredient::{Ingredient, IngredientRequiresReset}, ingredient::{fmt_index, Ingredient, IngredientRequiresReset},
ingredient_list::IngredientList, ingredient_list::IngredientList,
interned::{InternedData, InternedId, InternedIngredient}, interned::{InternedData, InternedId, InternedIngredient},
key::{DatabaseKeyIndex, DependencyIndex}, key::{DatabaseKeyIndex, DependencyIndex},
@ -42,6 +44,8 @@ where
/// each of these functions will be notified /// each of these functions will be notified
/// so they can remove any data tied to that instance. /// so they can remove any data tied to that instance.
dependent_fns: IngredientList, dependent_fns: IngredientList,
debug_name: &'static str,
} }
#[derive(Debug, PartialEq, Eq, Hash, PartialOrd, Ord, Copy, Clone)] #[derive(Debug, PartialEq, Eq, Hash, PartialOrd, Ord, Copy, Clone)]
@ -59,10 +63,11 @@ where
Id: TrackedStructId, Id: TrackedStructId,
Data: TrackedStructData, Data: TrackedStructData,
{ {
pub fn new(index: IngredientIndex) -> Self { pub fn new(index: IngredientIndex, debug_name: &'static str) -> Self {
Self { Self {
interned: InternedIngredient::new(index), interned: InternedIngredient::new(index, debug_name),
dependent_fns: IngredientList::new(), dependent_fns: IngredientList::new(),
debug_name,
} }
} }
@ -175,6 +180,10 @@ where
fn salsa_struct_deleted(&self, _db: &DB, _id: crate::Id) { fn salsa_struct_deleted(&self, _db: &DB, _id: crate::Id) {
panic!("unexpected call: interned ingredients do not register for salsa struct deletion events"); panic!("unexpected call: interned ingredients do not register for salsa struct deletion events");
} }
fn fmt_index(&self, index: Option<crate::Id>, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt_index(self.debug_name, index, fmt)
}
} }
impl<Id, Data> IngredientRequiresReset for TrackedStructIngredient<Id, Data> impl<Id, Data> IngredientRequiresReset for TrackedStructIngredient<Id, Data>

0
rustfmt.toml Normal file
View file

View file

@ -190,8 +190,8 @@ fn cycle_memoized() {
let cycle = extract_cycle(|| memoized_a(&db, input)); let cycle = extract_cycle(|| memoized_a(&db, input));
let expected = expect![[r#" let expected = expect![[r#"
[ [
"DependencyIndex { ingredient_index: IngredientIndex(1), key_index: Some(Id { value: 1 }) }", "memoized_a(0)",
"DependencyIndex { ingredient_index: IngredientIndex(2), key_index: Some(Id { value: 1 }) }", "memoized_b(0)",
] ]
"#]]; "#]];
expected.assert_debug_eq(&cycle.all_participants(&db)); expected.assert_debug_eq(&cycle.all_participants(&db));
@ -204,8 +204,8 @@ fn cycle_volatile() {
let cycle = extract_cycle(|| volatile_a(&db, input)); let cycle = extract_cycle(|| volatile_a(&db, input));
let expected = expect![[r#" let expected = expect![[r#"
[ [
"DependencyIndex { ingredient_index: IngredientIndex(3), key_index: Some(Id { value: 1 }) }", "volatile_a(0)",
"DependencyIndex { ingredient_index: IngredientIndex(4), key_index: Some(Id { value: 1 }) }", "volatile_b(0)",
] ]
"#]]; "#]];
expected.assert_debug_eq(&cycle.all_participants(&db)); expected.assert_debug_eq(&cycle.all_participants(&db));
@ -233,8 +233,8 @@ fn inner_cycle() {
assert!(err.is_err()); assert!(err.is_err());
let expected = expect![[r#" let expected = expect![[r#"
[ [
"DependencyIndex { ingredient_index: IngredientIndex(9), key_index: Some(Id { value: 1 }) }", "cycle_a(0)",
"DependencyIndex { ingredient_index: IngredientIndex(10), key_index: Some(Id { value: 1 }) }", "cycle_b(0)",
] ]
"#]]; "#]];
expected.assert_debug_eq(&err.unwrap_err().cycle); expected.assert_debug_eq(&err.unwrap_err().cycle);
@ -306,8 +306,8 @@ fn cycle_mixed_1() {
let expected = expect![[r#" let expected = expect![[r#"
[ [
"DependencyIndex { ingredient_index: IngredientIndex(10), key_index: Some(Id { value: 1 }) }", "cycle_b(0)",
"DependencyIndex { ingredient_index: IngredientIndex(11), key_index: Some(Id { value: 1 }) }", "cycle_c(0)",
] ]
"#]]; "#]];
expected.assert_debug_eq(&cycle_c(&db, abc).unwrap_err().cycle); expected.assert_debug_eq(&cycle_c(&db, abc).unwrap_err().cycle);
@ -325,9 +325,9 @@ fn cycle_mixed_2() {
let abc = ABC::new(&mut db, CycleQuery::B, CycleQuery::C, CycleQuery::A); let abc = ABC::new(&mut db, CycleQuery::B, CycleQuery::C, CycleQuery::A);
let expected = expect![[r#" let expected = expect![[r#"
[ [
"DependencyIndex { ingredient_index: IngredientIndex(9), key_index: Some(Id { value: 1 }) }", "cycle_a(0)",
"DependencyIndex { ingredient_index: IngredientIndex(10), key_index: Some(Id { value: 1 }) }", "cycle_b(0)",
"DependencyIndex { ingredient_index: IngredientIndex(11), key_index: Some(Id { value: 1 }) }", "cycle_c(0)",
] ]
"#]]; "#]];
expected.assert_debug_eq(&cycle_a(&db, abc).unwrap_err().cycle); expected.assert_debug_eq(&cycle_a(&db, abc).unwrap_err().cycle);
@ -352,12 +352,12 @@ fn cycle_deterministic_order() {
let expected = expect![[r#" let expected = expect![[r#"
( (
[ [
"DependencyIndex { ingredient_index: IngredientIndex(9), key_index: Some(Id { value: 1 }) }", "cycle_a(0)",
"DependencyIndex { ingredient_index: IngredientIndex(10), key_index: Some(Id { value: 1 }) }", "cycle_b(0)",
], ],
[ [
"DependencyIndex { ingredient_index: IngredientIndex(9), key_index: Some(Id { value: 1 }) }", "cycle_a(0)",
"DependencyIndex { ingredient_index: IngredientIndex(10), key_index: Some(Id { value: 1 }) }", "cycle_b(0)",
], ],
) )
"#]]; "#]];
@ -387,16 +387,16 @@ fn cycle_multiple() {
let expected = expect![[r#" let expected = expect![[r#"
( (
[ [
"DependencyIndex { ingredient_index: IngredientIndex(9), key_index: Some(Id { value: 1 }) }", "cycle_a(0)",
"DependencyIndex { ingredient_index: IngredientIndex(10), key_index: Some(Id { value: 1 }) }", "cycle_b(0)",
], ],
[ [
"DependencyIndex { ingredient_index: IngredientIndex(9), key_index: Some(Id { value: 1 }) }", "cycle_a(0)",
"DependencyIndex { ingredient_index: IngredientIndex(10), key_index: Some(Id { value: 1 }) }", "cycle_b(0)",
], ],
[ [
"DependencyIndex { ingredient_index: IngredientIndex(9), key_index: Some(Id { value: 1 }) }", "cycle_a(0)",
"DependencyIndex { ingredient_index: IngredientIndex(10), key_index: Some(Id { value: 1 }) }", "cycle_b(0)",
], ],
) )
"#]]; "#]];
@ -420,7 +420,7 @@ fn cycle_recovery_set_but_not_participating() {
let r = extract_cycle(|| drop(cycle_a(&db, abc))); let r = extract_cycle(|| drop(cycle_a(&db, abc)));
let expected = expect![[r#" let expected = expect![[r#"
[ [
"DependencyIndex { ingredient_index: IngredientIndex(11), key_index: Some(Id { value: 1 }) }", "cycle_c(0)",
] ]
"#]]; "#]];
expected.assert_debug_eq(&r.all_participants(&db)); expected.assert_debug_eq(&r.all_participants(&db));

View file

@ -122,13 +122,13 @@ fn basic() {
db.assert_logs(expect![[r#" db.assert_logs(expect![[r#"
[ [
"intermediate_result(MyInput(Id { value: 1 }))", "intermediate_result(MyInput(Id { value: 1 }))",
"salsa_event(WillDiscardStaleOutput { execute_key: DependencyIndex { ingredient_index: IngredientIndex(5), key_index: Some(Id { value: 1 }) }, output_key: DependencyIndex { ingredient_index: IngredientIndex(3), key_index: Some(Id { value: 3 }) } })", "salsa_event(WillDiscardStaleOutput { execute_key: create_tracked_structs(0), output_key: MyTracked(2) })",
"salsa_event(DidDiscard { key: DependencyIndex { ingredient_index: IngredientIndex(3), key_index: Some(Id { value: 3 }) } })", "salsa_event(DidDiscard { key: MyTracked(2) })",
"salsa_event(DidDiscard { key: DependencyIndex { ingredient_index: IngredientIndex(2), key_index: Some(Id { value: 3 }) } })", "salsa_event(DidDiscard { key: field(2) })",
"salsa_event(DidDiscard { key: DependencyIndex { ingredient_index: IngredientIndex(6), key_index: Some(Id { value: 3 }) } })", "salsa_event(DidDiscard { key: contribution_from_struct(2) })",
"salsa_event(DidDiscard { key: DependencyIndex { ingredient_index: IngredientIndex(3), key_index: Some(Id { value: 6 }) } })", "salsa_event(DidDiscard { key: MyTracked(5) })",
"salsa_event(DidDiscard { key: DependencyIndex { ingredient_index: IngredientIndex(2), key_index: Some(Id { value: 6 }) } })", "salsa_event(DidDiscard { key: field(5) })",
"salsa_event(DidDiscard { key: DependencyIndex { ingredient_index: IngredientIndex(7), key_index: Some(Id { value: 6 }) } })", "salsa_event(DidDiscard { key: copy_field(5) })",
"final_result(MyInput(Id { value: 1 }))", "final_result(MyInput(Id { value: 1 }))",
]"#]]); ]"#]]);
} }

View file

@ -108,10 +108,10 @@ fn basic() {
db.assert_logs(expect![[r#" db.assert_logs(expect![[r#"
[ [
"intermediate_result(MyInput(Id { value: 1 }))", "intermediate_result(MyInput(Id { value: 1 }))",
"salsa_event(WillDiscardStaleOutput { execute_key: DependencyIndex { ingredient_index: IngredientIndex(5), key_index: Some(Id { value: 1 }) }, output_key: DependencyIndex { ingredient_index: IngredientIndex(3), key_index: Some(Id { value: 3 }) } })", "salsa_event(WillDiscardStaleOutput { execute_key: create_tracked_structs(0), output_key: MyTracked(2) })",
"salsa_event(DidDiscard { key: DependencyIndex { ingredient_index: IngredientIndex(3), key_index: Some(Id { value: 3 }) } })", "salsa_event(DidDiscard { key: MyTracked(2) })",
"salsa_event(DidDiscard { key: DependencyIndex { ingredient_index: IngredientIndex(2), key_index: Some(Id { value: 3 }) } })", "salsa_event(DidDiscard { key: field(2) })",
"salsa_event(DidDiscard { key: DependencyIndex { ingredient_index: IngredientIndex(6), key_index: Some(Id { value: 3 }) } })", "salsa_event(DidDiscard { key: contribution_from_struct(2) })",
"final_result(MyInput(Id { value: 1 }))", "final_result(MyInput(Id { value: 1 }))",
]"#]]); ]"#]]);
} }

View file

@ -64,8 +64,8 @@ fn execute() {
if let Some(c) = err_b.downcast_ref::<salsa::Cycle>() { if let Some(c) = err_b.downcast_ref::<salsa::Cycle>() {
let expected = expect![[r#" let expected = expect![[r#"
[ [
"DependencyIndex { ingredient_index: IngredientIndex(8), key_index: Some(Id { value: 1 }) }", "a(0)",
"DependencyIndex { ingredient_index: IngredientIndex(9), key_index: Some(Id { value: 1 }) }", "b(0)",
] ]
"#]]; "#]];
expected.assert_debug_eq(&c.all_participants(&db)); expected.assert_debug_eq(&c.all_participants(&db));

View file

@ -98,13 +98,13 @@ fn test_run_0() {
db.assert_logs(expect![[r#" db.assert_logs(expect![[r#"
[ [
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: DependencyIndex { ingredient_index: IngredientIndex(7), key_index: Some(Id { value: 1 }) } } }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: final_result(0) } }",
"final_result(MyInput(Id { value: 1 }))", "final_result(MyInput(Id { value: 1 }))",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: DependencyIndex { ingredient_index: IngredientIndex(6), key_index: Some(Id { value: 1 }) } } }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: create_tracked(0) } }",
"create_tracked(MyInput(Id { value: 1 }))", "create_tracked(MyInput(Id { value: 1 }))",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: DependencyIndex { ingredient_index: IngredientIndex(5), key_index: Some(Id { value: 1 }) } } }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: read_maybe_specified(0) } }",
"read_maybe_specified(MyTracked(Id { value: 1 }))", "read_maybe_specified(MyTracked(Id { value: 1 }))",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }",
]"#]]); ]"#]]);
@ -119,13 +119,13 @@ fn test_run_5() {
db.assert_logs(expect![[r#" db.assert_logs(expect![[r#"
[ [
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: DependencyIndex { ingredient_index: IngredientIndex(7), key_index: Some(Id { value: 1 }) } } }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: final_result(0) } }",
"final_result(MyInput(Id { value: 1 }))", "final_result(MyInput(Id { value: 1 }))",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: DependencyIndex { ingredient_index: IngredientIndex(6), key_index: Some(Id { value: 1 }) } } }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: create_tracked(0) } }",
"create_tracked(MyInput(Id { value: 1 }))", "create_tracked(MyInput(Id { value: 1 }))",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: DependencyIndex { ingredient_index: IngredientIndex(5), key_index: Some(Id { value: 1 }) } } }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: read_maybe_specified(0) } }",
"read_maybe_specified(MyTracked(Id { value: 1 }))", "read_maybe_specified(MyTracked(Id { value: 1 }))",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }",
]"#]]); ]"#]]);
@ -140,16 +140,16 @@ fn test_run_10() {
db.assert_logs(expect![[r#" db.assert_logs(expect![[r#"
[ [
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: DependencyIndex { ingredient_index: IngredientIndex(7), key_index: Some(Id { value: 1 }) } } }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: final_result(0) } }",
"final_result(MyInput(Id { value: 1 }))", "final_result(MyInput(Id { value: 1 }))",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: DependencyIndex { ingredient_index: IngredientIndex(6), key_index: Some(Id { value: 1 }) } } }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: create_tracked(0) } }",
"create_tracked(MyInput(Id { value: 1 }))", "create_tracked(MyInput(Id { value: 1 }))",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: DependencyIndex { ingredient_index: IngredientIndex(5), key_index: Some(Id { value: 1 }) } } }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: read_maybe_specified(0) } }",
"read_maybe_specified(MyTracked(Id { value: 1 }))", "read_maybe_specified(MyTracked(Id { value: 1 }))",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: DependencyIndex { ingredient_index: IngredientIndex(4), key_index: Some(Id { value: 1 }) } } }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: maybe_specified(0) } }",
"maybe_specified(MyTracked(Id { value: 1 }))", "maybe_specified(MyTracked(Id { value: 1 }))",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }",
]"#]]); ]"#]]);
@ -164,16 +164,16 @@ fn test_run_20() {
db.assert_logs(expect![[r#" db.assert_logs(expect![[r#"
[ [
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: DependencyIndex { ingredient_index: IngredientIndex(7), key_index: Some(Id { value: 1 }) } } }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: final_result(0) } }",
"final_result(MyInput(Id { value: 1 }))", "final_result(MyInput(Id { value: 1 }))",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: DependencyIndex { ingredient_index: IngredientIndex(6), key_index: Some(Id { value: 1 }) } } }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: create_tracked(0) } }",
"create_tracked(MyInput(Id { value: 1 }))", "create_tracked(MyInput(Id { value: 1 }))",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: DependencyIndex { ingredient_index: IngredientIndex(5), key_index: Some(Id { value: 1 }) } } }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: read_maybe_specified(0) } }",
"read_maybe_specified(MyTracked(Id { value: 1 }))", "read_maybe_specified(MyTracked(Id { value: 1 }))",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: DependencyIndex { ingredient_index: IngredientIndex(4), key_index: Some(Id { value: 1 }) } } }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: maybe_specified(0) } }",
"maybe_specified(MyTracked(Id { value: 1 }))", "maybe_specified(MyTracked(Id { value: 1 }))",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }",
]"#]]); ]"#]]);
@ -192,13 +192,13 @@ fn test_run_0_then_5_then_20() {
db.assert_logs(expect![[r#" db.assert_logs(expect![[r#"
[ [
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: DependencyIndex { ingredient_index: IngredientIndex(7), key_index: Some(Id { value: 1 }) } } }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: final_result(0) } }",
"final_result(MyInput(Id { value: 1 }))", "final_result(MyInput(Id { value: 1 }))",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: DependencyIndex { ingredient_index: IngredientIndex(6), key_index: Some(Id { value: 1 }) } } }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: create_tracked(0) } }",
"create_tracked(MyInput(Id { value: 1 }))", "create_tracked(MyInput(Id { value: 1 }))",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: DependencyIndex { ingredient_index: IngredientIndex(5), key_index: Some(Id { value: 1 }) } } }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: read_maybe_specified(0) } }",
"read_maybe_specified(MyTracked(Id { value: 1 }))", "read_maybe_specified(MyTracked(Id { value: 1 }))",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }",
]"#]]); ]"#]]);
@ -213,12 +213,12 @@ fn test_run_0_then_5_then_20() {
[ [
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: DependencyIndex { ingredient_index: IngredientIndex(6), key_index: Some(Id { value: 1 }) } } }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: create_tracked(0) } }",
"create_tracked(MyInput(Id { value: 1 }))", "create_tracked(MyInput(Id { value: 1 }))",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: DidValidateMemoizedValue { database_key: DependencyIndex { ingredient_index: IngredientIndex(5), key_index: Some(Id { value: 1 }) } } }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: DidValidateMemoizedValue { database_key: read_maybe_specified(0) } }",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: DidValidateMemoizedValue { database_key: DependencyIndex { ingredient_index: IngredientIndex(7), key_index: Some(Id { value: 1 }) } } }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: DidValidateMemoizedValue { database_key: final_result(0) } }",
]"#]]); ]"#]]);
// Set input to 20: // Set input to 20:
@ -232,18 +232,18 @@ fn test_run_0_then_5_then_20() {
[ [
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: DependencyIndex { ingredient_index: IngredientIndex(6), key_index: Some(Id { value: 1 }) } } }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: create_tracked(0) } }",
"create_tracked(MyInput(Id { value: 1 }))", "create_tracked(MyInput(Id { value: 1 }))",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillDiscardStaleOutput { execute_key: DependencyIndex { ingredient_index: IngredientIndex(6), key_index: Some(Id { value: 1 }) }, output_key: DependencyIndex { ingredient_index: IngredientIndex(4), key_index: Some(Id { value: 1 }) } } }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillDiscardStaleOutput { execute_key: create_tracked(0), output_key: maybe_specified(0) } }",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: DependencyIndex { ingredient_index: IngredientIndex(4), key_index: Some(Id { value: 1 }) } } }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: maybe_specified(0) } }",
"maybe_specified(MyTracked(Id { value: 1 }))", "maybe_specified(MyTracked(Id { value: 1 }))",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: DependencyIndex { ingredient_index: IngredientIndex(5), key_index: Some(Id { value: 1 }) } } }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: read_maybe_specified(0) } }",
"read_maybe_specified(MyTracked(Id { value: 1 }))", "read_maybe_specified(MyTracked(Id { value: 1 }))",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: DependencyIndex { ingredient_index: IngredientIndex(7), key_index: Some(Id { value: 1 }) } } }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: final_result(0) } }",
"final_result(MyInput(Id { value: 1 }))", "final_result(MyInput(Id { value: 1 }))",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }",
@ -263,13 +263,13 @@ fn test_run_0_then_5_then_10_then_20() {
db.assert_logs(expect![[r#" db.assert_logs(expect![[r#"
[ [
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: DependencyIndex { ingredient_index: IngredientIndex(7), key_index: Some(Id { value: 1 }) } } }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: final_result(0) } }",
"final_result(MyInput(Id { value: 1 }))", "final_result(MyInput(Id { value: 1 }))",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: DependencyIndex { ingredient_index: IngredientIndex(6), key_index: Some(Id { value: 1 }) } } }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: create_tracked(0) } }",
"create_tracked(MyInput(Id { value: 1 }))", "create_tracked(MyInput(Id { value: 1 }))",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: DependencyIndex { ingredient_index: IngredientIndex(5), key_index: Some(Id { value: 1 }) } } }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: read_maybe_specified(0) } }",
"read_maybe_specified(MyTracked(Id { value: 1 }))", "read_maybe_specified(MyTracked(Id { value: 1 }))",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }",
]"#]]); ]"#]]);
@ -284,12 +284,12 @@ fn test_run_0_then_5_then_10_then_20() {
[ [
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: DependencyIndex { ingredient_index: IngredientIndex(6), key_index: Some(Id { value: 1 }) } } }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: create_tracked(0) } }",
"create_tracked(MyInput(Id { value: 1 }))", "create_tracked(MyInput(Id { value: 1 }))",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: DidValidateMemoizedValue { database_key: DependencyIndex { ingredient_index: IngredientIndex(5), key_index: Some(Id { value: 1 }) } } }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: DidValidateMemoizedValue { database_key: read_maybe_specified(0) } }",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: DidValidateMemoizedValue { database_key: DependencyIndex { ingredient_index: IngredientIndex(7), key_index: Some(Id { value: 1 }) } } }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: DidValidateMemoizedValue { database_key: final_result(0) } }",
]"#]]); ]"#]]);
// Set input to 10: // Set input to 10:
@ -303,16 +303,16 @@ fn test_run_0_then_5_then_10_then_20() {
[ [
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: DependencyIndex { ingredient_index: IngredientIndex(6), key_index: Some(Id { value: 1 }) } } }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: create_tracked(0) } }",
"create_tracked(MyInput(Id { value: 1 }))", "create_tracked(MyInput(Id { value: 1 }))",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillDiscardStaleOutput { execute_key: DependencyIndex { ingredient_index: IngredientIndex(6), key_index: Some(Id { value: 1 }) }, output_key: DependencyIndex { ingredient_index: IngredientIndex(4), key_index: Some(Id { value: 1 }) } } }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillDiscardStaleOutput { execute_key: create_tracked(0), output_key: maybe_specified(0) } }",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: DependencyIndex { ingredient_index: IngredientIndex(4), key_index: Some(Id { value: 1 }) } } }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: maybe_specified(0) } }",
"maybe_specified(MyTracked(Id { value: 1 }))", "maybe_specified(MyTracked(Id { value: 1 }))",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: DidValidateMemoizedValue { database_key: DependencyIndex { ingredient_index: IngredientIndex(5), key_index: Some(Id { value: 1 }) } } }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: DidValidateMemoizedValue { database_key: read_maybe_specified(0) } }",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: DidValidateMemoizedValue { database_key: DependencyIndex { ingredient_index: IngredientIndex(7), key_index: Some(Id { value: 1 }) } } }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: DidValidateMemoizedValue { database_key: final_result(0) } }",
]"#]]); ]"#]]);
// Set input to 20: // Set input to 20:
@ -324,18 +324,18 @@ fn test_run_0_then_5_then_10_then_20() {
[ [
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: DependencyIndex { ingredient_index: IngredientIndex(6), key_index: Some(Id { value: 1 }) } } }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: create_tracked(0) } }",
"create_tracked(MyInput(Id { value: 1 }))", "create_tracked(MyInput(Id { value: 1 }))",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: DependencyIndex { ingredient_index: IngredientIndex(4), key_index: Some(Id { value: 1 }) } } }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: maybe_specified(0) } }",
"maybe_specified(MyTracked(Id { value: 1 }))", "maybe_specified(MyTracked(Id { value: 1 }))",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: DependencyIndex { ingredient_index: IngredientIndex(5), key_index: Some(Id { value: 1 }) } } }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: read_maybe_specified(0) } }",
"read_maybe_specified(MyTracked(Id { value: 1 }))", "read_maybe_specified(MyTracked(Id { value: 1 }))",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: DependencyIndex { ingredient_index: IngredientIndex(7), key_index: Some(Id { value: 1 }) } } }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: final_result(0) } }",
"final_result(MyInput(Id { value: 1 }))", "final_result(MyInput(Id { value: 1 }))",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }",
@ -351,13 +351,13 @@ fn test_run_5_then_20() {
db.assert_logs(expect![[r#" db.assert_logs(expect![[r#"
[ [
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: DependencyIndex { ingredient_index: IngredientIndex(7), key_index: Some(Id { value: 1 }) } } }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: final_result(0) } }",
"final_result(MyInput(Id { value: 1 }))", "final_result(MyInput(Id { value: 1 }))",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: DependencyIndex { ingredient_index: IngredientIndex(6), key_index: Some(Id { value: 1 }) } } }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: create_tracked(0) } }",
"create_tracked(MyInput(Id { value: 1 }))", "create_tracked(MyInput(Id { value: 1 }))",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: DependencyIndex { ingredient_index: IngredientIndex(5), key_index: Some(Id { value: 1 }) } } }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: read_maybe_specified(0) } }",
"read_maybe_specified(MyTracked(Id { value: 1 }))", "read_maybe_specified(MyTracked(Id { value: 1 }))",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }",
]"#]]); ]"#]]);
@ -368,18 +368,18 @@ fn test_run_5_then_20() {
[ [
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: DependencyIndex { ingredient_index: IngredientIndex(6), key_index: Some(Id { value: 1 }) } } }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: create_tracked(0) } }",
"create_tracked(MyInput(Id { value: 1 }))", "create_tracked(MyInput(Id { value: 1 }))",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillDiscardStaleOutput { execute_key: DependencyIndex { ingredient_index: IngredientIndex(6), key_index: Some(Id { value: 1 }) }, output_key: DependencyIndex { ingredient_index: IngredientIndex(4), key_index: Some(Id { value: 1 }) } } }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillDiscardStaleOutput { execute_key: create_tracked(0), output_key: maybe_specified(0) } }",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: DependencyIndex { ingredient_index: IngredientIndex(4), key_index: Some(Id { value: 1 }) } } }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: maybe_specified(0) } }",
"maybe_specified(MyTracked(Id { value: 1 }))", "maybe_specified(MyTracked(Id { value: 1 }))",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: DependencyIndex { ingredient_index: IngredientIndex(5), key_index: Some(Id { value: 1 }) } } }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: read_maybe_specified(0) } }",
"read_maybe_specified(MyTracked(Id { value: 1 }))", "read_maybe_specified(MyTracked(Id { value: 1 }))",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: DependencyIndex { ingredient_index: IngredientIndex(7), key_index: Some(Id { value: 1 }) } } }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: final_result(0) } }",
"final_result(MyInput(Id { value: 1 }))", "final_result(MyInput(Id { value: 1 }))",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }", "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }",