Commit 839c272
fix(codegen): register struct_layouts for record-type aliases (#388)
## Summary
Record-type aliases (`type X = { ... }`) silently miscompiled when used
as function parameters or return types: every field access on such a
value resolved to offset 0.
### Root cause
`type X = { a: T, b: U }` parses to `TopType { td_body = TyAlias
(TyRecord (rfs, _)) }` (parser.mly:431). The TopType branch in
`gen_decl` (codegen.ml:2439) handled the analogous `TyStruct` case by
registering a 4-byte-stride layout in `ctx.struct_layouts`, but the
TyAlias branch caught everything with `TyAlias _ -> Ok ctx`. With no
layout registered, every `.field_N` access fell back to offset 0 — a
silent runtime miscompile, not a validation error or compile failure.
The fix adds a `TyAlias (TyRecord (rfs, _))` branch immediately before
the catch-all, mirroring the TyStruct case but unpacking the alias.
## Regression coverage
Two new tests in the `E2E WASM` group:
- **`record-alias registers struct_layouts`** — parses `type State = {
health: Int, score: Int };`, calls `gen_decl` directly, asserts
`(\"State\", [(\"health\", 0); (\"score\", 4)])` appears in
`ctx.struct_layouts`. Verified to fail on main without the fix
(stash-revert reproduces `expected Some [...] but got None`); passes
with it.
- **`non-record alias leaves struct_layouts alone`** — guards against
accidental over-broadening: `type Plain = Int` must still hit the
catch-all and add no layout entry.
## Verification
\`\`\`
$ dune build && dune runtest
…
Test Successful in 0.082s. 329 tests run.
\`\`\`
Was 327, now 329 with the two new tests. Full suite green.
## Discovered during
Field trial taking `airborne-submarine-squadron` (a 29-field state
record stepped at 60 fps over WASM) from \"compiles\" to \"runs to
conclusion\". The product currently ships via the linear backend with
flat-record boundaries; this fix removes the flatness constraint at the
per-record-alias level. WasmGC-backend record/tuple layout has a
separate, independent defect — out of scope here.
## Test plan
- [x] `dune build` clean
- [x] `dune runtest` → 329/329 green
- [x] New regression test verified to fail on main without the fix
- [x] Catch-all `TyAlias _` still reached for non-record aliases
- [ ] CI green
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>1 parent 2395c76 commit 839c272
2 files changed
Lines changed: 53 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2452 | 2452 | | |
2453 | 2453 | | |
2454 | 2454 | | |
| 2455 | + | |
| 2456 | + | |
| 2457 | + | |
| 2458 | + | |
| 2459 | + | |
| 2460 | + | |
| 2461 | + | |
| 2462 | + | |
| 2463 | + | |
2455 | 2464 | | |
2456 | 2465 | | |
2457 | 2466 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
644 | 644 | | |
645 | 645 | | |
646 | 646 | | |
| 647 | + | |
| 648 | + | |
| 649 | + | |
| 650 | + | |
| 651 | + | |
| 652 | + | |
| 653 | + | |
| 654 | + | |
| 655 | + | |
| 656 | + | |
| 657 | + | |
| 658 | + | |
| 659 | + | |
| 660 | + | |
| 661 | + | |
| 662 | + | |
| 663 | + | |
| 664 | + | |
| 665 | + | |
| 666 | + | |
| 667 | + | |
| 668 | + | |
| 669 | + | |
| 670 | + | |
| 671 | + | |
| 672 | + | |
| 673 | + | |
| 674 | + | |
| 675 | + | |
| 676 | + | |
| 677 | + | |
| 678 | + | |
| 679 | + | |
| 680 | + | |
| 681 | + | |
| 682 | + | |
| 683 | + | |
| 684 | + | |
| 685 | + | |
| 686 | + | |
647 | 687 | | |
648 | 688 | | |
649 | 689 | | |
650 | 690 | | |
651 | 691 | | |
652 | 692 | | |
653 | 693 | | |
| 694 | + | |
| 695 | + | |
| 696 | + | |
| 697 | + | |
654 | 698 | | |
655 | 699 | | |
656 | 700 | | |
| |||
0 commit comments