Skip to content

Commit f78a641

Browse files
authored
fix: incorrect caching for queries participating in fixpoint (#843)
1 parent f8cd8e7 commit f78a641

File tree

2 files changed

+22
-16
lines changed

2 files changed

+22
-16
lines changed

src/function/backdate.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,15 @@ where
1717
revisions: &mut QueryRevisions,
1818
value: &C::Output<'db>,
1919
) {
20+
// We've seen issues where queries weren't re-validated when backdating provisional values
21+
// in ty. This is more of a bandaid because we're close to a release and don't have the time to prove
22+
// right now whether backdating could be made safe for queries participating in queries.
23+
// TODO: Write a test that demonstrates that backdating queries participating in a cycle isn't safe
24+
// OR write many tests showing that it is (and fixing the case where it didn't correctly account for today).
25+
if !revisions.cycle_heads.is_empty() {
26+
return;
27+
}
28+
2029
if let Some(old_value) = &old_memo.value {
2130
// Careful: if the value became less durable than it
2231
// used to be, that is a "breaking change" that our

src/function/maybe_changed_after.rs

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -412,20 +412,14 @@ where
412412
// in rev 1 but not in rev 2.
413413
VerifyResult::changed()
414414
}
415-
QueryOrigin::FixpointInitial => {
416-
let is_provisional = old_memo.may_be_provisional();
417-
418-
// If the value is from the same revision but is still provisional, consider it changed
419-
// because we're now in a new iteration.
420-
if shallow_update_possible && is_provisional {
421-
return VerifyResult::Changed(CycleHeads::initial(database_key_index));
422-
}
423-
424-
VerifyResult::Unchanged(
425-
InputAccumulatedValues::Empty,
426-
CycleHeads::initial(database_key_index),
427-
)
428-
}
415+
// Return `Unchanged` similar to the initial value that we insert
416+
// when we hit the cycle. Any dependencies accessed when creating the fixpoint initial
417+
// are tracked by the outer query. Nothing should have changed assuming that the
418+
// fixpoint initial function is deterministic.
419+
QueryOrigin::FixpointInitial => VerifyResult::Unchanged(
420+
InputAccumulatedValues::Empty,
421+
CycleHeads::initial(database_key_index),
422+
),
429423
QueryOrigin::DerivedUntracked(_) => {
430424
// Untracked inputs? Have to assume that it changed.
431425
VerifyResult::changed()
@@ -458,8 +452,11 @@ where
458452
last_verified_at,
459453
!cycle_heads.is_empty(),
460454
) {
461-
VerifyResult::Changed(_) => {
462-
break 'cycle VerifyResult::Changed(cycle_heads)
455+
VerifyResult::Changed(heads) => {
456+
// Carry over the heads from the inner query to avoid
457+
// backdating the outer query.
458+
cycle_heads.extend(&heads);
459+
break 'cycle VerifyResult::Changed(cycle_heads);
463460
}
464461
VerifyResult::Unchanged(input_accumulated, cycles) => {
465462
cycle_heads.extend(&cycles);

0 commit comments

Comments
 (0)