Skip to content

feat(DAG): warn when several func nodes write to the same var node - #84

Merged
thorwhalen merged 3 commits into
masterfrom
fix/warn-duplicate-outs-40
Sep 22, 2026
Merged

thorwhalen merged 3 commits into
masterfrom
fix/warn-duplicate-outs-40

Conversation

@thorwhalen

@thorwhalen thorwhalen commented Sep 22, 2026 •

Copy link
Copy Markdown
Member

Closes #40

Two FuncNodes can share an out: the DAG computes both and only the last one's value is visible, silently.

def foo(x): return x + 1
t = foo
def foo(y): return y * 2
tt = foo
DAG([t, tt])(x=1, y=2)  # 4 -- t's result is computed and dropped, no error, no warning

This PR detects that and reports it through a strategy seam:

  • DAG gets an on_duplicate_outs field (default warn_on_duplicate_outs, which raises a DuplicateOutsWarning). Alternatives shipped: ignore_duplicate_outs, raise_on_duplicate_outs, or any callable (duplicates, *, dag_name=None). duplicate_outs(func_nodes) is the public detector. All are exported from meshed.
  • The warning's stacklevel is computed (first frame outside meshed/i2), so it points at the code that built the dag — including through code_to_dag and through a custom strategy that delegates to the default.
  • Dags derived from another dag (dag[...], copy, partial, ch_funcs, add_edge, +, sum) keep the source's strategy but only hear about duplications that are new, so a pre-existing duplication is reported once, at the place it was created. A renaming copy(renamer=...) that collapses two outs into one is reported.
  • Nothing else changes: it's a warning, not an error, because existing dags may rely on the shadowing; making it an error is a breaking change that needs Thor's call (on_duplicate_outs=raise_on_duplicate_outs is there for those who want it).

Tests: meshed/tests/test_duplicate_outs.py (13 tests: explicit shared out, same __name__, no warning for distinct outs, the three strategies, derived dags silent, union warns, strategy survives derivation, opt-out survives derivation, renaming copy that creates a duplicate, warning location) plus doctests.

Review: three rounds with an independent refute-review agent. Round 1 found the warning was unattributable (<string>:9), re-fired up to 4x on derived dags, broke -W error consumers from inside meshed internals, and had no opt-out; round 2 found the seam was lost on derivation, the baked-in stacklevel broke for delegating strategies, +/sum still warned from internals, code_to_dag pointed at makers.py, and a renaming copy could create a silent duplicate. All fixed here, each with a test.

Dependents: test suites of the 10 local dependents present on this box (allude, dagapp, dotsci, extrude, front, guided, lookbook, theremin, titbit, uf) give identical results with this branch and with master (their pre-existing failures/collection errors are unchanged). meshed's own suite: 204 passed, 1 skipped, 1 pre-existing failure (test_hybrid_dag needs optional http2py/extrude). The full suite also passes under -W error::meshed.dag.DuplicateOutsWarning, i.e. meshed itself never trips its own warning.

🤖 Generated with Claude Code

thorwhalen and others added 3 commits September 22, 2026 18:14
Two FuncNodes can share an 'out', in which case the DAG silently computes both
and only the last value is visible. DAG.__post_init__ now emits a
DuplicateOutsWarning naming the shadowed var nodes and the func nodes involved.
Behaviour is otherwise unchanged (a warning, not an error, since existing dags
may rely on it).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Review of #84: make the duplicate-out check a DAG field
(on_duplicate_outs, default warn_on_duplicate_outs, alternatives
ignore_duplicate_outs / raise_on_duplicate_outs or any callable), fix
stacklevel so the warning points at the user's call site, don't re-warn
for dags derived from a dag that already warned (copy, partial,
__getitem__, ch_funcs, add_edge, ch_names), and name the node whose value
is visible in the message.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Second review round of #84:
- derived dags keep the source dag's on_duplicate_outs strategy, wrapped so it
  only hears about duplications that are NEW (only_new_duplicate_outs), which
  also catches a renaming copy() that collapses two outs into one;
- the warning's stacklevel is computed (first frame outside meshed/i2), so it
  points at the user's code for a delegating custom strategy and for
  code_to_dag too;
- '+' and sum() report only the duplications the union creates;
- raise_on_duplicate_outs reuses the formatted message; the new symbols are
  exported from meshed; annotation and docstrings corrected.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@thorwhalen
thorwhalen merged commit e52a06c into master Sep 22, 2026
6 checks passed
@thorwhalen
thorwhalen deleted the fix/warn-duplicate-outs-40 branch September 22, 2026 18:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Potential DAG (regression?) "bug": name unicity not enforced!

1 participant