Skip to content

fix(language): a divisor that a shift fills with 0 at the edge is refused at load - #889

Draft
FBumann wants to merge 3 commits into
mainfrom
fix/divisor-edge
Draft

FBumann wants to merge 3 commits into
mainfrom
fix/divisor-edge

Conversation

@FBumann

@FBumann FBumann commented Oct 15, 2026

Copy link
Copy Markdown
Contributor

Prompt: We should fix the bug on main directly in another pr

Note

The following content was generated by AI.

p / shift(c, along=t, offset=1, edge=0) loaded and divided by 0 at the edge, whatever the data held. A divisor that edge=0 can make 0 is now refused at load, with the rewrite named.

What changes, how it was checked, what was not done

The rule. edge=0 puts a 0 where a shift vacates, so the file itself makes the divisor 0 there. _zero_in in _expression_resolver.py walks the whole divisor. The shift makes the divisor 0 where it is a factor, a numerator, a base, or the operand of a negation, a sum, a window, another shift, a lookup or a named expression; where any region of a case holds it; and in a sum only where every term can be 0, so shift(c, …, edge=0) + 1 loads. The message:

Constraint 'cap': the divisor is 0 where shift(along=g, edge=0) vacates, which no number divides by. Write edge='wrap', or an edge= value other than 0.

It is refused in every position, a reported expression included. There a zero divisor makes the quotient absent, but edge=0 in a divisor is never the way to ask for that: a shift with no edge= vacates to absence already. expressions.md states the rule beside the other rules for /.

Reproduced first. On origin/main (7cc9515), x / shift(p, along=t, offset=1, edge=0) and x / (2 * shift(…, edge=0)) both loaded. The first test commit's five refusal cases failed there; the three loading cases passed.

Mutation table. Each branch of _zero_in was deleted by hand. tests/test_validation.py -k shift_fills was run, the file was restored through git checkout -- with __pycache__ dropped on both sides, and the tree came back clean each time.

Branch deleted Cases that fail
edge=0 is the zero 12
through a negation, a sum, a window, a shift 3
through a lookup, a named expression 3
a factor 1
a numerator 1
a base 1
a sum needs every term 1
a region of a case 1

Gates. pixi run lint and pixi run test pass (2931 passed, 1 skipped). docs-build and compile-tex were not run.

Relation to #880. #880 adds the same walk for a missing: 0 parameter. This PR's _zero_in returns the reason and the rewrite, so #880 can add its case to this one helper when it is merged, rather than keep a second walk.

Not done. sum_back stops short at the edge and sums fewer terms; that is not a 0 the file puts in, so it is not refused.

🤖 Generated with Claude Code

https://claude.ai/code/session_01AvtZGymCbY9swLnR8JwHng


Generated by Claude Code

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AvtZGymCbY9swLnR8JwHng
…used at load

`edge=0` puts a 0 where a shift vacates, whatever the data holds, so
`p / shift(c, along=t, offset=1, edge=0)` divided by 0 at the edge and
loaded. The refusal walks the whole divisor: a factor, a numerator, a
base, the operand of a sum, a window, a shift or a lookup, a named
expression or a region of a case, and a sum only where every term can be
0. The message names the rewrite: `edge='wrap'`, or another edge value.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AvtZGymCbY9swLnR8JwHng
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AvtZGymCbY9swLnR8JwHng
@read-the-docs-community

Copy link
Copy Markdown

Documentation build overview

📚 mathspec | 🛠️ Build #35172449 | 📁 Comparing 0209c0d against latest (7cc9515)

  🔍 Preview build  

2 files changed
± changelog/index.html
± reference/language/expressions/index.html

@FBumann FBumann added the v0.5.0 label Oct 22, 2026
FBumann pushed a commit that referenced this pull request Oct 23, 2026
…used at load

The check that refuses a divisor a missing row of a missing: 0 parameter
makes 0 now also names an edge=0 shift as a cause, through the same walk.
The tests and the rule in expressions.md come from #889.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W7L7U7Av5v8wnKV6eDpXfi
@FBumann
FBumann marked this pull request as draft October 23, 2026 13:26

FBumann commented Oct 23, 2026

Copy link
Copy Markdown
Contributor Author

Prompt: Why should we not do one PR per topic? Keep the enum one, combine the "missing" ones, and combine the ones making the spec fully sorted and predictable?

Note

The following content was generated by AI.

Superseded by #894 (216660d). The edge=0 rule is now one more case in #894's divisor check in _divisors.py, not a second walk. This PR's tests, refusal message and paragraph in expressions.md moved there unchanged. This PR stays open as a draft for its review history.


Generated by Claude Code

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants