diff --git a/src/active_query.rs b/src/active_query.rs index 64ccfb85b..2cc29591c 100644 --- a/src/active_query.rs +++ b/src/active_query.rs @@ -89,6 +89,8 @@ impl ActiveQuery { // Mark all tracked structs from the previous iteration as active. self.tracked_struct_ids .mark_all_active(active_tracked_ids.iter().copied()); + self.disambiguator_map + .seed(active_tracked_ids.iter().map(|(id, _)| id)); } pub(super) fn take_cycle_heads(&mut self) -> CycleHeads { diff --git a/src/function/execute.rs b/src/function/execute.rs index a67b40bec..5e520605c 100644 --- a/src/function/execute.rs +++ b/src/function/execute.rs @@ -172,7 +172,6 @@ where // This is different from `opt_old_memo` which might be from a different revision. let mut last_provisional_memo_opt: Option<&Memo<'db, C>> = None; - // TODO: Can we seed those somehow? let mut last_stale_tracked_ids: Vec<(Identity, Id)> = Vec::new(); let mut iteration_count = IterationCount::initial(); diff --git a/src/tracked_struct.rs b/src/tracked_struct.rs index a83d5b456..a6a5a5d0e 100644 --- a/src/tracked_struct.rs +++ b/src/tracked_struct.rs @@ -461,11 +461,20 @@ impl DisambiguatorMap { result } - pub fn clear(&mut self) { + pub(crate) fn seed<'a>(&mut self, identities: impl Iterator) { + for identity in identities { + self.disambiguate(IdentityHash { + ingredient_index: identity.ingredient_index, + hash: identity.hash, + }); + } + } + + pub(crate) fn clear(&mut self) { self.map.clear() } - pub fn is_empty(&self) -> bool { + pub(crate) fn is_empty(&self) -> bool { self.map.is_empty() } } diff --git a/tests/cycle_tracked.rs b/tests/cycle_tracked.rs index ca2faebff..9cb12b84d 100644 --- a/tests/cycle_tracked.rs +++ b/tests/cycle_tracked.rs @@ -302,3 +302,36 @@ fn test_cycle_with_fixpoint_structs() { "DidDiscard { key: IterationNode(Id(402)) }", ]"#]]); } + +#[salsa::tracked(debug)] +struct NameWithOffset<'db> { + name: String, + + #[tracked] + offset: u32, +} + +#[test] +fn cycle_tracked_struct_with_tracked_field() { + #[salsa::tracked(cycle_initial=|_,_| 0)] + fn query_a(db: &dyn salsa::Database) -> u32 { + let offset = query_b(db); + + let tracked = NameWithOffset::new(db, "test".to_string(), offset); + + tracked.offset(db) + } + + #[salsa::tracked] + fn query_b(db: &dyn salsa::Database) -> u32 { + let base_offset = query_a(db); + + (base_offset + 1).min(5) + } + + let db = salsa::DatabaseImpl::default(); + + let result = query_a(&db); + + assert_eq!(result, 5); +}