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#"
[
"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: DependencyIndex { ingredient_index: IngredientIndex(18), 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: type_check_function(0) } }",
]
"#]],
)],

View file

@ -48,7 +48,7 @@ fn accumulator_contents(
let struct_ty = &parse_quote! {#struct_name};
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 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> {
match &struct_item.fields {
syn::Fields::Unnamed(fields) => {
if fields.unnamed.len() != 1 {
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(
if let syn::Fields::Unnamed(fields) = &struct_item.fields {
if fields.unnamed.len() != 1 {
Err(syn::Error::new(
struct_item.ident.span(),
"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 debug_name = crate::literal(struct_name);
parse_quote! {
impl salsa::storage::IngredientsFor for #struct_ty {
impl salsa::storage::IngredientsFor for #struct_name {
type Ingredients = salsa::accumulator::AccumulatorIngredient<#data_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)
},
);
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> {
let storage = format!("storage");
let storage = "storage";
for field in input.fields.iter() {
if let Some(i) = &field.ident {
if i.to_string() == storage {
if i == storage {
return Ok(i.clone());
}
} else {
@ -159,6 +159,10 @@ fn has_jars_dyn_impl(input: &syn::ItemStruct, storage: &syn::Ident) -> syn::Item
let ingredient = self.#storage.ingredient(ingredient);
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
/// function ingredient for each of the value fields.
fn input_ingredients(&self) -> syn::ItemImpl {
use crate::literal;
let ident = self.id_ident();
let field_ty = self.all_field_tys();
let jar_ty = self.jar_ty();
let all_field_indices: Vec<Literal> = self.all_field_indices();
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! {
impl salsa::storage::IngredientsFor for #ident {
@ -167,7 +170,7 @@ impl InputStruct {
&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
},
);
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`.
fn ingredients_for_impl(&self) -> syn::ItemImpl {
let id_ident = self.id_ident();
let debug_name = crate::literal(id_ident);
let jar_ty = self.jar_ty();
let data_ident = self.data_ident();
parse_quote! {
@ -143,7 +144,7 @@ impl InternedStruct {
<_ 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 configuration;
mod db;

View file

@ -12,7 +12,7 @@ pub(crate) fn tracked(
let args = syn::parse_macro_input!(args as Args);
match tracked_fn(args, item_fn) {
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 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 {
// 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.
@ -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
// 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! {
fn execute(__db: &salsa::function::DynDb<Self>, __id: Self::Key) -> Self::Value {
#inner_fn
@ -212,6 +212,7 @@ fn ingredients_for_impl(
config_ty: &syn::Type,
) -> syn::ItemImpl {
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) {
parse_quote! {
@ -230,7 +231,7 @@ fn ingredients_for_impl(
&mut ingredients.intern_map
}
);
salsa::interned::InternedIngredient::new(index)
salsa::interned::InternedIngredient::new(index, #debug_name)
}
}
} else {
@ -242,6 +243,9 @@ fn ingredients_for_impl(
// set 0 as default to disable LRU
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! {
impl salsa::storage::IngredientsFor for #config_ty {
type Ingredients = Self;
@ -268,7 +272,7 @@ fn ingredients_for_impl(
<_ as salsa::storage::HasIngredientsFor<Self::Ingredients>>::ingredient_mut(jar);
&mut ingredients.function
});
let ingredient = salsa::function::FunctionIngredient::new(index);
let ingredient = salsa::function::FunctionIngredient::new(index, #debug_name);
ingredient.set_capacity(#lru);
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.
fn db_lifetime_and_ty(func: &mut syn::ItemFn) -> syn::Result<(syn::Lifetime, &syn::Type)> {
match &mut func.sig.inputs[0] {
syn::FnArg::Receiver(r) => {
return Err(syn::Error::new(r.span(), "expected database, not self"))
}
syn::FnArg::Receiver(r) => Err(syn::Error::new(r.span(), "expected database, not self")),
syn::FnArg::Typed(pat_ty) => match &mut *pat_ty.ty {
syn::Type::Reference(ty) => match &ty.lifetime {
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))
}
},
_ => {
return Err(syn::Error::new(
pat_ty.span(),
"expected database to be a `&` type",
))
}
_ => Err(syn::Error::new(
pat_ty.span(),
"expected database to be a `&` type",
)),
},
}
}
@ -607,7 +607,7 @@ fn accumulated_fn(
/// * the name(s) of the key arguments
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
if item_fn.sig.inputs.len() == 0 {
if item_fn.sig.inputs.is_empty() {
return Err(syn::Error::new(
item_fn.sig.span(),
"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
/// function ingredient for each of the value fields.
fn tracked_struct_ingredients(&self, config_structs: &[syn::ItemStruct]) -> syn::ItemImpl {
use crate::literal;
let ident = self.id_ident();
let jar_ty = self.jar_ty();
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 tracked_struct_index: Literal = self.tracked_struct_index();
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! {
impl salsa::storage::IngredientsFor for #ident {
@ -191,7 +194,7 @@ impl TrackedStruct {
&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
},
);
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.
fn value_field_indices(&self) -> Vec<Literal> {
(0..self.value_fields().count())
.map(|i| Literal::usize_unsuffixed(i))
.map(Literal::usize_unsuffixed)
.collect()
}
/// Indices of each of the id fields
fn id_field_indices(&self) -> Vec<Literal> {
(0..self.id_fields().count())
.map(|i| Literal::usize_unsuffixed(i))
.map(Literal::usize_unsuffixed)
.collect()
}
}

View file

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

View file

@ -1,11 +1,11 @@
use std::sync::Arc;
use std::{fmt, sync::Arc};
use arc_swap::ArcSwap;
use crossbeam::{atomic::AtomicCell, queue::SegQueue};
use crate::{
cycle::CycleRecoveryStrategy,
ingredient::IngredientRequiresReset,
ingredient::{fmt_index, IngredientRequiresReset},
jar::Jar,
key::{DatabaseKeyIndex, DependencyIndex},
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`.
/// Prevents us from registering more than once.
registered: AtomicCell<bool>,
debug_name: &'static str,
}
pub trait Configuration {
@ -87,7 +89,7 @@ pub trait Configuration {
type Key: AsId;
/// 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
/// (and, if so, how).
@ -137,7 +139,7 @@ impl<C> FunctionIngredient<C>
where
C: Configuration,
{
pub fn new(index: IngredientIndex) -> Self {
pub fn new(index: IngredientIndex, debug_name: &'static str) -> Self {
Self {
index,
memo_map: memo::MemoMap::default(),
@ -145,6 +147,7 @@ where
sync_map: Default::default(),
deleted_entries: 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>

View file

@ -1,3 +1,5 @@
use std::fmt;
use crate::{
cycle::CycleRecoveryStrategy, key::DependencyIndex, runtime::local_state::QueryOrigin,
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.
/// 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
/// that together are used to create the salsa concept.
/// For example, a tracked struct defines a [`crate::interned::InternedIngredient`] to store 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.
/// Each use salsa macro (e.g., `#[salsa::tracked]`, `#[salsa::interned]`) adds one or more
/// 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 plus [`crate::function::FunctionIngredient`] values to store its fields.
/// The exact ingredients are determined by
/// [`IngredientsFor`](`crate::storage::IngredientsFor`) implementations generated by the
/// macro.
pub trait Ingredient<DB: ?Sized> {
/// If this ingredient is a participant in a cycle, what is its cycle recovery strategy?
/// (Really only relevant to [`crate::function::FunctionIngredient`],
@ -25,7 +29,8 @@ pub trait Ingredient<DB: ?Sized> {
fn origin(&self, key_index: Id) -> Option<QueryOrigin>;
/// 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>);
/// 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);
/// 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,
/// and hence any pre-existing `&`-references must have expired.
/// This moment is important because it means that we have an `&mut`-reference to the
/// database, and hence any pre-existing `&`-references must have expired.
/// Many ingredients, given an `&'db`-reference to the database,
/// 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
/// [`IngredientRequiresReset::RESET_ON_NEW_REVISION`] to true.
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.
/// 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 {
/// If this is true, then `reset_for_new_revision` will be called every new revision.
const RESET_ON_NEW_REVISION: bool;

View file

@ -1,6 +1,8 @@
use std::fmt;
use crate::{
cycle::CycleRecoveryStrategy,
ingredient::{Ingredient, IngredientRequiresReset},
ingredient::{fmt_index, Ingredient, IngredientRequiresReset},
key::{DatabaseKeyIndex, DependencyIndex},
runtime::{local_state::QueryOrigin, Runtime},
AsId, IngredientIndex, Revision,
@ -15,6 +17,7 @@ where
{
ingredient_index: IngredientIndex,
counter: u32,
debug_name: &'static str,
_phantom: std::marker::PhantomData<Id>,
}
@ -22,10 +25,11 @@ impl<Id> InputIngredient<Id>
where
Id: InputId,
{
pub fn new(index: IngredientIndex) -> Self {
pub fn new(index: IngredientIndex, debug_name: &'static str) -> Self {
Self {
ingredient_index: index,
counter: Default::default(),
debug_name,
_phantom: std::marker::PhantomData,
}
}
@ -95,6 +99,10 @@ where
"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>

View file

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

View file

@ -1,11 +1,12 @@
use crossbeam::atomic::AtomicCell;
use crossbeam::queue::SegQueue;
use std::fmt;
use std::hash::Hash;
use std::marker::PhantomData;
use crate::durability::Durability;
use crate::id::AsId;
use crate::ingredient::IngredientRequiresReset;
use crate::ingredient::{fmt_index, IngredientRequiresReset};
use crate::key::DependencyIndex;
use crate::runtime::local_state::QueryOrigin;
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,
/// guaranteeing that there are no more references to it.
deleted_entries: SegQueue<Box<Data>>,
debug_name: &'static str,
}
impl<Id, Data> InternedIngredient<Id, Data>
@ -61,7 +64,7 @@ where
Id: InternedId,
Data: InternedData,
{
pub fn new(ingredient_index: IngredientIndex) -> Self {
pub fn new(ingredient_index: IngredientIndex, debug_name: &'static str) -> Self {
Self {
ingredient_index,
key_map: Default::default(),
@ -69,6 +72,7 @@ where
counter: AtomicCell::default(),
reset_at: Revision::start(),
deleted_entries: Default::default(),
debug_name,
}
}
@ -234,6 +238,10 @@ where
fn salsa_struct_deleted(&self, _db: &DB, _id: crate::Id) {
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>

View file

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

View file

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

View file

@ -1,6 +1,8 @@
use std::fmt;
use crate::{
cycle::CycleRecoveryStrategy,
ingredient::{Ingredient, IngredientRequiresReset},
ingredient::{fmt_index, Ingredient, IngredientRequiresReset},
ingredient_list::IngredientList,
interned::{InternedData, InternedId, InternedIngredient},
key::{DatabaseKeyIndex, DependencyIndex},
@ -42,6 +44,8 @@ where
/// each of these functions will be notified
/// so they can remove any data tied to that instance.
dependent_fns: IngredientList,
debug_name: &'static str,
}
#[derive(Debug, PartialEq, Eq, Hash, PartialOrd, Ord, Copy, Clone)]
@ -59,10 +63,11 @@ where
Id: TrackedStructId,
Data: TrackedStructData,
{
pub fn new(index: IngredientIndex) -> Self {
pub fn new(index: IngredientIndex, debug_name: &'static str) -> Self {
Self {
interned: InternedIngredient::new(index),
interned: InternedIngredient::new(index, debug_name),
dependent_fns: IngredientList::new(),
debug_name,
}
}
@ -175,6 +180,10 @@ where
fn salsa_struct_deleted(&self, _db: &DB, _id: crate::Id) {
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>

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

View file

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

View file

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

View file

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

View file

@ -98,13 +98,13 @@ fn test_run_0() {
db.assert_logs(expect![[r#"
[
"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 }))",
"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 }))",
"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 }))",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }",
]"#]]);
@ -119,13 +119,13 @@ fn test_run_5() {
db.assert_logs(expect![[r#"
[
"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 }))",
"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 }))",
"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 }))",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }",
]"#]]);
@ -140,16 +140,16 @@ fn test_run_10() {
db.assert_logs(expect![[r#"
[
"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 }))",
"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 }))",
"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 }))",
"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 }))",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }",
]"#]]);
@ -164,16 +164,16 @@ fn test_run_20() {
db.assert_logs(expect![[r#"
[
"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 }))",
"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 }))",
"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 }))",
"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 }))",
"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#"
[
"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 }))",
"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 }))",
"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 }))",
"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: 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 }))",
"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: DependencyIndex { ingredient_index: IngredientIndex(7), 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: final_result(0) } }",
]"#]]);
// 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: 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 }))",
"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: 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 }))",
"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 }))",
"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 }))",
"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#"
[
"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 }))",
"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 }))",
"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 }))",
"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: 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 }))",
"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: DependencyIndex { ingredient_index: IngredientIndex(7), 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: final_result(0) } }",
]"#]]);
// 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: 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 }))",
"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: 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 }))",
"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: DependencyIndex { ingredient_index: IngredientIndex(7), 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: final_result(0) } }",
]"#]]);
// 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: 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 }))",
"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 }))",
"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 }))",
"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 }))",
"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#"
[
"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 }))",
"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 }))",
"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 }))",
"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: 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 }))",
"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: 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 }))",
"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 }))",
"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 }))",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }",
"Event { runtime_id: RuntimeId { counter: 0 }, kind: WillCheckCancellation }",