You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
## Summary
T0 operational-soundness fence (sibling of the just-closed#554).
`gen_function` previously fell through to synchronous `gen_expr`
whenever the ADR-013 async CPS transform did not fire — **even for an
`Async` fn whose async-call result is consumed by a continuation**. That
silently ran the continuation against an unsettled `Thenable` handle: a
wrong runtime value, no diagnostic.
## Fix
A precise loud-fail guard in `lib/codegen.ml::gen_function`: fail with
`UnsupportedFeature` when an `Async` fn performs an async call
**consumed by a continuation** that cannot be CPS-lowered
(`thenableThen` not importable / unrecognised shape / effect side-table
miss), while still lowering the **sound** shapes:
- the `let r = <async-call>; <cont>` base case (transformed as before),
- the bare tail-return-`Thenable` pass-through (#205 convergence
protocol — the host awaits the handle),
- an `Async` fn that performs no async call at all.
This mirrors the #555/#566 "fail loud, never silent" fence already in
the same file. The narrow guard was deliberate: the broader
`fn_is_async`-only guard would have wrongly rejected the valid
`tests/codegen/http_thenable_skeleton.affine` pass-through (verified —
all 7 existing async fixtures still compile).
## Tests
New `E2E Async Fence (#556)` group:
- `async_sync_fallback.affine` → loud `UnsupportedFeature` (negative)
- `async_passthrough_thenable.affine` → still compiles (no
over-rejection)
- `async_no_boundary.affine` → still compiles (no over-rejection)
Full suite **454/454 green**.
Closes#556
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
0 commit comments