fix(dfir_lang): order loop-ingress senders before the whole loop block, fix #3048#3049
Open
MingweiSamuel wants to merge 3 commits into
Open
fix(dfir_lang): order loop-ingress senders before the whole loop block, fix #3048#3049MingweiSamuel wants to merge 3 commits into
MingweiSamuel wants to merge 3 commits into
Conversation
`make_loops_contiguous` gathers every subgraph of a loop to the flat-order position of the loop's *first* subgraph. This is only sound if every subgraph feeding the loop from outside (loop ingress) is already ordered before the loop's earliest subgraph. Otherwise gathering hoists an ingress *receiver* inside the loop ahead of its external *sender*, violating topological order. Downstream this produced a handoff-buffer "use before declaration" compile error (and, logically, a drained-but-never-filled batch). Fix: in `find_subgraph_unionfind`, add loop-ingress ordering constraints to the predecessor set that feeds the (existing, unified) topological sort. For each forward (non-tick) edge `src -> dst` where `dst` lies inside a loop that does not contain `src`, require `src` to precede *every* node inside the outermost such loop — i.e. the whole top-level loop block that will be gathered. Because this reuses the same toposort, all other ordering constraints (handoff references, access groups) are respected automatically, and non-loop programs are entirely unaffected (no constraints are added). A genuine `loop -> external -> loop` dependency (which cannot be made contiguous) now surfaces as the usual intra-tick cycle error. Also adds a defensive `debug_assert` (`subgraph_toposort_respects_handoffs`) after `make_loops_contiguous` that verifies every forward handoff's producer subgraph precedes its consumer subgraph, catching any future regression at compile time. Tests: - `dfir_lang`: `test_make_loops_contiguous_ingress_toposort` (previously `#[ignore]`d as a repro) now asserts a valid toposort and passes. - `dfir_rs` `surface_loop`: adds `test_loop_ingress_forward_ref_sources`, an end-to-end surface-syntax repro (two ingress points with sources declared after the loop) that both compiles and delivers all data. Both tests were confirmed to fail without the fix (the integration test fails at macro expansion via the new debug assertion). Co-authored-by: Infinity 🤖 <infinity@hydro.run> PR: #3049
Deploying hydro with
|
| Latest commit: |
41f9871
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://3eb60c15.hydroflow.pages.dev |
| Branch Preview URL: | https://mingwei-loop-contig.hydroflow.pages.dev |
MingweiSamuel
added a commit
that referenced
this pull request
Jul 21, 2026
MingweiSamuel
force-pushed
the
mingwei/loop-contig
branch
from
July 21, 2026 17:21
8525537 to
2391a1b
Compare
MingweiSamuel
added a commit
that referenced
this pull request
Jul 21, 2026
MingweiSamuel
force-pushed
the
mingwei/loop-contig
branch
from
July 21, 2026 17:23
2391a1b to
38e2c9e
Compare
MingweiSamuel
force-pushed
the
mingwei/loop-contig
branch
from
July 21, 2026 17:26
38e2c9e to
cedb918
Compare
MingweiSamuel
marked this pull request as ready for review
July 21, 2026 17:26
Contributor
There was a problem hiding this comment.
Pull request overview
This PR fixes a DFIR graph ordering bug where make_loops_contiguous could hoist loop-ingress receivers ahead of their external senders, breaking topological order (issue #3048). It does so by adding loop-ingress ordering constraints into the existing predecessor set that feeds the unified toposort, and adds regression coverage plus a defensive post-condition check.
Changes:
- Add loop-ingress ordering constraints during subgraph union-find/toposort construction to keep gathered loop blocks topologically valid.
- Add a defensive post-
make_loops_contiguoustopo validation check (plus a reusablevalidate_topo_sorthelper). - Add regression tests in both
dfir_lang(unit) anddfir_rs(end-to-end surface syntax).
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
| dfir_rs/tests/surface_loop.rs | Adds an end-to-end regression test covering forward-referenced loop ingress sources. |
| dfir_lang/src/graph/meta_graph.rs | Exposes loop member nodes via a new loop_nodes(loop_id) accessor. |
| dfir_lang/src/graph/graph_algorithms.rs | Adds validate_topo_sort utility and unit tests for it. |
| dfir_lang/src/graph/flat_to_partitioned.rs | Adds loop-ingress ordering constraints and a post-contiguity topo validation check; includes regression test. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
MingweiSamuel
added a commit
that referenced
this pull request
Jul 21, 2026
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> PR: #3049
shadaj
approved these changes
Jul 21, 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.
make_loops_contiguousgathers every subgraph of a loop to the flat-orderposition of the loop's first subgraph. This is only sound if every subgraph
feeding the loop from outside (loop ingress) is already ordered before the
loop's earliest subgraph. Otherwise gathering hoists an ingress receiver
inside the loop ahead of its external sender, violating topological order.
Downstream this produced a handoff-buffer "use before declaration" compile
error (and, logically, a drained-but-never-filled batch).
Fix: in
find_subgraph_unionfind, add loop-ingress ordering constraints to thepredecessor set that feeds the (existing, unified) topological sort. For each
forward (non-tick) edge
src -> dstwheredstlies inside a loop that doesnot contain
src, requiresrcto precede every node inside the outermostsuch loop — i.e. the whole top-level loop block that will be gathered. Because
this reuses the same toposort, all other ordering constraints (handoff
references, access groups) are respected automatically, and non-loop programs
are entirely unaffected (no constraints are added). A genuine
loop -> external -> loopdependency (which cannot be made contiguous) nowsurfaces as the usual intra-tick cycle error.
Also adds a defensive assertion after
make_loops_contiguousthat verifies thetoposort is still valid.
Tests:
dfir_lang:test_make_loops_contiguous_ingress_toposort(previously#[ignore]d as a repro) now asserts a valid toposort and passes.dfir_rssurface_loop: addstest_loop_ingress_forward_ref_sources, anend-to-end surface-syntax repro (two ingress points with sources declared
after the loop) that both compiles and delivers all data. Both tests were
confirmed to fail without the fix (the integration test fails at macro
expansion via the new debug assertion).