Language-meta evaluation articles previously mixed informal notes with hub requirements.
Fibers and spawn
Platform spec feature
Fibers and spawn
Spec standingStandard
-
Sibling articles defer to this hub for MUST/SHOULD authority.
Context
Decision
This feature hub must own normative MUST/SHOULD contract text. Sibling articles must not redefine hub requirements and should link here for authority.
Consequences
Editors consolidate conflicting rules on the hub; articles carry detail and examples only.
Verification anchors
/platform-spec/language-meta/evaluation/fibers-and-spawn/;
site/websitetrudoc verify. -
Spawn expressions type-check to Fiber; Join yields Result with FiberError.
Context
Authors need a single cooperative concurrency entry keyword with an explicit handle for cancellation and join.
Decision
Rule Detail Keyword spawnintroduces a child fiberType Expression must type-check to a Fiber<T>handle for the entry return typeT(notTdirectly)Result spawnmust not return the entry value; useJoinforResult<T, FiberError>Contract The handle shape is the corelib_concurrencyFiber<T>type required by loweringConsequences
Parser, semantic analysis, and codegen share one spawn contract with the concurrency package.
Verification anchors
compiler/crates/beskid_analysis/;compiler/crates/beskid_codegen/spawn lowering; Concurrency package. -
Closure captures that share stack memory across fibers are rejected.
Context
Moving stack references into another fiber breaks the memory model and GC rooting assumptions.
Decision
Closure captures that would leak stack references across fibers must be rejected with diagnostic
StackReferenceEscapesSpawn(compile error).Consequences
Authors pass data through
Channel<T>or other approved sharing; runtime does not repair invalid captures.Verification anchors
compiler/crates/beskid_analysis/capture analysis; Memory and references. -
Language events are single-fiber; another fiber must use Channel.
Context
eventmulticast is defined for ownership within one fiber; UI/IO delivery across fibers needs a defined transport.Decision
Delivering notifications to another fiber must use
Channel<T>(or coordination primitives), not languageeventdelivery across fiber boundaries.Consequences
Events stays single-fiber; console and host specs reference channels for cross-fiber IO.
Verification anchors
-
Child Join on parent or ancestor Fiber handle is JoinWouldDeadlock.
Context
Waiting on an ancestor handle while the ancestor may wait on descendants creates predictable deadlocks.
Decision
Join on a parent or ancestor
Fiber<T>handle must be a compile error (JoinWouldDeadlock). Normative ordering for cancel + Join aligns with D-CORE-CONC-0014.Consequences
Structured concurrency stays acyclic on the join graph; runtime need not recover ancestor joins.
Verification anchors
compiler/crates/beskid_analysis/; D-CORE-CONC-0014.
- No directly attached article pages for this node.
0 revisions (git unavailable at build; counts may be empty)
No commits recorded for this path.
| Section id | Required | Found |
|---|---|---|
what-this-feature-specifies | yes | yes |
implementation-anchors | yes | yes |
Full tree: run pnpm verify:platform-spec-layout (writes src/generated/platform-spec-layout-report.json).
What this feature specifies
The spawn keyword starts cooperative fibers. Every spawn expression must type-check to Fiber<T> (Concurrency.Fiber in corelib_concurrency) where T is the entry return type. There is no async / await; cross-fiber payloads use Channel<T> only. Reserved async / await tokens are compile errors.
Implementation anchors
- Language surface and diagnostics in
compiler/crates/beskid_analysis/ - Lowering:
compiler/crates/beskid_codegen/→fiber_spawnand stack maps - Runtime: Fiber scheduler and stacks
- Corelib contract: Concurrency package
Contract statement
Beskid provides a spawn keyword for cooperative concurrency. Every spawn expression must type-check against the Fiber<T> contract defined in corelib_concurrency (Concurrency.Fiber), where T is the return type of the spawned callable.
There is no async / await surface in the language. Structured concurrency uses Join, Channel Send/Receive, WaitGroup, and Hub.
Syntax
`Fiber<T>` handle = spawn Callable(/* args */);Callable— function or closure satisfying the spawn contract (see semantic rules).- Lowering produces runtime
fiber_spawnwith environment captures rooted for GC. spawnis not an expression that returnsTdirectly; useJoinforResult<T, FiberError>.
Fiber handle
spawn returns Fiber<T> where T is the entry callable’s return type. The handle struct (corelib) must expose:
event OnCancelled();The entry callable is a normal function or closure — it does not declare OnCancelled. Cancellation is observed on the child fiber via the handle’s event, then Join / channel Result errors per decisions record.
Semantic rules
- Spawn target — callable return type
TdeterminesFiber<T>; entry signature must be compatible with spawn lowering. - Captures — closure captures must not leak stack references across fibers;
StackReferenceEscapesSpawndiagnostic. - Detach — explicit Detach waives shutdown Join; otherwise runtime joins non-detached children when
mainreturns. - Cancel — Cancel + OnCancelled on handle + Join / channel Cancelled (normative ordering in decisions record).
- Cross-fiber data — Channel only; Mutex / WaitGroup coordinate invariants, not payload transfer.
- Join cycle — child (or descendant) Join on parent / ancestor handle is
JoinWouldDeadlock(compile error). - Reserved keywords —
asyncandawaitare errors if parsed (not implemented).
Relationship to events
Language event members remain for single-fiber multicast within one fiber’s ownership. Delivering UI or IO notifications to another fiber must use Channel (see Events and console spec).
Diagnostics
| Code | When |
|---|---|
SpawnTargetNotFiberCompatible | Spawned callable not a valid spawn entry (signature / captures) |
JoinWouldDeadlock | Join would wait on an ancestor fiber handle |
StackReferenceEscapesSpawn | Capture would share stack memory across fibers |
AsyncKeywordReserved | async token in source |
AwaitKeywordReserved | await token in source |
Decisions
Section titled “Decisions”No open decisions. Closed choices are normative ADRs under adr/ (D-LMETA-FIBERS-0001 … D-LMETA-FIBERS-0005); use the reader ADRs tab for detail. Fiber/async keyword policy is also recorded in inception D-INC-0008 (not duplicated here).