Skip to content

fix(compiler): lay_el accepts datatypes and type formers only - #1426

Merged
Lorenzobattistela merged 2 commits into
bendlang:mainfrom
nicolas-abril:fix/1404-array-function-elements
Oct 8, 2026
Merged

Lorenzobattistela merged 2 commits into
bendlang:mainfrom
nicolas-abril:fix/1404-array-function-elements

Conversation

@nicolas-abril

@nicolas-abril nicolas-abril commented Oct 8, 2026 •

Copy link
Copy Markdown
Collaborator

Follow-up to #1410 (already merged), from its review.

lay_el kept an allow-list of element types that aren't datatypes: equality types for #1130, and function types since #1410. Every new kind of element type would hit an open Array element type again in the JS and C builds.

  • lay_el: accepts a datatype or one of the type formers: function (All), equality (Eql), Type (Typ) and Quant (Qnt). Those formers are a closed set. A former gets lay_of's layout, so the two stay in step. Everything else is refused as open: a type variable, a hole, a stuck application, or a law or family with no body. A missing (undefined) type is refused too, instead of crashing.
  • Comment: rewritten to match, including that a function is a box even when its arguments are erased.
  • Tests:
    • tests/reg/array_function_element.bend covers a generic Array<(T -> U32)> used with U32 and with Bool, Array.swap and Array.set under that generic domain, an Array<(@-m: Nat -> U32)> of erased-argument functions, and Array.set on a function array built recursively on a depth.
    • New tests/reg/array_open_element_family.bend: an element type that applies a type variable (Array<F(U32)> with -F: Type -> Type) still refuses.

A law or family with no body as an element type is refused by lay_el now. It can't be put in a test, because the checker stops a book with a TODO before the compiler runs.

About #1404: its Array.new(U32 -> U32, …) call stays rejected on purpose. Array.new copies its value into every leaf, so it needs Data, and closures can't be copied. Function arrays are built from ALeaf/ANode, and both halves of each ANode must have the same depth for the JS and C builds.

Validation

  • array_function_element.bend gives 49 19 a!b! 16 22 43 9 16 in the interpreter, JS and C.
  • array_open_element.bend and array_open_element_family.bend fail with an open Array element type on all three paths.
  • I ran the other 88 tests that use arrays and have expected outputs, on the three paths, before and after each commit. The results are identical.
  • bun gates/repo.ts: PASS 54/54.
  • Not run on GPU or the minis.

🤖 Generated with Claude Code

lay_el kept an allow-list of non-datatype element types (equality, now
functions). It now refuses only a type variable, or an application or
match stuck on one, and gives every other non-datatype element one box,
which is what lay_of gave them. The guide change is dropped: arrays of
functions are built leaf by leaf, which is not the usual way to use
arrays. The regression adds a generic domain, erased-argument functions,
and Array.set on a function array built by depth.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@nicolas-abril
nicolas-abril force-pushed the fix/1404-array-function-elements branch from 10da3bb to b93d46d Compare October 8, 2026 18:44
@nicolas-abril nicolas-abril changed the title fix(compiler): support concrete function array elements fix(compiler): lay_el refuses only open Array element types Oct 8, 2026
@Lorenzobattistela

Copy link
Copy Markdown
Collaborator

Thanks @nicolas-abril. Dropping the allow-list is the right direction, and the change is sound: every element type that now reaches the box path gets BOX from lay_of anywhere else too, so all callers still agree.

Checked on main 000de96 + this PR:

  • New element types now build and run the same on the interpreter, JS and C: Array<Type>, Array<Quant>, and handles (Array<File>: opened, swapped out, written, closed, read back). UBSan build clean; a 10M-iteration Array.set loop on Array<Type> stays flat.
  • Open types are still refused: array_open_element, generic Array<T>, and a type family stuck on a variable (Array<Sel(b)>).
  • Emitted C and JS for the 1,678 .bend files in tests/demos/bench are byte-identical to main (1,585 outputs; the 1,771 failing emissions fail with the same message).
  • Gates same as main: repo 54/54, ping 48/48, test 1595/1595, perf 123/124 on both (mandelbrot PAR-GPU flicker), safe 1034 agree with an identical table. tsc same as main. comp.ts 63,829 -> 63,864.

Two things before merging:

  1. The new test lines don't cover this change. All four (applyAll at U32 and Bool, sumErased, Array.set on build) are function element types, which main already accepts since fix(compiler): support concrete function array elements #1410: the updated array_function_element.bend prints 49 19 a!b! 16 22 9 16 on main too, on all three lanes. The types this PR newly accepts (types, handles) have no test, so reverting lay_el would not fail anything.

  2. Array<Chan(U32)> is still refused with an open Array element type, on all three lanes. Chan(U32) is not open: it is an opaque law applied to a closed type, one box like File, and it is even Data. The comment says only an application stuck on a type variable is refused, but every application is. This is the case the description says should no longer need another allow-list entry.

From the review of bendlang#1426. lay_el refused a short list of stuck tags, so
a stuck Ref (a law or family with no body) was laid out as a box, and an
undefined type crashed on t.$. It now accepts a datatype or one of the
type formers (function, equality, Type, Quant), which form a closed set,
returns lay_of for a former so the two stay in step, and refuses
everything else, undefined included.

Tests: Array.swap and Array.set under a generic domain, and a refusal
for an element type that applies a type variable (Array<F(U32)>).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@nicolas-abril nicolas-abril changed the title fix(compiler): lay_el refuses only open Array element types fix(compiler): lay_el accepts datatypes and type formers only Oct 8, 2026
@Lorenzobattistela
Lorenzobattistela merged commit 5750ae0 into bendlang:main Oct 8, 2026
1 check passed
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.

2 participants