diff --git a/NEXT.md b/NEXT.md index 3de934a..b20e314 100644 --- a/NEXT.md +++ b/NEXT.md @@ -955,11 +955,13 @@ check and return early, which reuses the existing `return` path and with it §5's defers. `Emit.signature` was already the one place a signature is spelled, which is what made this a three-line change rather than a hunt. -**Every function is transfer-transparent**, release included. §6's escape -analysis is an optimisation, and in a dev build a cell can hold anything, so -the honest answer to "what can this call?" is "anything" — the same bargain as -the indirect call. Uniform also means redefinition acquires no new refusal -class. +**Every function is transfer-transparent**, release included — and that is the +ABI, not a stopgap. A cell holds a bare pointer, so the honest answer to "what +can this call?" is "anything"; the same bargain as the indirect call. §6 and +plan.org both now say the later optimisation may stop a function *checking* the +channel, or pass the pointer straight through, but may not drop the parameter — +a signature that depended on an analysis could not be reloaded into. Uniform +also means redefinition acquires no new refusal class. **The transfer target is the restart frame's own address, not a clause id.** This is a correction to what the previous note settled. A static id has to be diff --git a/spec-conditions.md b/spec-conditions.md index d0bcc3a..18c3d9b 100644 --- a/spec-conditions.md +++ b/spec-conditions.md @@ -123,9 +123,15 @@ but it is not re-entrant: §5 runs defers *during* a transfer, so a defer that signals and invokes a restart would start a second transfer over the first. A per-frame slot nests correctly with no threads involved. -- The compiler marks a function transfer-transparent if it can call, directly or - indirectly, anything that may invoke a restart. Escape analysis narrows this - set; functions outside it pay nothing. +- **Every function carries the channel, and that is the ABI.** Uniformity is + what keeps an indirect call and a hot-reload cell safe: a cell holds a bare + pointer, so the honest answer to "what can this call?" is "anything", and a + signature that depended on the answer could not be reloaded into. An earlier + draft had escape analysis decide which functions are transfer-transparent; + that is now an *optimisation over what a function does with the channel* — + a function that provably cannot transfer need not check it after a call, and + can pass the pointer straight through. It may not drop the parameter. See + plan.org, Hot reload. - **Foreign frames cannot be crossed.** A restart transfer whose path passes through a C frame (a raylib callback, an `extern` function calling back into Flan) is a runtime error, not undefined behaviour. Handlers installed across an