Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Misc — reference

The small modules that don’t need a page of their own: std::io, std::promise, std::context, std::crypto, std::jwt, std::asset.

std::io

fun print(message: any)                     // console.log
fun panic(message: str)                     // abort with a message
fun assert(condition: bool, message: str)   // panic when false

panic is for unreachable states (expected failures are Result). A panic arm in a match diverges — the other arms decide the match’s type. assert is the vilan test failure mechanism.

std::task

external struct Task<T>;
impl Task<type T> {
	fun settle_all(tasks: List<Task<T>>): List<T>   // async; implicitly awaited
	fun race(tasks: List<Task<T>>): T               // async; first settled wins
}

fun nursery<T>(body: (|Nursery| T) context ambient_nursery): T

external struct Nursery;
impl Nursery {
	fun cancel(self)                 // abort the extent's signal
	fun is_cancelled(self): bool     // the compute-loop check
	fun signal(self): CancelSignal   // the raw host AbortSignal
}

resource struct OwnedNursery { nursery: Nursery }
impl OwnedNursery {
	fun new(): OwnedNursery                                       // a detached owner
	fun enter<T>(&self, body: (|| T) context ambient_nursery): T  // spawns inside → owned
	fun cancel(&self)                                             // early, idempotent
}
// `impl OwnedNursery with Drop` cancels the owned nursery at scope end.

fun ambient_signal(): Option<CancelSignal>   // the enclosing nursery's, if any

Tasks only arise from spawning (async expr); see the async tour. The handle is opaque and copying it refers to the same task. Every task absorbs its own failure: a later await receives it, and a task nobody awaits reports the error (with its spawn origin) instead of crashing the program. Keep the task instead of the results by spawning the settle_all itself: let pending = async Task::settle_all(tasks);.

nursery(body) joins every task spawned in the body’s dynamic extent — the body’s value passes through, the first-observed failure re-raises with its spawn origin, and everything else is absorbed. cancel() aborts the nursery’s signal; sleep and fetch carry the ambient signal automatically, so in-flight IO in the extent rejects promptly, and those rejections absorb as cancellation echoes. Task::race + cancel() is the race idiom: first settled wins, the losers’ IO stops. Spec: §7.7. ambient_signal() bridges host APIs std doesn’t wrap.

OwnedNursery is the owner for background work no function-scoped nursery can hold — a task whose lifetime is an object’s, not a call’s. It is a resource: it has a single owner, moves, and is destroyed deterministically. new() makes a detached owner; enter(body) runs body with the owner’s nursery ambient, so every task spawned inside registers with it — but, unlike nursery, enter does NOT join: it returns as soon as the body settles, leaving the tasks running. Dropping the owner (at scope end, or drop(owner)) cancels them, so in-flight bridged IO aborts. Because the owner’s nursery is never joined it runs detached: a child’s REAL failure reports to the console with its spawn origin — as a free-floating task would — instead of being absorbed for a join, and children do not cancel their siblings (ownership is lifetime, not fate-sharing). Cancellation echoes, from the owner’s cancel or drop, stay silent.

std::promise

external struct Promise<T>;
impl Promise<type T> {
	fun all(promises: List<Promise<T>>): List<T>   // async; implicitly awaited
}

The raw host promise, for direct host interop: an [extern(new, "Promise")] constructor or a promise-returning host API is typed Promise<T>, and await unwraps it exactly like a task. Code that only spawns never sees this type.

std::context

Ambient values with dynamic extent — the machinery under owner_scope and turn_scope:

impl Context<type T> {
	fun new(): Context<T>
	fun run<U>(self, value: T, body: || U): U   // establish for the body's extent
	fun get(self): T                            // read (compile error if possibly absent)
	fun get_safe(self): Option<T>               // read, absence as None
}
  • get is statically covered: the compiler proves every call path runs inside a run — an uncovered read is a compile error, not a runtime None.
  • Closures capture their contexts at creation; parameters declare context needs with the context clause (functions & closures).
  • Async-safe by construction: a continuation sees the value captured at creation, across awaits and interleaved extents.

Define module-level contexts for app-wide ambients (a session identity on the server is the canonical use).

std::crypto

fun random_bytes(length: i32): Bytes        // cryptographically secure
fun random_uuid(): str
fun equals_constant_time(a: Bytes, b: Bytes): bool   // timing-safe compare

WebCrypto-backed (async where the host is). For password hashing on the server, bind the host’s sync primitives as externs (the kolt pilot uses node’s pbkdf2Sync) — candidates for std promotion.

std::jwt

HS512 JSON Web Tokens; claims are any Wire type:

async fun sign_hs512<C: Wire>(secret: Bytes, claims: C): str
async fun verify_hs512<C: Wire>(secret: Bytes, token: str): Option<C>
fun decode_claims<C: Wire>(segment: str): Option<C>   // decode WITHOUT verifying

verify_hs512 checks the signature (constant-time) before yielding claims; decode_claims is for non-security introspection only.

std::asset

fun emit(kind: str, line: str)   // compile-time only: append to a build asset

Callable only from const evaluation — it’s how std::style writes the CSS file (emit("css", rule)). A browser build with emissions produces <entry>.css beside <entry>.js.