Lower a monomorphic (new T args) over a user ADT without crashing codegen #53

Closed
opened 2026-05-31 03:04:46 +02:00 by Brummel · 0 comments
Owner

A monomorphic (new Counter 42) over a user ADT that defines a new
function passes ail check but crashes ail build:

$ ail check examples/fieldtest/kem_2_counter_new.ail
ok (35 symbols across 3 modules)
$ ail build examples/fieldtest/kem_2_counter_new.ail --alloc=rc -o /tmp/x
Error: module `kem_2_counter_new`: def `main`: unknown variable: `Counter.new`

Reproducer: examples/fieldtest/kem_2_counter_new.ail (the (new Counter 42)
at line 31).

This is the same check-clean → build-crash class as #51, but a different
root. #51 was a polymorphic new carrying a written type-arg whose
result-only forall var defaulted to Unit. This is a monomorphic new
(no NewArg::Type) over a user ADT: the desugar lowers it to
(app Counter.new 42) — a type-scoped Var — and codegen does not
recognise Counter.new as a static callee, so the name reaches the
indirect-call path and surfaces as UnknownVar.

Claim (unverified): the gap is the lower_app / is_static_callee lockstep
pair documented in CLAUDE.md (a name lowered by neither path falls through
to the indirect call). Not yet pinned to a line.

Pre-existing at HEAD: the failure reproduces with the #51 fix (ee4107c)
stashed. The #51 fix deliberately left the monomorphic app-lowering path
unchanged, so it neither caused nor touches this. Surfaced while verifying
ee4107c.

Acceptance:

  • (new Counter 42) over a user ADT with a new def builds and runs
  • a RED test pins the build success before the fix
A monomorphic `(new Counter 42)` over a user ADT that defines a `new` function passes `ail check` but crashes `ail build`: ``` $ ail check examples/fieldtest/kem_2_counter_new.ail ok (35 symbols across 3 modules) $ ail build examples/fieldtest/kem_2_counter_new.ail --alloc=rc -o /tmp/x Error: module `kem_2_counter_new`: def `main`: unknown variable: `Counter.new` ``` Reproducer: `examples/fieldtest/kem_2_counter_new.ail` (the `(new Counter 42)` at line 31). This is the same check-clean → build-crash class as `#51`, but a different root. `#51` was a polymorphic `new` carrying a written type-arg whose result-only forall var defaulted to `Unit`. This is a *monomorphic* `new` (no `NewArg::Type`) over a user ADT: the desugar lowers it to `(app Counter.new 42)` — a type-scoped `Var` — and codegen does not recognise `Counter.new` as a static callee, so the name reaches the indirect-call path and surfaces as `UnknownVar`. Claim (unverified): the gap is the `lower_app` / `is_static_callee` lockstep pair documented in `CLAUDE.md` (a name lowered by neither path falls through to the indirect call). Not yet pinned to a line. Pre-existing at HEAD: the failure reproduces with the `#51` fix (`ee4107c`) stashed. The `#51` fix deliberately left the monomorphic app-lowering path unchanged, so it neither caused nor touches this. Surfaced while verifying `ee4107c`. Acceptance: - [ ] `(new Counter 42)` over a user ADT with a `new` def builds and runs - [ ] a RED test pins the build success before the fix
Brummel added the bug label 2026-05-31 03:04:46 +02:00
Sign in to join this conversation.