Skip to content

Comments

Collect cycle heads transitively#1050

Merged
MichaReiser merged 11 commits intosalsa-rs:masterfrom
MichaReiser:micha/cycle-participant-keep-lock
Jan 5, 2026
Merged

Collect cycle heads transitively#1050
MichaReiser merged 11 commits intosalsa-rs:masterfrom
MichaReiser:micha/cycle-participant-keep-lock

Conversation

@MichaReiser
Copy link
Contributor

@MichaReiser MichaReiser commented Dec 30, 2025

I started looking into fixing the maybe_changed_after unsoundness when I noticed that I don't fully understand how it can happen that outer_cycle is None for a query that has cycle heads but doesn't depend on itself. It's essential that there's always an outer cycle in that case that finalizes the cycle participant once it converges.

My first change was to make Salsa panic if we encounter the situation that outer_cycle is None (and the query has cycle heads but doesn't depend on itself), but we then started seeing frequent panics in ty. So I dug a bit deeper and found that we need to transitively collect the cycle heads (only going one level deep isn't enough).

I added a regression test that demonstrates why transitively collecting all cycle heads is necessary.

Knowing the outer cycle is not only necessary so that we can transfer the head's lock to the proper outer cycle, it's also necessary so that the memo's considered stale when the iteration count of the outer-most cycle changes (validate_same_iteration).

@netlify
Copy link

netlify bot commented Dec 30, 2025

Deploy Preview for salsa-rs canceled.

Name Link
🔨 Latest commit 1fcdc98
🔍 Latest deploy log https://app.netlify.com/projects/salsa-rs/deploys/695406a5dae7f10008e13f4e

@netlify
Copy link

netlify bot commented Dec 30, 2025

Deploy Preview for salsa-rs ready!

Name Link
🔨 Latest commit d74a59a
🔍 Latest deploy log https://app.netlify.com/projects/salsa-rs/deploys/695bb0dd03d2e300083aec34
😎 Deploy Preview https://deploy-preview-1050--salsa-rs.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@codspeed-hq
Copy link

codspeed-hq bot commented Dec 30, 2025

CodSpeed Performance Report

Merging #1050 will not alter performance

Comparing MichaReiser:micha/cycle-participant-keep-lock (d74a59a) with master (23de837)

Summary

✅ 13 untouched

@MichaReiser MichaReiser changed the title Don't release lock when cycle head becomes cycle participant Collect cycle heads transitively Dec 31, 2025
@MichaReiser MichaReiser force-pushed the micha/cycle-participant-keep-lock branch from d9c263e to 797f85b Compare December 31, 2025 12:39
@MichaReiser MichaReiser added the bug Something isn't working label Dec 31, 2025
@MichaReiser MichaReiser marked this pull request as ready for review December 31, 2025 12:42
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes an unsoundness issue in Salsa's cycle detection by transitively collecting cycle heads instead of only going one level deep. The key changes ensure that queries participating in nested cycles properly track all outer cycle heads, which is necessary for correct memoization invalidation and cycle finalization.

  • Refactored collect_all_cycle_heads to recursively collect all cycle heads transitively
  • Added panic in complete_cycle_participant when outer_cycle is None for non-self-dependent cycle participants
  • Added regression test demonstrating the necessity of transitive cycle head collection

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 6 comments.

File Description
tests/parallel/cycle_nested_deep_conditional.rs Fixed thread span naming to correctly identify threads t2, t3, and t4
tests/cycle_stale_cycle_heads.rs New regression test demonstrating the stale cycle heads scenario with deeply nested cycles
src/function/execute.rs Core logic changes: reordered condition check in outer_cycle, refactored collect_all_cycle_heads to use recursive collection, and added panic for missing outer cycle

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@MichaReiser MichaReiser force-pushed the micha/cycle-participant-keep-lock branch from e5e840f to 56c62b9 Compare December 31, 2025 14:14
@MichaReiser MichaReiser force-pushed the micha/cycle-participant-keep-lock branch from 5039f35 to b92dc45 Compare December 31, 2025 14:53
for (head_key, iteration_count) in missing_heads {
max_iteration_count = max_iteration_count.max(iteration_count);
depends_on_self |= head_key == database_key_index;
let mut missing_heads: SmallVec<[(DatabaseKeyIndex, IterationCount); 4]> = SmallVec::new();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume the choice of 4 is ~arbitrary here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes

Co-authored-by: Ibraheem Ahmed <ibraheem@ibraheem.ca>
@MichaReiser MichaReiser added this pull request to the merge queue Jan 5, 2026
Merged via the queue into salsa-rs:master with commit 103fa51 Jan 5, 2026
23 of 26 checks passed
@MichaReiser MichaReiser deleted the micha/cycle-participant-keep-lock branch January 5, 2026 13:22
@github-actions github-actions bot mentioned this pull request Jan 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants