Glossary
kola's terms on one page, as the compiler's diagnostics and the two cards use them: SPEC-CARD.md for the language and STD-CARD.md for the standard library (kola help spec-card, kola help std-card).
Values and types
data: plain copyable values with nothing owning inside: integers,
bool,(),char,f64, references, and structs, enums and tuples built from them. Copied freely and compared by value with==, through references too (by pointee, never by address).owning value: a value that moves and is never copied: an owned
Vec[T](aVecby value), aMap, a value that holds a&mut, and anything that carries one of those in a field or payload. Passing it by value moves it, and reading the source afterwards is an error. Borrow it instead with&vor&mut v.resource: a linear value, declared with
resource struct: a file, a socket, a thread handle, a capability. It cannot be copied and cannot be silently lost. Many resources wrap an operating-system handle, such as a file descriptor (the small integer the OS uses to name an open file or socket), which must be closed exactly once.linearity: the rule that a resource is consumed exactly once on every execution path. Forgetting it is a compile error (
resource `t` is not consumed on this return path), and so is using it twice.consumption: the ways to finish a resource: pass it to a function that takes it by value (
self: T), return it, move it on, or destructure it.destructuring: taking a value apart with a pattern, as in
let Wal { entries: _ } = self;. For a resource this is how a consuming function ends the value. Every field must be named; there is no...move: handing a value to a new owner. Every position typed by value moves an owning value or a resource: a call argument, a
let, a struct-literal field, a variant payload such asSome(v), a channel message, a thread's context, an assignment into a field, a return. Data is copied instead.unit
(): the type with one value, also written(). A function without-> Treturns it.literal: a value written in the source:
42,0x2A,0o644,0b1010,1.5,"text",f"n={n}",b"bytes",r"raw",[1u8, 2u8],Point { x: 1, y: 2 }._between digits is a separator. There is no character literal.type suffix:
3u64is the number 3 of typeu64. An unsuffixed literal takes its width from context (an annotation, a parameter, the other operand, an index position, which isusize). A width nothing pins isu64, ori64if a negative value ever enters it.widen / narrow / wrap: the only numeric conversions, all explicit.
widen[u64](x)is lossless,narrow[u8](x)returnsOption[u8], andwrap[i16](x)reinterprets the low bits and never traps. There is noas.slice: a view into an array or a
Vec, typed&[u64]or&r [u8]. It has.len, indexingxs[i]and subslicesxs[a..b]. Nothing is copied.view rule: while a view into a place (
&v[i], a subslice, aforwalk overv) is still used, that place is not written, grown, shrunk or moved through any other name. The repair is to finish the reads first, copy the value out, or keep the index and read again after the change.str: a (pointer, length) view of UTF-8 text..lenis its length in bytes and.bytesis the same view as&[u8]. A plain"..."literal is static data and fits any region.interpolation: an
f"..."literal substitutes expressions into text:f"n={n} sum={a + b}". A plain"..."never interpolates. A boundf-literal allocates; its region is the destination's if the destination's type names one, otherwise the innermost openregion, and otherwise the literal is refused. Passed straight to a call-scoped&strparameter, it allocates nothing.generic: a parameter in square brackets. Uppercase names bind types and lowercase names bind regions:
fn first[T: data](xs: &[T]) -> Option[T]. An unboundedTis treated as linear;T: datamakes it copyable;T: moveadmits data and owning values but no resource. A[const N: usize]parameter binds a compile-time number, usable as an array length. There are no angle brackets.monomorphization: compiling a generic by generating one specialized copy per set of type arguments, much as if you had written
first_u64andfirst_u8by hand. Every call goes straight to a known function; there is no run-time lookup of which function to call, as there is with C++ virtual methods.fn reference: a top-level function name used as a value, as in
seq::sort(xs, less_u64). Its type includes the effect row:fn(u64) -> u64 !{}. It captures nothing, because there are no closures.module-scoped type: a
structorenumbelongs to its module, like a function. Inside the module you name it bare; elsewhere,use M::T;and thenT, orM::Tin a type position.
Memory
arena: a block of memory that hands out allocations in order, by moving a pointer forward past each one ("bumping" it), and is freed all at once. That makes allocation very cheap. Nothing in an arena is freed individually.
region: a lexical block
region r { ... }that owns an arena. Everything allocated in it is freed at the closing brace.region r from m { ... }backs the arena with the memory budgetm.alloc in: allocation into a region:
alloc in r mut Vec::new()gives a&r mut Vec[T]. Mutability is chosen where the value is allocated.heap: the built-in region that lives as long as the program. There is no garbage collector;
heapmemory is released when the process ends. A plain string literal is static data and can be typed&heap str. An ownedVec's storage is always onheap, so growing one isalloc(heap).region reference
&r T: a reference whose type names its region. It can be copied freely but cannot outlive the region, which is checked at compile time.call-scoped view
&T/&mut T: a reference that exists only as a parameter type. The callee may use it for the duration of the call but cannot store or return it. It is the default parameter form.region parameter: a lowercase name in square brackets, as in
fn body[r](b: &r [u8]) -> &r [u8]: the function works with whatever region the caller has. A call never writes the region; it is inferred.lend: a region-scoped shared view of a resource:
let v: &r Wal = lend wal in r;. The resource is frozen until the region closes. There is nolend mut.Pool[T]: a slab (a fixed array of equal-sized slots) for long-lived, graph-shaped data, where individual slots can be freed, which a region cannot do. Capacity is reserved atnewand charged to the budget in full, but pages are touched only when a slot is first used.inserttraps withTrapKind::Capacitywhen the pool is full;try_inserthands the element back instead.drain_nextpops an arbitrary occupied slot for teardown. APoolmay not cross a thread.generational handle
Gen[T]: the ticketinsertreturns. It answers two questions: is this slot still the one you were given (afterremove, the old handle yieldsNoneeven if the slot is reused), and is the handle from this pool at all (a handle used on another pool is a deterministic miss).owned
Vec:Vec::new()bound by value, with storage onheap. Its buffer moves between threads without copying. For memory returned at a brace, allocate theVecin a region instead.
Effects and capabilities
effect: what kind of thing a function may do. There are five:
alloc(r)(allocates into regionr),io(touches the outside world through a capability),hw(a privileged or ordering-sensitive machine operation),block(may block or sleep) andlog(writes to the process log). Effects say what kind; capabilities say to what.effect row:
!{...}at the end of a signature, after the return type:fn f(x: &T) -> u32 !{io}. Every public function states one; a private one may leave it to inference.pure function: a function with the row
!{}: provably no allocation, no I/O, no blocking.hw: the machine effect, for operations a kernel or driver performs on the hardware itself: masking interrupts, maintaining caches and the TLB (the CPU's cache of address translations), memory barriers (instructions that stop the CPU from reordering memory accesses across them), MMIO and atomics. It is forbidden in act fnand never reordered or removed. Plain reads and writes through aRamWindowstay onio.capability: a value that grants access to one part of the world. There is no ambient authority, so every effectful library operation takes one. Authority tokens such as
Clock,Rng,Fs,Dir,Dial,Stdoutmay be dropped.Memand linear handles such asFile,Conn,Childmust be consumed.Sys: the root set the runtime passes tomainand nothing else:sys.clock,sys.rng,sys.mem,sys.fs,sys.dial,sys.listen,sys.stdout,sys.stdin,sys.stderr,sys.args,sys.env,sys.tty,sys.ping,sys.proc,sys.netlink,sys.raw_ip,sys.mmio,sys.cpu,sys.dev,sys.windowandsys.inherited.maintakes it by value or takes nothing.ambient authority: power available from anywhere, such as a global
print, filesystem or clock. kola has none.attenuation: narrowing authority as it is passed down.
mainholds everything and passes a helper only&sys.clock. Some narrowing is typed:dir.ro()gives aDirRowith no write operations,w.atomic()leaves a window only its atomic operations, anddial.to_host(host, port)reaches one endpoint. A capability moves once, soclock.split(),rng.split()anddial.split()hand a worker its own.grant: authority beyond the working directory and the process itself (a directory, a binary, a device, a hardware window), bound by name by whoever runs the program.
kola run --fs-root db:ro=/absgrants it, andsys.fs.root(b"db")looks it up, returningNoneif nothing was granted. Each flag has an environment twin, such asKOLA_FS_ROOT_db. Grants come from the operator, never from a parent process.log: the one effect that needs no capability, because the sink is write-only: the program cannot read it back, so it cannot steer control flow. The sink and level are chosen once, by--logand--log-levelorKOLA_LOGandKOLA_LOG_LEVEL. The functions arestd::log::{error, warn, info, debug}.memory budget: a part of the
Memcapability carved off withsys.mem.split(n). It backs a region withregion r from m, and linearity makes you return it withsys.mem.absorb(m). Exceeding a budget traps withTrapKind::Budget.window: a granted span of memory or address space with a length and an opaque base. kola works with offsets, never pointers.
RamWindowis memory shared with hardware, such as a ring of buffer descriptors a network card reads.MmioWindowis device registers mapped into memory (MMIO, memory-mapped I/O: reading or writing such an address talks to the device instead of RAM).IoWindowis x86 port I/O, an older separate address space for devices. Every access carries a bounds contract that the prover can discharge like an array index.device model: under a hosted
runortestthere is no real device behind a window or device grant, so a model written in kola supplies the behaviour, bound with--sim-mmio,--sim-ioor--sim-dev. A grant without a model refuses the test at startup.Proc/Child:sys.proc.spawn(bin, argv, env, disp, slots)runs a binary the operator granted by name (--proc-bin ffmpeg=/abs).envis explicit, so nothing ambient crosses.disp: StdioisInherit,PipedorNull.Childis linear:waitorkillconsumes it.ExitStatusisCode(u8)orSignaled(Signal), and a signal is a name, never a number.
Errors and contracts
trap: a deterministic halt when an assumption is violated: overflow, out-of-bounds access, a false contract, an
unwrapofNone, an explicittrap("msg"). No unwinding and no continuing with garbage.fault domain: what a trap kills. By default the whole process (in a test, the test). A
domain d { ... } recover(t: Trap) { ... }block narrows it to the block: a trap in the body tearsddown and runsrecover. A domain is a region that also catches. A trap insiderecoveris fatal.Trap: the plain datarecoverreceives.t.kindis one ofBounds,Arith,Req,Ens,Inv,Assert,Unwrap,Explicit,BudgetorCapacity, andt.siteismodule:line, never a filesystem path.contract: a checkable condition on a signature. It is always enforced: proven at compile time, in which case the check disappears, or checked at run time with a trap. No build mode removes it.
req: a precondition, the caller's obligation:req i < xs.len.ens: a postcondition, the function's promise;retnames the result:ens ret <= 100.inv: an invariant of a resource struct, written as the last item of its body:resource struct Ring { head: usize, inv head < 8 }. Checked at construction and at function boundaries.assert: a checked claim inside a body, with the same discharge rule as contracts. Its expression must not change anything.Option/Result: expected outcomes as values.Option[T]is present or absent;Result[T, E]is success or an expected error.?: an early return. It takesvout ofOk(v), and onErrreturns the error from the current function. A resource live at the?is a linearity error.discarding a
Result: a compile error. Handle it withmatch,?or.unwrap(), or discard it on purpose withlet _ = ...;.unwrap: takes the value out of anOptionorResultand traps onNoneorErr. It moves its receiver.OS result convention: an operation that reaches the OS answers
Result[T, (E, OsErr)], whereEis the action family (FsErr,NetErr,IoErr,DevErr,ProcErr,NetlinkErr) andOsErris the OS's own identity, such asNoEnt. "Nothing yet" is never an error: atry_*operation answersOk(None).layout_assert: a module-level item,layout_assert[Point](8, 4);, that claims a type's C size and alignment. The C backend turns it into a_Static_assert; the interpreter treats it as a no-op. kola has nosize_of.
Data you must not trust, data you must not reveal
untrusted: a parameter marker for attacker-supplied input: wire, file, stdin or IPC bytes. Areq,ensorinvmay not depend on it, because a contract is a claim about the caller and these bytes have no caller. Check the value at run time and returnResultorOption.kola report tainted-reqsfinds candidates in existing code.Secret[T]: an opaque, linear box for data you must not reveal.Secret::wrap(x)boxes it,Secret::expose(&s)is the only read,Secret::wipe(s)consumes and scrubs it,Secret::eq(&a, &b)compares in constant time, andSecret::wipe_bytes(&mut buf)scrubs a buffer you do not own the box of. A runtime-length secret isSecret[Vec[u8]]. A reference cannot be boxed: scrubbing a pointer would leave the bytes behind it.Entropy[[u8; N]]: a box that records where the bytes came from: OS entropy, unpredictable to an adversary.Entropy::draw[[u8; N]](&mut rng)mints one andEntropy::expose(&e)reads it.Entropy::of(x), for test vectors, is refused bykola auditon any path that does not start in atest. It is not linear and not aSecret; a key can want both.ct fn: a constant-time function. Its running time and memory-access pattern may depend on the shape of its parameters (widths, lengths) but not on their values. This matters for cryptography: if a comparison of a password or key returns faster when the first byte is wrong, an attacker who can time it can recover the secret byte by byte. Inside one, every parameter is secret unless markedpub, and the checker rejects branching, indexing, division, trapping arithmetic and secret shift amounts on secret-derived values, as well as calls to non-ctfunctions. See Constant time.
Tools and the project
SPEC-CARD: the whole language on one card, and the source of truth. Diagnostics cite its sections, as in
error[card §8]. What is not on the card is not in the language. Its companion STD-CARD holds the standard library: the types, the capabilities' operations and SIMD.golden: the
golden/directory of normative example programs in the repository, from hello world to a sandbox and a VM-exit dispatcher. All of them compile and are tested.kola: the compiler, one binary with the standard library embedded. Its commands arecheck,run,test,build,ir,report,query,audit,pack,security,cc,lsp,mcpandhelp. See Under the hood.interpreter: the executor behind
kola runandkola test, and the reference every backend is compared against. It runs with a JIT;--no-jitgives the pure tree-walker.differential test:
kola testruns every test on the interpreter and on the C backend and compares the answers; a disagreement exits with code 3.--interpor--nativeruns one side alone.KIR: the verified intermediate representation every backend consumes, with each check's proof decision recorded in it.
kola irprints it. See IR-0.report checks: the list of every obligation in a file and whether it was proven at compile time or left as a run-time check. "0 runtime" is the bar for kernel-grade code. Siblings includereachable,leaks,regions,effects,secrets,tainted-reqsandstack-frames;kola help reportlists them.seeded run: a run in which all nondeterminism (randomness, time, I/O order, thread scheduling) derives from one number.
kola test --sim --seed Nreplays the same run bit for bit.simulator (
--sim): capabilities replaced by deterministic doubles: a virtual clock, a seeded random source, a simulated filesystem and network with fault injection, an empty environment.Prochas no double; a granted spawn really runs.kola.pack: the package manifest: name, version, source root, dependencies, and the capability budget[caps] allowedwith its per-name lists (fs_roots,proc_bins,devices,dial_hosts,netlink, the window lists and others).[caps.tests]and[caps.examples]widen it for tests and examples only.kola auditfails when code exceeds the budget. The budget limits what a pack may take from the root set; authority it receives as a parameter is listed separately on the audit'sreaches:line.confusion log:
docs/confusion-log.mdin the repository, the record of constructs that people or models consistently get wrong. A construct that confuses is treated as a defect in the construct or in the card.