diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 1a792ed5..5dbfff70 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -51,7 +51,7 @@ jobs: - name: Format run: cargo fmt -- --check - name: Clippy - run: cargo clippy --workspace --all-features --all-targets + run: cargo clippy --workspace --all-features --all-targets -- -D warnings - name: Test run: cargo test --workspace --all-features --all-targets - name: Test docs diff --git a/Cargo.toml b/Cargo.toml index e2192d4c..e9db3355 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,7 +9,6 @@ description = "A generic framework for on-demand, incrementalized computation (e [dependencies] arc-swap = "1" -boomphf = "0.6" crossbeam = "0.8" dashmap = "6" hashlink = "0.9" @@ -32,7 +31,7 @@ eyre = "0.6.8" notify-debouncer-mini = "0.4.1" ordered-float = "4.2.1" rustversion = "1.0" -test-log = "0.2.11" +test-log = { version ="0.2.11", features = ["trace"] } trybuild = "1.0" diff --git a/components/salsa-macro-rules/src/setup_input_struct.rs b/components/salsa-macro-rules/src/setup_input_struct.rs index ab2fbc63..f5a0f984 100644 --- a/components/salsa-macro-rules/src/setup_input_struct.rs +++ b/components/salsa-macro-rules/src/setup_input_struct.rs @@ -86,13 +86,13 @@ macro_rules! setup_input_struct { }) } - pub fn ingredient_mut(db: &mut dyn $zalsa::Database) -> (&mut $zalsa_struct::IngredientImpl, $zalsa::Revision) { + pub fn ingredient_mut(db: &mut dyn $zalsa::Database) -> (&mut $zalsa_struct::IngredientImpl, &mut $zalsa::Runtime) { let zalsa_mut = db.zalsa_mut(); let index = zalsa_mut.add_or_lookup_jar_by_type(&<$zalsa_struct::JarImpl<$Configuration>>::default()); let current_revision = zalsa_mut.current_revision(); - let ingredient = zalsa_mut.lookup_ingredient_mut(index); + let (ingredient, runtime) = zalsa_mut.lookup_ingredient_mut(index); let ingredient = ingredient.assert_type_mut::<$zalsa_struct::IngredientImpl>(); - (ingredient, current_revision) + (ingredient, runtime) } } diff --git a/components/salsa-macro-rules/src/setup_tracked_fn.rs b/components/salsa-macro-rules/src/setup_tracked_fn.rs index 58d88875..9a072a93 100644 --- a/components/salsa-macro-rules/src/setup_tracked_fn.rs +++ b/components/salsa-macro-rules/src/setup_tracked_fn.rs @@ -225,6 +225,7 @@ macro_rules! setup_tracked_fn { } } + #[allow(non_local_definitions)] impl $fn_name { pub fn accumulated<$db_lt, A: salsa::Accumulator>( $db: &$db_lt dyn $Db, diff --git a/src/active_query.rs b/src/active_query.rs index bc723655..eb728597 100644 --- a/src/active_query.rs +++ b/src/active_query.rs @@ -110,7 +110,7 @@ impl ActiveQuery { } /// Adds any dependencies from `other` into `self`. - /// Used during cycle recovery, see [`Runtime::create_cycle_error`]. + /// Used during cycle recovery, see [`Runtime::unblock_cycle_and_maybe_throw`]. pub(super) fn add_from(&mut self, other: &ActiveQuery) { self.changed_at = self.changed_at.max(other.changed_at); self.durability = self.durability.min(other.durability); @@ -120,7 +120,7 @@ impl ActiveQuery { } /// Removes the participants in `cycle` from my dependencies. - /// Used during cycle recovery, see [`Runtime::create_cycle_error`]. + /// Used during cycle recovery, see [`Runtime::unblock_cycle_and_maybe_throw`]. pub(super) fn remove_cycle_participants(&mut self, cycle: &Cycle) { for p in cycle.participant_keys() { let p: DependencyIndex = p.into(); @@ -129,7 +129,7 @@ impl ActiveQuery { } /// Copy the changed-at, durability, and dependencies from `cycle_query`. - /// Used during cycle recovery, see [`Runtime::create_cycle_error`]. + /// Used during cycle recovery, see [`Runtime::unblock_cycle_and_maybe_throw`]. pub(crate) fn take_inputs_from(&mut self, cycle_query: &ActiveQuery) { self.changed_at = cycle_query.changed_at; self.durability = cycle_query.durability; diff --git a/src/array.rs b/src/array.rs index c9441093..ef82d9dd 100644 --- a/src/array.rs +++ b/src/array.rs @@ -1,6 +1,7 @@ +use std::fmt::Debug; use std::ops::{Deref, DerefMut}; -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub struct Array { data: [T; N], } diff --git a/src/cycle.rs b/src/cycle.rs index 44558b4a..6071aa30 100644 --- a/src/cycle.rs +++ b/src/cycle.rs @@ -94,17 +94,15 @@ impl std::fmt::Debug for Cycle { pub enum CycleRecoveryStrategy { /// Cannot recover from cycles: panic. /// - /// This is the default. It is also what happens if a cycle - /// occurs and the queries involved have different recovery - /// strategies. + /// This is the default. /// /// In the case of a failure due to a cycle, the panic - /// value will be XXX (FIXME). + /// value will be the `Cycle`. Panic, /// Recovers from cycles by storing a sentinel value. /// - /// This value is computed by the `QueryFunction::cycle_fallback` + /// This value is computed by the query's `recovery_fn` /// function. Fallback, } diff --git a/src/function.rs b/src/function.rs index bd39a4fe..fca066c7 100644 --- a/src/function.rs +++ b/src/function.rs @@ -65,7 +65,7 @@ pub trait Configuration: Any { /// This invokes the function the user wrote. fn execute<'db>(db: &'db Self::DbView, input: Self::Input<'db>) -> Self::Output<'db>; - /// If the cycle strategy is `Recover`, then invoked when `key` is a participant + /// If the cycle strategy is `Fallback`, then invoked when `key` is a participant /// in a cycle to find out what value it should have. /// /// This invokes the recovery function given by the user. diff --git a/src/input.rs b/src/input.rs index 5ab315f9..1da42d75 100644 --- a/src/input.rs +++ b/src/input.rs @@ -20,7 +20,7 @@ use crate::{ plumbing::{Jar, Stamp}, zalsa::IngredientIndex, zalsa_local::QueryOrigin, - Database, Durability, Id, Revision, + Database, Durability, Id, Revision, Runtime, }; pub trait Configuration: Any { @@ -35,7 +35,7 @@ pub trait Configuration: Any { type Fields: Send + Sync; /// A array of [`StampedValue<()>`](`StampedValue`) tuples, one per each of the value fields. - type Stamps: Send + Sync + DerefMut; + type Stamps: Send + Sync + fmt::Debug + DerefMut; } pub struct JarImpl { @@ -120,7 +120,7 @@ impl IngredientImpl { /// * `setter`, function that modifies the fields tuple; should only modify the element for `field_index` pub fn set_field( &mut self, - current_revision: Revision, + runtime: &mut Runtime, id: C::Struct, field_index: usize, durability: Durability, @@ -129,8 +129,13 @@ impl IngredientImpl { let id: Id = id.as_id(); let mut r = self.struct_map.update(id); let stamp = &mut r.stamps[field_index]; + + if stamp.durability != Durability::LOW { + runtime.report_tracked_write(stamp.durability); + } + stamp.durability = durability; - stamp.changed_at = current_revision; + stamp.changed_at = runtime.current_revision(); setter(&mut r.fields) } diff --git a/src/input/setter.rs b/src/input/setter.rs index e19d9c95..a976aad0 100644 --- a/src/input/setter.rs +++ b/src/input/setter.rs @@ -1,7 +1,7 @@ use std::marker::PhantomData; use crate::input::{Configuration, IngredientImpl}; -use crate::{Durability, Revision}; +use crate::{Durability, Runtime}; /// Setter for a field of an input. pub trait Setter: Sized { @@ -12,7 +12,7 @@ pub trait Setter: Sized { #[must_use] pub struct SetterImpl<'setter, C: Configuration, S, F> { - current_revision: Revision, + runtime: &'setter mut Runtime, id: C::Struct, ingredient: &'setter mut IngredientImpl, durability: Durability, @@ -27,14 +27,14 @@ where S: FnOnce(&mut C::Fields, F) -> F, { pub fn new( - current_revision: Revision, + runtime: &'setter mut Runtime, id: C::Struct, field_index: usize, ingredient: &'setter mut IngredientImpl, setter: S, ) -> Self { SetterImpl { - current_revision, + runtime, id, field_index, ingredient, @@ -59,7 +59,7 @@ where fn to(self, value: F) -> F { let Self { - current_revision, + runtime, id, ingredient, durability, @@ -68,7 +68,7 @@ where phantom: _, } = self; - ingredient.set_field(current_revision, id, field_index, durability, |tuple| { + ingredient.set_field(runtime, id, field_index, durability, |tuple| { setter(tuple, value) }) } diff --git a/src/zalsa.rs b/src/zalsa.rs index dabd249b..7a950dcc 100644 --- a/src/zalsa.rs +++ b/src/zalsa.rs @@ -171,8 +171,14 @@ impl Zalsa { } /// **NOT SEMVER STABLE** - pub fn lookup_ingredient_mut(&mut self, index: IngredientIndex) -> &mut dyn Ingredient { - &mut **(&mut self.ingredients_vec[index.as_usize()]) + pub fn lookup_ingredient_mut( + &mut self, + index: IngredientIndex, + ) -> (&mut dyn Ingredient, &mut Runtime) { + ( + &mut **(&mut self.ingredients_vec[index.as_usize()]), + &mut self.runtime, + ) } /// **NOT SEMVER STABLE** diff --git a/src/zalsa_local.rs b/src/zalsa_local.rs index 3d944858..19362a97 100644 --- a/src/zalsa_local.rs +++ b/src/zalsa_local.rs @@ -109,7 +109,7 @@ impl ZalsaLocal { changed_at: Revision, ) { debug!( - "report_query_read_and_unwind_if_cycle_resulted(input={:?}, durability={:?}, changed_at={:?})", + "report_tracked_read(input={:?}, durability={:?}, changed_at={:?})", input, durability, changed_at ); self.with_query_stack(|stack| { diff --git a/tests/cycles.rs b/tests/cycles.rs index 1cc2f06a..4aca2fce 100644 --- a/tests/cycles.rs +++ b/tests/cycles.rs @@ -49,9 +49,6 @@ use salsa::Durability; // | Cross | Fallback | N/A | Tracked | both | parallel/parallel_cycle_mid_recover.rs | // | Cross | Fallback | N/A | Tracked | both | parallel/parallel_cycle_all_recover.rs | -// TODO: The following test is not yet ported. -// | Intra | Fallback | Old | Tracked | direct | cycle_disappears_durability | - #[derive(PartialEq, Eq, Hash, Clone, Debug)] struct Error { cycle: Vec, diff --git a/tests/tracked_fn_high_durability_dependency.rs b/tests/tracked_fn_high_durability_dependency.rs new file mode 100644 index 00000000..a05be178 --- /dev/null +++ b/tests/tracked_fn_high_durability_dependency.rs @@ -0,0 +1,36 @@ +#![allow(warnings)] + +use salsa::plumbing::HasStorage; +use salsa::{Database, Durability, Setter}; + +mod common; +#[salsa::input] +struct MyInput { + field: u32, +} + +#[salsa::tracked] +fn tracked_fn(db: &dyn salsa::Database, input: MyInput) -> u32 { + input.field(db) * 2 +} + +#[test] +fn execute() { + let mut db = salsa::DatabaseImpl::default(); + + let input_high = MyInput::new(&mut db, 0); + input_high + .set_field(&mut db) + .with_durability(Durability::HIGH) + .to(2200); + + assert_eq!(tracked_fn(&db, input_high), 4400); + + // Changing the value should re-execute the query + input_high + .set_field(&mut db) + .with_durability(Durability::HIGH) + .to(2201); + + assert_eq!(tracked_fn(&db, input_high), 4402); +}