//! Basic deletion test: //! //! * entities not created in a revision are deleted, as is any memoized data keyed on them. mod common; use salsa::{Database, Setter}; use test_log::test; #[salsa::input] struct MyInput { identity: u32, } #[salsa::tracked] struct MyTracked<'db> { #[id] identifier: u32, #[return_ref] field: Bomb, } thread_local! { static DROPPED: std::cell::RefCell> = const { std::cell::RefCell::new(vec![]) }; } fn dropped() -> Vec { DROPPED.with(|d| d.borrow().clone()) } #[derive(Clone, Debug, PartialEq, Eq)] struct Bomb { identity: u32, } impl Drop for Bomb { fn drop(&mut self) { DROPPED.with(|d| d.borrow_mut().push(self.identity)); } } #[salsa::tracked] impl MyInput { #[salsa::tracked] fn create_tracked_struct(self, db: &dyn Database) -> MyTracked<'_> { MyTracked::new( db, self.identity(db), Bomb { identity: self.identity(db), }, ) } } #[test] fn deletion_drops() { let mut db = salsa::DatabaseImpl::new(); let input = MyInput::new(&db, 22); expect_test::expect![[r#" [] "#]] .assert_debug_eq(&dropped()); let tracked_struct = input.create_tracked_struct(&db); assert_eq!(tracked_struct.field(&db).identity, 22); expect_test::expect![[r#" [] "#]] .assert_debug_eq(&dropped()); input.set_identity(&mut db).to(44); expect_test::expect![[r#" [] "#]] .assert_debug_eq(&dropped()); // Now that we execute with rev = 44, the old id is put on the free list let tracked_struct = input.create_tracked_struct(&db); assert_eq!(tracked_struct.field(&db).identity, 44); expect_test::expect![[r#" [] "#]] .assert_debug_eq(&dropped()); // When we execute again with `input1`, that id is re-used, so the old value is deleted let input1 = MyInput::new(&db, 66); let _tracked_struct1 = input1.create_tracked_struct(&db); expect_test::expect![[r#" [ 22, ] "#]] .assert_debug_eq(&dropped()); }