diff --git a/calc-example/calc/src/type_check.rs b/calc-example/calc/src/type_check.rs index f62b2086..104dfeb6 100644 --- a/calc-example/calc/src/type_check.rs +++ b/calc-example/calc/src/type_check.rs @@ -114,7 +114,9 @@ fn check_string( // Apply edits and check diagnostics/logs after each one for (new_source_text, expected_diagnostics, expected_logs) in edits { - source_program.set_text(&mut db, new_source_text.to_string()); + source_program + .set_text(&mut db) + .to(new_source_text.to_string()); let program = parse_statements(&db, source_program); expected_diagnostics.assert_debug_eq(&type_check_program::accumulated::( &db, program, @@ -246,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) } }", ] "#]], )], diff --git a/components/salsa-2022-macros/src/accumulator.rs b/components/salsa-2022-macros/src/accumulator.rs index 55cb3f54..4a6537d4 100644 --- a/components/salsa-2022-macros/src/accumulator.rs +++ b/components/salsa-2022-macros/src/accumulator.rs @@ -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>::ingredient_mut(jar) }, ); - salsa::accumulator::AccumulatorIngredient::new(index) + salsa::accumulator::AccumulatorIngredient::new(index, #debug_name) } } } diff --git a/components/salsa-2022-macros/src/db.rs b/components/salsa-2022-macros/src/db.rs index 54c22ab8..fabb706e 100644 --- a/components/salsa-2022-macros/src/db.rs +++ b/components/salsa-2022-macros/src/db.rs @@ -55,10 +55,10 @@ impl syn::parse::Parse for Args { } fn find_storage_field(input: &syn::ItemStruct) -> Result { - 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) + } } } } diff --git a/components/salsa-2022-macros/src/input.rs b/components/salsa-2022-macros/src/input.rs index 9932226b..f10c8a78 100644 --- a/components/salsa-2022-macros/src/input.rs +++ b/components/salsa-2022-macros/src/input.rs @@ -94,11 +94,11 @@ impl InputStruct { let set_field_names = self.all_set_field_names(); let field_setters: Vec = field_indices.iter().zip(&set_field_names).zip(&field_tys).map(|((field_index, set_field_name), field_ty)| { parse_quote! { - pub fn #set_field_name<'db>(self, __db: &'db mut #db_dyn_ty, __value: #field_ty) -> #field_ty + pub fn #set_field_name<'db>(self, __db: &'db mut #db_dyn_ty) -> salsa::setter::Setter<'db, #ident, #field_ty> { let (__jar, __runtime) = <_ as salsa::storage::HasJar<#jar_ty>>::jar_mut(__db); let __ingredients = <#jar_ty as salsa::storage::HasIngredientsFor< #ident >>::ingredient_mut(__jar); - __ingredients.#field_index.store(__runtime, self, __value, salsa::Durability::LOW).unwrap() + salsa::setter::Setter::new(__runtime, self, &mut __ingredients.#field_index) } } }) @@ -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 = 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) }, ) } diff --git a/components/salsa-2022-macros/src/interned.rs b/components/salsa-2022-macros/src/interned.rs index 629a23de..54df62ab 100644 --- a/components/salsa-2022-macros/src/interned.rs +++ b/components/salsa-2022-macros/src/interned.rs @@ -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>::ingredient_mut(jar) }, ); - salsa::interned::InternedIngredient::new(index) + salsa::interned::InternedIngredient::new(index, #debug_name) } } } diff --git a/components/salsa-2022-macros/src/lib.rs b/components/salsa-2022-macros/src/lib.rs index 13263b3b..45b31e67 100644 --- a/components/salsa-2022-macros/src/lib.rs +++ b/components/salsa-2022-macros/src/lib.rs @@ -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; diff --git a/components/salsa-2022-macros/src/tracked_fn.rs b/components/salsa-2022-macros/src/tracked_fn.rs index f8d262f7..8dc648c7 100644 --- a/components/salsa-2022-macros/src/tracked_fn.rs +++ b/components/salsa-2022-macros/src/tracked_fn.rs @@ -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, __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>::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 } @@ -426,7 +430,7 @@ fn setter_fn( /// /// # Examples /// -/// ```rust +/// ```rust,ignore /// #[salsa::tracked(lru=32)] /// fn my_tracked_fn(db: &dyn crate::Db, ...) { } /// @@ -520,9 +524,7 @@ fn make_fn_return_ref(mut ref_getter_fn: syn::ItemFn) -> syn::Result 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)> { // 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", diff --git a/components/salsa-2022-macros/src/tracked_struct.rs b/components/salsa-2022-macros/src/tracked_struct.rs index 5212e5b0..99f12b53 100644 --- a/components/salsa-2022-macros/src/tracked_struct.rs +++ b/components/salsa-2022-macros/src/tracked_struct.rs @@ -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 = 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 { (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 { (0..self.id_fields().count()) - .map(|i| Literal::usize_unsuffixed(i)) + .map(Literal::usize_unsuffixed) .collect() } } diff --git a/components/salsa-2022/src/accumulator.rs b/components/salsa-2022/src/accumulator.rs index 1d91a405..fcae3d05 100644 --- a/components/salsa-2022/src/accumulator.rs +++ b/components/salsa-2022/src/accumulator.rs @@ -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 { index: IngredientIndex, map: FxDashMap>, + debug_name: &'static str, } struct AccumulatedValues { @@ -29,10 +32,11 @@ struct AccumulatedValues { } impl AccumulatorIngredient { - 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, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt_index(self.debug_name, index, fmt) + } } impl IngredientRequiresReset for AccumulatorIngredient diff --git a/components/salsa-2022/src/function.rs b/components/salsa-2022/src/function.rs index cfadc8c4..f88187b7 100644 --- a/components/salsa-2022/src/function.rs +++ b/components/salsa-2022/src/function.rs @@ -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 { /// Set to true once we invoke `register_dependent_fn` for `C::SalsaStruct`. /// Prevents us from registering more than once. registered: AtomicCell, + + 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 FunctionIngredient 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, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt_index(self.debug_name, index, fmt) + } } impl IngredientRequiresReset for FunctionIngredient diff --git a/components/salsa-2022/src/ingredient.rs b/components/salsa-2022/src/ingredient.rs index 06b1a903..5d051289 100644 --- a/components/salsa-2022/src/ingredient.rs +++ b/components/salsa-2022/src/ingredient.rs @@ -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 { /// 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 { fn origin(&self, key_index: Id) -> Option; /// 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); /// Invoked when the value `stale_output` was output by `executor` in a previous @@ -46,19 +51,36 @@ pub trait Ingredient { 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, fmt: &mut fmt::Formatter<'_>) -> fmt::Result; +} + +/// A helper function to show human readable fmt. +pub(crate) fn fmt_index( + debug_name: &str, + id: Option, + 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; diff --git a/components/salsa-2022/src/input.rs b/components/salsa-2022/src/input.rs index f6dc35cf..fa908f6a 100644 --- a/components/salsa-2022/src/input.rs +++ b/components/salsa-2022/src/input.rs @@ -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, } @@ -22,10 +25,11 @@ impl InputIngredient 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, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt_index(self.debug_name, index, fmt) + } } impl IngredientRequiresReset for InputIngredient diff --git a/components/salsa-2022/src/input_field.rs b/components/salsa-2022/src/input_field.rs index 8204e60b..0ad5cd78 100644 --- a/components/salsa-2022/src/input_field.rs +++ b/components/salsa-2022/src/input_field.rs @@ -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 { index: IngredientIndex, map: FxHashMap>, + debug_name: &'static str, } impl InputFieldIngredient 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, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt_index(self.debug_name, index, fmt) + } } impl IngredientRequiresReset for InputFieldIngredient diff --git a/components/salsa-2022/src/interned.rs b/components/salsa-2022/src/interned.rs index e30c1235..eab2354a 100644 --- a/components/salsa-2022/src/interned.rs +++ b/components/salsa-2022/src/interned.rs @@ -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 { /// `&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>, + + debug_name: &'static str, } impl InternedIngredient @@ -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, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt_index(self.debug_name, index, fmt) + } } impl IngredientRequiresReset for InternedIngredient diff --git a/components/salsa-2022/src/key.rs b/components/salsa-2022/src/key.rs index d1369bdb..c443b7bb 100644 --- a/components/salsa-2022/src/key.rs +++ b/components/salsa-2022/src/key.rs @@ -38,8 +38,8 @@ impl crate::debug::DebugWithDb 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) } } diff --git a/components/salsa-2022/src/lib.rs b/components/salsa-2022/src/lib.rs index 6a0e4ad8..d3fe4ddd 100644 --- a/components/salsa-2022/src/lib.rs +++ b/components/salsa-2022/src/lib.rs @@ -20,6 +20,7 @@ pub mod revision; pub mod routes; pub mod runtime; pub mod salsa_struct; +pub mod setter; pub mod storage; #[doc(hidden)] pub mod tracked_struct; diff --git a/components/salsa-2022/src/setter.rs b/components/salsa-2022/src/setter.rs new file mode 100644 index 00000000..05af9c0e --- /dev/null +++ b/components/salsa-2022/src/setter.rs @@ -0,0 +1,39 @@ +use crate::input_field::InputFieldIngredient; +use crate::{AsId, Durability, Runtime}; +use std::hash::Hash; + +#[must_use] +pub struct Setter<'setter, K, F> { + runtime: &'setter mut Runtime, + key: K, + ingredient: &'setter mut InputFieldIngredient, + durability: Durability, +} + +impl<'setter, K, F> Setter<'setter, K, F> +where + K: Eq + Hash + AsId, +{ + pub fn new( + runtime: &'setter mut Runtime, + key: K, + ingredient: &'setter mut InputFieldIngredient, + ) -> Self { + Setter { + runtime, + key, + ingredient, + durability: Durability::LOW, + } + } + + pub fn with_durability(self, durability: Durability) -> Self { + Setter { durability, ..self } + } + + pub fn to(self, value: F) -> F { + self.ingredient + .store(self.runtime, self.key, value, self.durability) + .unwrap() + } +} diff --git a/components/salsa-2022/src/storage.rs b/components/salsa-2022/src/storage.rs index bf5ba0ea..83e3d617 100644 --- a/components/salsa-2022/src/storage.rs +++ b/components/salsa-2022/src/storage.rs @@ -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 diff --git a/components/salsa-2022/src/tracked_struct.rs b/components/salsa-2022/src/tracked_struct.rs index 98ebf6d4..9f749097 100644 --- a/components/salsa-2022/src/tracked_struct.rs +++ b/components/salsa-2022/src/tracked_struct.rs @@ -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, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt_index(self.debug_name, index, fmt) + } } impl IngredientRequiresReset for TrackedStructIngredient diff --git a/rustfmt.toml b/rustfmt.toml new file mode 100644 index 00000000..e69de29b diff --git a/salsa-2022-tests/tests/accumulate-from-tracked-fn.rs b/salsa-2022-tests/tests/accumulate-from-tracked-fn.rs index 85559e44..92c832b5 100644 --- a/salsa-2022-tests/tests/accumulate-from-tracked-fn.rs +++ b/salsa-2022-tests/tests/accumulate-from-tracked-fn.rs @@ -81,7 +81,7 @@ fn test1() { "#]] .assert_debug_eq(&compute::accumulated::(&db, l1)); - l0.set_value(&mut db, 2); + l0.set_value(&mut db).to(2); compute(&db, l1); expect![[r#" [ diff --git a/salsa-2022-tests/tests/accumulate-reuse-workaround.rs b/salsa-2022-tests/tests/accumulate-reuse-workaround.rs index fa3f5af6..6a1421dc 100644 --- a/salsa-2022-tests/tests/accumulate-reuse-workaround.rs +++ b/salsa-2022-tests/tests/accumulate-reuse-workaround.rs @@ -87,7 +87,7 @@ fn test1() { // When we mutate `l1`, we should re-execute `compute` for `l1`, // and we re-execute accumulated for `l1`, but we do NOT re-execute // `compute` for `l2`. - l1.set_value(&mut db, 2); + l1.set_value(&mut db).to(2); assert_eq!(compute(&db, l2), 2); db.assert_logs(expect![[r#" [ diff --git a/salsa-2022-tests/tests/accumulate-reuse.rs b/salsa-2022-tests/tests/accumulate-reuse.rs index f8258c40..a2fc5cda 100644 --- a/salsa-2022-tests/tests/accumulate-reuse.rs +++ b/salsa-2022-tests/tests/accumulate-reuse.rs @@ -82,7 +82,7 @@ fn test1() { // but we should not have to re-execute `compute` for `l2`. // The only inpout for `compute(l1)` is the accumulated values from `l1`, // which have not changed. - l1.set_value(&mut db, 2); + l1.set_value(&mut db).to(2); assert_eq!(compute(&db, l2), 2); db.assert_logs(expect![[r#" [ diff --git a/salsa-2022-tests/tests/accumulate.rs b/salsa-2022-tests/tests/accumulate.rs index 86932f8c..257bd802 100644 --- a/salsa-2022-tests/tests/accumulate.rs +++ b/salsa-2022-tests/tests/accumulate.rs @@ -132,7 +132,7 @@ fn change_a_and_reaccumulate() { ]"#]]); // Change to `a = 1`, which means `push_logs` does not call `push_a_logs` at all - input.set_field_a(&mut db, 1); + input.set_field_a(&mut db).to(1); let logs = push_logs::accumulated::(&db, input); expect![[r#" [ @@ -167,7 +167,7 @@ fn get_a_logs_after_changing_b() { // Changing `b` does not cause `push_a_logs` to re-execute // and we still get the same result - input.set_field_b(&mut db, 5); + input.set_field_b(&mut db).to(5); let logs = push_a_logs::accumulated::(&db, input); expect![[r#" [ diff --git a/salsa-2022-tests/tests/cycles.rs b/salsa-2022-tests/tests/cycles.rs index 5a88ed9a..90a8bb5a 100644 --- a/salsa-2022-tests/tests/cycles.rs +++ b/salsa-2022-tests/tests/cycles.rs @@ -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); @@ -248,7 +248,7 @@ fn cycle_revalidate() { let mut db = Database::default(); let abc = ABC::new(&mut db, CycleQuery::B, CycleQuery::A, CycleQuery::None); assert!(cycle_a(&db, abc).is_err()); - abc.set_b(&mut db, CycleQuery::A); // same value as default + abc.set_b(&mut db).to(CycleQuery::A); // same value as default assert!(cycle_a(&db, abc).is_err()); } @@ -261,7 +261,7 @@ fn cycle_recovery_unchanged_twice() { let abc = ABC::new(&mut db, CycleQuery::B, CycleQuery::A, CycleQuery::None); assert!(cycle_a(&db, abc).is_err()); - abc.set_c(&mut db, CycleQuery::A); // force new revision + abc.set_c(&mut db).to(CycleQuery::A); // force new revision assert!(cycle_a(&db, abc).is_err()); } @@ -276,7 +276,7 @@ fn cycle_appears() { // A --> B // ^ | // +-----+ - abc.set_b(&mut db, CycleQuery::A); + abc.set_b(&mut db).to(CycleQuery::A); assert!(cycle_a(&db, abc).is_err()); } @@ -291,7 +291,7 @@ fn cycle_disappears() { assert!(cycle_a(&db, abc).is_err()); // A --> B - abc.set_b(&mut db, CycleQuery::None); + abc.set_b(&mut db).to(CycleQuery::None); assert!(cycle_a(&db, abc).is_ok()); } @@ -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)); diff --git a/salsa-2022-tests/tests/deletion-cascade.rs b/salsa-2022-tests/tests/deletion-cascade.rs index d52f698b..d9002957 100644 --- a/salsa-2022-tests/tests/deletion-cascade.rs +++ b/salsa-2022-tests/tests/deletion-cascade.rs @@ -117,18 +117,18 @@ fn basic() { // * the struct's field // * the `copy_field` result - input.set_field(&mut db, 2); + input.set_field(&mut db).to(2); assert_eq!(final_result(&db, input), 1 * 2 + 0 * 2); 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 }))", ]"#]]); } diff --git a/salsa-2022-tests/tests/deletion.rs b/salsa-2022-tests/tests/deletion.rs index b5c756b4..fdd453f8 100644 --- a/salsa-2022-tests/tests/deletion.rs +++ b/salsa-2022-tests/tests/deletion.rs @@ -103,15 +103,15 @@ fn basic() { // * the struct itself // * the struct's field // * the `contribution_from_struct` result - input.set_field(&mut db, 2); + input.set_field(&mut db).to(2); assert_eq!(final_result(&db, input), 1 * 2 + 0 * 2); 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 }))", ]"#]]); } diff --git a/salsa-2022-tests/tests/expect_reuse_field_x_of_a_tracked_struct_changes_but_fn_depends_on_field_y.rs b/salsa-2022-tests/tests/expect_reuse_field_x_of_a_tracked_struct_changes_but_fn_depends_on_field_y.rs index 86cf517c..e4185c7d 100644 --- a/salsa-2022-tests/tests/expect_reuse_field_x_of_a_tracked_struct_changes_but_fn_depends_on_field_y.rs +++ b/salsa-2022-tests/tests/expect_reuse_field_x_of_a_tracked_struct_changes_but_fn_depends_on_field_y.rs @@ -91,7 +91,7 @@ fn execute() { "final_result_depends_on_y(MyInput(Id { value: 1 }))", ]"#]]); - input.set_field(&mut db, 23); + input.set_field(&mut db).to(23); // x = (23 + 1) / 2 = 12 // Intermediate result x changes, so final result depends on x // needs to be recomputed; diff --git a/salsa-2022-tests/tests/expect_reuse_field_x_of_an_input_changes_but_fn_depends_on_field_y.rs b/salsa-2022-tests/tests/expect_reuse_field_x_of_an_input_changes_but_fn_depends_on_field_y.rs index cb1331c7..5de3b98e 100644 --- a/salsa-2022-tests/tests/expect_reuse_field_x_of_an_input_changes_but_fn_depends_on_field_y.rs +++ b/salsa-2022-tests/tests/expect_reuse_field_x_of_an_input_changes_but_fn_depends_on_field_y.rs @@ -70,7 +70,7 @@ fn execute() { "result_depends_on_y(MyInput(Id { value: 1 }))", ]"#]]); - input.set_x(&mut db, 23); + input.set_x(&mut db).to(23); // input x changes, so result depends on x needs to be recomputed; assert_eq!(result_depends_on_x(&db, input), 24); db.assert_logs(expect![[r#" diff --git a/salsa-2022-tests/tests/hello_world.rs b/salsa-2022-tests/tests/hello_world.rs index 2484245e..99d53940 100644 --- a/salsa-2022-tests/tests/hello_world.rs +++ b/salsa-2022-tests/tests/hello_world.rs @@ -68,14 +68,14 @@ fn execute() { // Intermediate result is the same, so final result does // not need to be recomputed: - input.set_field(&mut db, 23); + input.set_field(&mut db).to(23); assert_eq!(final_result(&db, input), 22); db.assert_logs(expect![[r#" [ "intermediate_result(MyInput(Id { value: 1 }))", ]"#]]); - input.set_field(&mut db, 24); + input.set_field(&mut db).to(24); assert_eq!(final_result(&db, input), 24); db.assert_logs(expect![[r#" [ @@ -101,7 +101,7 @@ fn red_herring() { // This will trigger a new revision in the database // but shouldn't actually invalidate our existing ones. let input2 = MyInput::new(&mut db, 44); - input2.set_field(&mut db, 66); + input2.set_field(&mut db).to(66); // Re-run the query on the original input. Nothing re-executes! assert_eq!(final_result(&db, input), 22); diff --git a/salsa-2022-tests/tests/mutate_in_place.rs b/salsa-2022-tests/tests/mutate_in_place.rs index 83166c96..b6330345 100644 --- a/salsa-2022-tests/tests/mutate_in_place.rs +++ b/salsa-2022-tests/tests/mutate_in_place.rs @@ -44,12 +44,12 @@ fn execute() { // Overwrite field with an empty String // and store the old value in my_string - let mut my_string = input.set_field(&mut db, String::new()); + let mut my_string = input.set_field(&mut db).to(String::new()); my_string.push_str(" World!"); // Set the field back to out initial String, // expecting to get the empty one back - assert_eq!(input.set_field(&mut db, my_string), ""); + assert_eq!(input.set_field(&mut db).to(my_string), ""); // Check if the stored String is the one we expected assert_eq!(input.field(&db), "Hello World!"); diff --git a/salsa-2022-tests/tests/override_new_get_set.rs b/salsa-2022-tests/tests/override_new_get_set.rs index 86a5190c..80470e67 100644 --- a/salsa-2022-tests/tests/override_new_get_set.rs +++ b/salsa-2022-tests/tests/override_new_get_set.rs @@ -27,7 +27,7 @@ impl MyInput { } pub fn set_field(self, db: &mut dyn Db, id: String) { - self.set_text(db, id); + self.set_text(db).to(id); } } diff --git a/salsa-2022-tests/tests/parallel/parallel_cycle_none_recover.rs b/salsa-2022-tests/tests/parallel/parallel_cycle_none_recover.rs index 5a0227f2..5851f948 100644 --- a/salsa-2022-tests/tests/parallel/parallel_cycle_none_recover.rs +++ b/salsa-2022-tests/tests/parallel/parallel_cycle_none_recover.rs @@ -64,8 +64,8 @@ fn execute() { if let Some(c) = err_b.downcast_ref::() { 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)); diff --git a/salsa-2022-tests/tests/specify_tracked_fn_in_rev_1_but_not_2.rs b/salsa-2022-tests/tests/specify_tracked_fn_in_rev_1_but_not_2.rs index c1ab5003..f1caa1e2 100644 --- a/salsa-2022-tests/tests/specify_tracked_fn_in_rev_1_but_not_2.rs +++ b/salsa-2022-tests/tests/specify_tracked_fn_in_rev_1_but_not_2.rs @@ -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 }", ]"#]]); @@ -207,18 +207,18 @@ fn test_run_0_then_5_then_20() { // // * `create_tracked` does re-execute, but specifies same value for `maybe_specified` as before // * `read_maybe_specified` does not re-execute (its input has not changed) - input.set_field(&mut db, 5); + input.set_field(&mut db).to(5); assert_eq!(final_result(&db, input), 100); 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(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: @@ -226,24 +226,24 @@ fn test_run_0_then_5_then_20() { // * `create_tracked` re-executes but does not specify any value // * `read_maybe_specified` is invoked and it calls `maybe_specified`, which now executes // (its value has not been specified) - input.set_field(&mut db, 20); + input.set_field(&mut db).to(20); assert_eq!(final_result(&db, input), 200); 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(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 }", ]"#]]); @@ -278,18 +278,18 @@ fn test_run_0_then_5_then_10_then_20() { // // * `create_tracked` does re-execute, but specifies same value for `maybe_specified` as before // * `read_maybe_specified` does not re-execute (its input has not changed) - input.set_field(&mut db, 5); + input.set_field(&mut db).to(5); assert_eq!(final_result(&db, input), 100); 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(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: @@ -297,45 +297,45 @@ fn test_run_0_then_5_then_10_then_20() { // * `create_tracked` does re-execute and specifies no value for `maybe_specified` // * `maybe_specified_value` returns 10; this is the same value as was specified. // * `read_maybe_specified` therefore does NOT need to execute. - input.set_field(&mut db, 10); + input.set_field(&mut db).to(10); assert_eq!(final_result(&db, input), 100); 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(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: // // * Everything re-executes to get new result (200). - input.set_field(&mut db, 20); + input.set_field(&mut db).to(20); assert_eq!(final_result(&db, input), 200); 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(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,35 +351,35 @@ 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 }", ]"#]]); - input.set_field(&mut db, 20); + input.set_field(&mut db).to(20); assert_eq!(final_result(&db, input), 200); 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(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 }", diff --git a/salsa-2022-tests/tests/tracked_fn_read_own_entity.rs b/salsa-2022-tests/tests/tracked_fn_read_own_entity.rs index 949a5427..6d45a9e2 100644 --- a/salsa-2022-tests/tests/tracked_fn_read_own_entity.rs +++ b/salsa-2022-tests/tests/tracked_fn_read_own_entity.rs @@ -69,14 +69,14 @@ fn one_entity() { // Intermediate result is the same, so final result does // not need to be recomputed: - input.set_field(&mut db, 23); + input.set_field(&mut db).to(23); assert_eq!(final_result(&db, input), 22); db.assert_logs(expect![[r#" [ "intermediate_result(MyInput(Id { value: 1 }))", ]"#]]); - input.set_field(&mut db, 24); + input.set_field(&mut db).to(24); assert_eq!(final_result(&db, input), 24); db.assert_logs(expect![[r#" [ @@ -102,7 +102,7 @@ fn red_herring() { // This will trigger a new revision in the database // but shouldn't actually invalidate our existing ones. let input2 = MyInput::new(&mut db, 44); - input2.set_field(&mut db, 66); + input2.set_field(&mut db).to(66); // Re-run the query on the original input. Nothing re-executes! assert_eq!(final_result(&db, input), 22);