await is the block run here
For a handle h born by spawn [T] B, await $h is observationally !$B
run at the await: the same value or the same raise, and the bytes B wrote
to its stdout and its stderr written, in that order, to the awaiter’s current
stdout and stderr sinks. The await claims the handle’s result, which is
claimed once: a second await, or one after race or cancel claimed it,
fails as an ordinary error and replays nothing. The sinks are the awaiter’s:
inside a capture let x = await $h
binds the output as let x = { … } would, under 2> f the stderr goes to
f, and inside a worker the bytes land in that worker’s buffers. The ending
is the block’s: a value returned, an error raised as it stands, an exit or
a stop re-raised, a panic resumed. The type says the same thing — a handle
carries its block’s grade, await : Handle^ε α → F^ε α, so await of a
command’s block is a command.
The residue is stated, not hidden. The block’s effects happened earlier, concurrently, in the worker’s own shell, and the equation does not hold for:
- shell state:
cd, environment overrides and the status set insideBnever reach the awaiter; - the interleaving of the two streams: all of
B’s stdout is replayed, then all of its stderr; - a block that spawns: inline in a run its inner
spawnwould be a loose session worker, while as a worker it joins that child before it settles (a-worker-ends-with-its-children), so the awaiter sees the child’s bytes and failure too; - a cancelled or timed-out block, which ends
worker was cancelledorworker timed out, an ending no inline run has; exit, which ends the run that awaits, possibly a later one than the run that spawned it.
Two observations return data instead, and neither claims. poll returns
one handle’s bytes and state; first-settled returns the index of the first
of several handles to settle. Neither writes nor claims, so the handle either
names is left to the one await that replays it; both treat a claimed handle
as await does. Do not add an eliminator that returns a record, or an await
that does: the eliminators are this equation, and its data projections these
two observations.
The owner’s join is this same await: a gather — a gather { … } or a
worker’s body — claims each child no one has claimed at its exit and replays
it here (a-worker-ends-with-its-children).
See await-is-the-block-run-here
(I1), gather (I2) and docs/SPEC.md §11.2.