Open and answer this issue on GitHub.
blocked · opened 2026-10-30 · updated 2026-10-30 · 0 comments
Part of #983. Records: ADR-async-4 D2-D5, D7, D10-D14; ADR-async-2 D1, D3, D5, D8, D9; ADR-async-3 D2, D7; ADR-async-1 D5, D7-D9, D11; ADR-346 D3 (changed by async-4 D14). Spec: Part I 8.1.2, 8.2; Part II 12.6; Part III NK2104, NK2107, NK2109, NK2110-NK2112, NK2115, NK2118-NK2122, NK1132, NK2202, NK2203, NK2209. Needs #984 (parser).
let x = async e before the first statement naming any of its names anywhere nested (except a mention inside another task: that task waits); an argument before its call; an operand before its operation; an unnamed binding or statement form at its group’s end.async { } in the same function, else the innermost block. NK2110 for a task with nothing beside it (an argument with no sibling computed beside it, a binding named in the next statement, a statement ending its group; help removes the word); NK2111 for an async { } with no task; NK2120 for async in a loop body.NK2105); async(detached) takes everything (NK2101, the existing spawn rules).check_walks.nika, touch.nika): NK2104 between a bound task and each window statement, between the tasks of one call’s arguments / one operation’s operands and what is computed beside them, and a par_iter lambda of map/filter/for_each against itself (the stdout case: xs.par_iter().for_each fn(x) { println(…) } is refused); limit: 1 exempts; C.4. NK2107 as before.par_iter lambdas: NK2209 no longer asked of map/filter/for_each lambdas; still asked, finally, of fold, par_pieces, par_fold (async-2 D9). The help of NK2209 on a fold lambda names the chain map (pausing) followed by fold, e.g. xs.par_iter().map fn(u) { http::get(u) }.fold(…). Record per site pieces / one task per element in the ledger; NK2119 (warning) where the committed ledger had pieces and the lambda can now pause, naming the call (the NK2211 mechanism).async(handle) is a task::ChildHandle[T]; one that leaves its group is NK2122; an unjoined one is waited at the group’s end (not NK2109). async(deferred) not started or cancelled on some path, or started twice: NK2121 (the path rule NK2109 uses). async(detached) handles keep NK2109.join(within:) and NK2109 (async-4 D14, Part I 8.2): a join(within: d) without on_timeout: task::OnTimeout::Cancel takes a TaskHandle only on its success path (and on a failure of the task’s body). On the path where it throws task::TimedOut the handle is still live and must be taken on every path out of the handler: in a match error arm for task::TimedOut, in an else or binding arm that can match it, in the whole handler where it does not match on the error; otherwise NK2109. join(within: d, on_timeout: task::OnTimeout::Cancel) takes it on both paths. A live ChildHandle after a timed-out join is waited at its group’s end, not NK2109.NK2104); a task moving a pending binding hands it over at its start (NK2105 later); diamonds.async e has e’s type; the callee sees T. async fn { … } the lambda’s result type. Handles their types.NK1132; return inside async fn { … } ends the task.limit: on a one-task form NK2112; types of limit, within, admission; on_timeout: task::OnTimeout on join (Keep by default, or Cancel); limit:/within:/admission: on par_iter, limit: on fold/par_fold (workers: refused as an unknown option).async form is not sync (NK2202); an async form in an open door NK2203.NK2118: a mention after a catch where the failure arrived took it, without a fallback.tests/compiler/tests/async_*.nika with .stderr), among them: two tasks printing refused; a par_iter lambda printing refused; limit: 1 accepted; f(async g()) alone refused; async in a loop refused; a child handle returned refused; a deferred handle never started refused; chained read/read accepted; NK2119 after a ledger change; a join(within:) whose task::TimedOut handler drops the handle refused (NK2109), the same with on_timeout: task::OnTimeout::Cancel accepted; a pausing fold step refused with the map-then-fold help.The names are final (async-4 D13).
Generated by Claude Code