Invalidate fixpoint memos after cancellation#1100
Merged
MichaReiser merged 11 commits intoJun 4, 2026
Merged
Conversation
👷 Deploy Preview for salsa-rs processing.
|
✅ Deploy Preview for salsa-rs canceled.
|
12379b4 to
ce0ea9b
Compare
MichaReiser
commented
Jun 2, 2026
| pub(crate) database_key_index: DatabaseKeyIndex, | ||
| pub(crate) iteration_count: AtomicIterationCount, | ||
| #[cfg_attr(feature = "persistence", serde(skip))] | ||
| pub(crate) iteration: AtomicIterationStamp, |
Contributor
Author
There was a problem hiding this comment.
We never persist provisional memos
f2a2340 to
3e9062b
Compare
MichaReiser
commented
Jun 2, 2026
carljm
approved these changes
Jun 3, 2026
carljm
left a comment
Contributor
There was a problem hiding this comment.
Looks good to me! Nice find that we can remove the iteration count from ActiveQuery.
This was referenced Jun 4, 2026
Merged
This was referenced Jun 4, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes the issue discussed in #1063.
Salsa "poisons" a fixpoint query when it panics when executing. All subsequent runs of that query within the same revision will panic with a
PropagatedPanic. The issue with that approach is that it incorrectly assumed that the only reason a query can panic and be re-executed in the same revision is due to a bug in the query function. However, this is not the case. A query can also panic due to cancellation that isn't followed by a write.Ideally, we'd remove the poisoning of fixpoint queries all together. But this is likely a more involved change. The challenge here is that we need a way to mark all cycle heads within a failed query as "failed" to avoid that
validate_same_iterationincorrectly returnstruefor a memo that only reference heads from a sub-cycle because we don't traverse cycle heads recursively.This PR introduces a new
cancellation_count(u8) and packs it into theIterationCount(renamed toIterationStamp). A provisional memo can only be reused if both the iteration count and the cancellation count are equal. I used an u8 because that fits into theQueryRevisionExtrapadding. Salsa will "poison" the revision when the u8 overflows. That means, Salsa will force-bump the revision incancel_othersif the cancellation count overflowed even if not followed by any writes. This has the downside that Salsa runs the more expensive deep_verify_memo for LOW durability queries during their next fetch. But that should still be cheap and I'd expect overflows to be rare.Alternatives
Poison revision
The simplest fix here is that we poison the current revision when a query with fixpoint iteration panics. Salsa bumps the revision on the next cancellation. This is by far the simplest change, but it has the downside that we always bump the revision, including panics that are bugs in the query function.
Tracking cycle states in a central location
The main challenge with fixpoint queries is that we have no reliable way to easily evict the state of an entire cycle because the state is stored across different cycle head memos. I had Codex prototype an implementation where the cycle state is stored in a centralized location #1098 but this resulted in a refactor that's way larger than I currently have an appetite for.
However, I do think that reconsidering where and how we store cycle state might be a worthwhile refactor in the future. Not only might it allow us to remove the cycle head poisoning, it may also help reduce memory usage.