The transfer channel is the ABI, not a stopgap
plan.org now says every Flan function carries the transfer channel, that uniformity is what keeps indirect calls and hot reload ABI-safe, and that a later optimisation cannot change the ABI. spec-conditions.md §6 still read the other way round - escape analysis deciding which functions are transfer-transparent, with the rest paying nothing - which describes a signature that depends on an analysis, and a cell cannot hold one of those. So the analysis is demoted to what it can still honestly do: a function that provably cannot transfer need not check the channel after a call and can pass the pointer straight through. It may not drop the parameter. NEXT.md said the same thing as a for-later note and now says it is settled.
This commit is contained in:
parent
943561e765
commit
5980b5b60f
12
NEXT.md
12
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
|
||||
|
||||
@ -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
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user