Skip to content

fix(codegen): register struct_layouts for record-type aliases - #388

Merged
hyperpolymath merged 1 commit into
mainfrom
fix/codegen-record-alias-struct-layout
May 27, 2026
Merged

fix(codegen): register struct_layouts for record-type aliases#388
hyperpolymath merged 1 commit into
mainfrom
fix/codegen-record-alias-struct-layout

Conversation

@hyperpolymath

Copy link
Copy Markdown
Owner

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

  • dune build clean
  • dune runtest → 329/329 green
  • New regression test verified to fail on main without the fix
  • Catch-all TyAlias _ still reached for non-record aliases
  • CI green

🤖 Generated with Claude Code

`type X = { a: T, b: U }` parses as `TopType { td_body = TyAlias
(TyRecord (rfs, _)) }`. The TopType branch in `gen_decl` handled
TyStruct (registering a 4-byte-stride field layout in
`ctx.struct_layouts`) but the TyAlias branch caught everything with
`TyAlias _ -> Ok ctx`, so record aliases never registered.

The downstream symptom is silent: every parameter or return of such
an alias resolves `.field_N` to offset 0 because the layout lookup
returns None. The miscompile only surfaces at runtime via wrong
field values, not a Wasm validation error or a compile failure.

Fix mirrors the existing TyStruct branch but unpacks the alias.

Regression coverage:

- `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`. This test fails on main without
  the fix (verified by stash-revert) with
  `expected Some [...] but got None`.
- `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.

327 → 329 tests; full suite green.

Refs affinescript ASBSQ trial 2026-05-19

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@hyperpolymath
hyperpolymath enabled auto-merge (squash) May 26, 2026 16:34
@github-actions

Copy link
Copy Markdown

🔍 Hypatia Security Scan

Findings: 43 issues detected

Severity Count
🔴 Critical 15
🟠 High 16
🟡 Medium 12

⚠️ Action Required: Critical security issues found!

View findings
[
  {
    "reason": "Action hyperpolymath/standards/.github/workflows/governance-reusable.yml@main needs attention",
    "type": "unpinned_action",
    "file": "governance.yml",
    "action": "pin_sha",
    "rule_module": "workflow_audit",
    "severity": "high"
  },
  {
    "reason": "Action actions/checkout@v6 needs attention",
    "type": "unpinned_action",
    "file": "publish-jsr.yml",
    "action": "pin_sha",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Action denoland/setup-deno@v2 needs attention",
    "type": "unpinned_action",
    "file": "publish-jsr.yml",
    "action": "pin_sha",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "TypeScript file detected -- banned language",
    "type": "banned_language_file",
    "file": "/home/runner/work/affinescript/affinescript/packages/affinescript-cli/mod.d.ts",
    "action": "flag",
    "rule_module": "cicd_rules",
    "severity": "critical"
  },
  {
    "reason": "TypeScript file detected -- banned language",
    "type": "banned_language_file",
    "file": "/home/runner/work/affinescript/affinescript/packages/affine-js/types.d.ts",
    "action": "flag",
    "rule_module": "cicd_rules",
    "severity": "critical"
  },
  {
    "reason": "TypeScript file detected -- banned language",
    "type": "banned_language_file",
    "file": "/home/runner/work/affinescript/affinescript/affinescript-deno-test/lib/runner.ts",
    "action": "flag",
    "rule_module": "cicd_rules",
    "severity": "critical"
  },
  {
    "reason": "TypeScript file detected -- banned language",
    "type": "banned_language_file",
    "file": "/home/runner/work/affinescript/affinescript/affinescript-deno-test/lib/discover.ts",
    "action": "flag",
    "rule_module": "cicd_rules",
    "severity": "critical"
  },
  {
    "reason": "TypeScript file detected -- banned language",
    "type": "banned_language_file",
    "file": "/home/runner/work/affinescript/affinescript/affinescript-deno-test/lib/compile.ts",
    "action": "flag",
    "rule_module": "cicd_rules",
    "severity": "critical"
  },
  {
    "reason": "TypeScript file detected -- banned language",
    "type": "banned_language_file",
    "file": "/home/runner/work/affinescript/affinescript/affinescript-deno-test/example/smoke_driver.ts",
    "action": "flag",
    "rule_module": "cicd_rules",
    "severity": "critical"
  },
  {
    "reason": "TypeScript file detected -- banned language",
    "type": "banned_language_file",
    "file": "/home/runner/work/affinescript/affinescript/affinescript-deno-test/mod.ts",
    "action": "flag",
    "rule_module": "cicd_rules",
    "severity": "critical"
  }
]

Powered by Hypatia Neurosymbolic CI/CD Intelligence

@hyperpolymath
hyperpolymath merged commit 839c272 into main May 27, 2026
20 of 21 checks passed
@hyperpolymath
hyperpolymath deleted the fix/codegen-record-alias-struct-layout branch May 27, 2026 12:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

1 participant