diff --git a/src/input.rs b/src/input.rs index c086dcb6..6b894ca1 100644 --- a/src/input.rs +++ b/src/input.rs @@ -116,14 +116,14 @@ impl IngredientImpl { /// * `runtime`, the salsa runtiem /// * `id`, id of the input struct /// * `field_index`, index of the field that will be changed - /// * `durability`, durability of the new value + /// * `durability`, durability of the new value. If omitted, uses the durability of the previous value. /// * `setter`, function that modifies the fields tuple; should only modify the element for `field_index` pub fn set_field( &mut self, runtime: &mut Runtime, id: C::Struct, field_index: usize, - durability: Durability, + durability: Option, setter: impl FnOnce(&mut C::Fields) -> R, ) -> R { let id: Id = id.as_id(); @@ -134,7 +134,7 @@ impl IngredientImpl { runtime.report_tracked_write(stamp.durability); } - stamp.durability = durability; + stamp.durability = durability.unwrap_or(stamp.durability); stamp.changed_at = runtime.current_revision(); setter(&mut r.fields) } diff --git a/src/input/setter.rs b/src/input/setter.rs index a976aad0..6a636c5a 100644 --- a/src/input/setter.rs +++ b/src/input/setter.rs @@ -15,7 +15,7 @@ pub struct SetterImpl<'setter, C: Configuration, S, F> { runtime: &'setter mut Runtime, id: C::Struct, ingredient: &'setter mut IngredientImpl, - durability: Durability, + durability: Option, field_index: usize, setter: S, phantom: PhantomData, @@ -38,7 +38,7 @@ where id, field_index, ingredient, - durability: Durability::LOW, + durability: None, setter, phantom: PhantomData, } @@ -53,7 +53,7 @@ where type FieldTy = F; fn with_durability(mut self, durability: Durability) -> Self { - self.durability = durability; + self.durability = Some(durability); self } diff --git a/tests/input_setter_preserves_durability.rs b/tests/input_setter_preserves_durability.rs new file mode 100644 index 00000000..745f24e4 --- /dev/null +++ b/tests/input_setter_preserves_durability.rs @@ -0,0 +1,34 @@ +use test_log::test; + +use salsa::plumbing::ZalsaDatabase; +use salsa::{Durability, Setter}; + +#[salsa::input] +struct MyInput { + required_field: bool, + + #[default] + optional_field: usize, +} + +#[test] +fn execute() { + let mut db = salsa::DatabaseImpl::new(); + + let input = MyInput::builder(true) + .required_field_durability(Durability::HIGH) + .new(&db); + + // Change the field value. It should preserve high durability. + input.set_required_field(&mut db).to(false); + + let last_high_revision = db.zalsa().last_changed_revision(Durability::HIGH); + + // Changing the value again should **again** dump the high durability revision. + input.set_required_field(&mut db).to(false); + + assert_ne!( + db.zalsa().last_changed_revision(Durability::HIGH), + last_high_revision + ); +}