iter form-a-scalar-param-mode-carveout: scalar-param mode carve-out (docs-honesty tidy)

Resolves the M1-fieldtest [friction] + [spec_gap]#1 shared root:
form_a.md stated an unconditional 'every (fn ...) param needs an
(own/borrow) mode' rule in 4 places, contradicting shipped checker
behaviour (scalars take and require bare (con Int); a mode on a
scalar trips body-pointing use-after-consume/consume-while-borrowed).
All 4 sites rewritten symmetric to the existing return-type carve-out;
DESIGN.md gains the bare-scalar export-param rule + a corpus-grounded
Form-A snippet; RED-first anti-regrowth pin via FORM_A_SPEC + norm().
Zero language/checker/codegen change. Plan 4c266a6.
This commit is contained in:
2026-05-18 15:51:34 +02:00
parent 4c266a64b4
commit 7d7f04e1a4
6 changed files with 169 additions and 11 deletions
+17
View File
@@ -2284,6 +2284,23 @@ context parameter that M2 threads through every exported call will
change this C signature; do not treat the M1 signature as frozen.
The value/record layout freeze is M3.
Export parameters are written **bare**: a scalar type carries no
`own`/`borrow` mode (modes apply only to heap-shaped types, which the
scalar-only rule above forbids at an export boundary anyway). The
canonical M1 export shape:
```
(fn step
(export "backtest_step")
(type
(fn-type
(params (con Int) (con Int))
(ret (con Int))))
(params state sample)
(body
(app + state (app * sample sample))))
```
## Data model
The on-disk JSON-AST is what the toolchain hashes, typechecks, and