fix(language): a long chain of named expressions loads, a typo beside a formal is refused, and a fault in an entry hides no other - #643
Merged
FBumann merged 4 commits intoSep 23, 2026
Conversation
This was referenced Sep 23, 2026
Documentation build overview
23 files changed ·
|
… a formal is refused, and a fault in an entry hides no other The review of #626 through #638, addressed on top of #638. - A template's by= is checked before its formal columns send the call back, so sum(x, by=nope, over=a, into=b) is refused again; the over= and by= refusals say "or a formal of this macro" again; a formal along= beside a by= is pinned as building nothing. - Validation no longer raises after the macros and the expressions: entries, so a fault there hides no constraint's fault. A use of a refused entry says it does not load, and the refusal is listed with it. - A cycle closed through a macro names the macro in its chain, and one closed through a case's when is pinned. - Named expressions are resolved from a worklist in dependency order, so a chain of any length costs no stack, and the resolved tree is held to MAX_RESOLVED_DEPTH, three times what one text may nest, with a refusal that names the depth rather than the parser's message about a tree that was not deep. - A refused call builds nothing for the call around it, so sum(sum(p, into=g)) reports one fault. - A named offset or window is held to dtype: int where it is read, so offset=-tag says the dtype before the sign. - A piecewise block is refused on the link the file wrote for a str or bool breakpoint parameter and for an lp x-link with no variable; an undeclared over: is one line. - The exclusivity rewrite quotes a literal as the file wrote it. - fan_in reads through a Named; dimensions uses program.children; the walk prints "otherwise" for the last region without testing it; the census names no line that runs. - Tests pin the error class per rule, the unused template and entry refusals, +p as a named amount, and a link through a refused entry. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015h57WkBDnpxrknuJ5zZy9F
…at measured it Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015h57WkBDnpxrknuJ5zZy9F
…e test that fails without it A mutation sweep over the guards #638 moved and added left nine green. Two were redundant with the check beside them and are gone: a formal amount is caught under its sign, and a role that named no column is caught where the roles are counted. The other seven are pinned. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015h57WkBDnpxrknuJ5zZy9F
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015h57WkBDnpxrknuJ5zZy9F
FBumann
force-pushed
the
claude/peaceful-tesla-eumvcy
branch
from
September 23, 2026 11:27
ab87f55 to
ce399f8
Compare
FBumann
added this pull request to stack #644
September 23, 2026 11:32
FBumann
pushed a commit
that referenced
this pull request
Sep 23, 2026
Merged against the tree this branch was written on, the head of #638 before its rebase, so the conflicts were the four places #643 and the join touch the same lines: fan_in reads through a Named and then asks a Sum, the relation read builds a join, and the dim tests carry the error class and the join's wording. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015h57WkBDnpxrknuJ5zZy9F
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.
Note
The following content was generated by AI.
Every should-fix and nit of the stack review of #626 through #638 that is a code change, fixed on top of #638, each with the test that fails without it. Stacked on #638. The three #628 findings are fixed in #628 itself, and the stack above it is rebased.
What this changes
along=besideby=/within=refused as "no key column over"sum(x, by=nope, over=a, into=b)loaded with formal columnsover=/by=refusals lost "or a formal of this macro"raiseafter the entriesa -> aa -> m -> aRecursionErroror the parser's "nests deeper"MAX_RESOLVED_DEPTH(300), and the refusal names that depthwhensum()is aSchemaErrorLanguageErrorSchemaError, the dim rules'DimensionErrorsum(sum(p, into=g))added "already a scalar"123456789 < prewrote top > 1.23457e+08:gover:added per-link linesstr/boolbreakpoint parameter and an lp x-link with no variable were refused undercost_curve_increasing/cost_curve_domain_looffset=-taglost the dtype hintdtype: intwhere it is read, before its sign+puntested;fan_incrashed onNamed;_operandsrepeatedchildren; theotherwisetest at_armsalways true;UNREACHABLEnamed a line that runsNot changed:
Mask.names_read(#631 nit) is moot at #638, where both sides of a comparison areExpression;_check_expression'sceiling=Nonepath (#632 nit) is live at #638, where_namedpasses it.Why
The review found them, and confirmed each by loading the same model on both branches. I reproduced every one at #638's head before changing anything.
Method, gate output, alternatives
The rebase
#628 gained one commit with the three fixes and their five tests, which fail on its first commit. #629, #631, #632, #638 and this branch were rebased onto it in that order, one lease each. Two conflicts: #632's commit and this one both append to
tests/test_expansion.py, both kept; #638's fourth commit rewrote the two functions #628's fix touches, resolved with #638's version and the fix carried into it, so the fix holds at every rung. The suite ran at every rung.The chain of named expressions
Measured before the change, load then lower then typeset, on a chain
e{i} = e{i-1} + 1read by one constraint:RecursionErrorRecursionErrorRecursionErrorRecursionErrorRecursionErrore150, "nests 301 deep … past the 300 levels"So the base branch loads 200 only when the deepest entry is declared last. The worklist makes loading order-free; what remains is every later pass recursing over the resolved tree.
MAX_RESOLVED_DEPTH = 3 * MAX_DEPTHis where the passes were measured to survive: with the cap off, a chain of 200 survives every pass and 250 does not.docs/reference/language/expressions.mdstates the limit. The 80-entry chaintest_a_call_expands_to_core_astpins still loads.Error class
The rule already on
main: a dim rule the resolver needs to build a node (a where side's dims, a pullback's landing) is collected with the resolver's faults as aSchemaError. #638 added the bare sum to that set.tests/test_dimensions.pynow pins the class per case, andtests/fixtures.py's helpers raiseSchemaErrorasto_specdoes.Guards
A mutation sweep replaced each
ifof_call,_built,_bare_sum,_edge_fits,_amount,_edge,_dim_ref,_relation_ref,_known_roles,_partition,build,cycle,curve_frame,_piecewise_referencesand_domain_decides_nothingwithif False:in turn and ran the suite: 78 guards, 69 red on the first run. Of the nine green:over=1,by='lk'andover=1as a column had no test:test_a_kwarg_that_names_nothing_is_refused;curve_frame, and the values-carries-over, points-undeclared and points-carries-overrules of_piecewise_references, had none: seven cases ontest_a_malformed_block_is_refused.The sweep re-run on the touched functions is all red.
Gates
ruff check,ruff format --check: green.pyrefly check: 0 errors.pytest -q -n auto: 1598 passed, 5 skipped (the typst compiles), the walk line census included.python -m tools.schemaandpython -m tests.typesetting.golden: no diff.prettier --checkon the two changed pages: green. The Read the Docs build passed.docs-builddid not run here: the session proxy refusesdocs.python.org.compile-texdid not run: no tectonic here.Not done
The bodies of #626, #628, #632 and #638 carried the review's claim findings; each is edited to say what is true now.
🤖 Generated with Claude Code
https://claude.ai/code/session_015h57WkBDnpxrknuJ5zZy9F