Skip to content
CryoCryo home
StdlibOverview

The Standard Library

std is written entirely in Cryo and ships with the compiler as a static library plus its sources. Nothing in it is privileged: the same type struct, type trait, and implement declarations available to your code build Array<T>, HashMap<K, V>, and the HTTP server. When a signature here looks like something you could have written, that is because it is.

The library is layered. core sits at the bottom and neither allocates nor performs I/O — it is the vocabulary the language itself is defined against. alloc introduces the heap, collections builds growable containers on top of it, and everything above that is domain-specific: files, sockets, threads, formatting, time.

collectionsArray, Str, String, HashMap, HashSet, Pair
allocLayout, Allocator, Box, Rc, Arc, Arena, Pool
corelanguage foundations — no heap, no I/O

How to read these pages

The tree mirrors the compiler repository's stdlib/ directory: one page per module (collections), and under it one page per source file (collections/array), so a page's URL is its import path. A module page opens with the module's own manifest — the public module lines from its _module.cryo — and lists its files; a file page opens each type and trait with its declaration as it appears in the source, minus method bodies:

type struct Pair<A, B> {
    first:  A;
    second: B;

    static new(first: A, second: B) -> Pair<A, B>;
}

Fields are listed because layout matters in a systems language; methods are listed as signatures. Private members and helpers the sources mark as internal are omitted. Where a type implements traits, a Trait implementations section lists each implement head, naming the module alongside when the impl lives somewhere other than the type's own — Display and Debug for the core types live in fmt, for instance, because core cannot import upward.

The declarations are not typed in by hand. A sync from the compiler repository extracts every signature in stdlib/ into an index the site builds from, so what a page shows is what the compiler ships — and a page whose declaration has disappeared fails the build rather than going quietly stale. The prose around each block is the part the signatures cannot say: what a method's contract is, which bounds are load-bearing, and why a design is the shape it is.

The prelude

A small set of names is imported into every source file automatically. The set is deliberately short — each entry competes for your attention — and most of it is there because the language desugars to it.

ModuleWhat it brings in
corepanic(message, loc) -> never, plus assert, unreachable, and todo
core::optionOption<T> and its methods
core::resultResult<T, E> and its methods
core::primitivesMethods on the built-in types (i32::max_value, char::is_digit, ...)
core::varargsVaArgs, the compiler-assigned type of a function's args... bucket
collections::arrayArray<T>, because [T] is a spelling of it
core::sliceSlice<T>, which backs for (x in arr) over a fixed-size array
core::opsRange and RangeInclusive, because a..b desugars to Range::new; the operator traits
core::iterIterator, the trait for-in drives its scrutinee through
core::drop, core::marker, core::cmp, core::cloneDrop, Copy, Send, Sync, Eq, Ord, Clone — the traits the compiler reasons about by identity, so an implement trait Drop for X head resolves without an import
alloc::boxBox<T>
alloc::rcRc<T>

The f-string runtime in fmt::interp is the one addition outside this list: the compiler injects import std::fmt::interp; into any module that contains an f"...", so the desugar resolves without the import appearing in every file.

Everything else is an explicit import. Most notably the print / println / eprint / eprintln family lives in fmt and is not in the prelude:

namespace app;

import std::fmt;

function main() -> i32 {
    println(f"hello, {name}");
    return 0;
}

Importing

Standard library paths are rooted at std, and you import the module that owns the item you want:

import std::collections::array;          // the module
import std::collections::{ str, string }; // two modules from one parent
import std::net::http::status as http_status;
import std::fmt::display::*;             // everything public in the module

Each module page below records the exact import path for the types it documents. Importing a parent aggregator (import std::collections;) brings in whatever that directory's _module.cryo marks public. See Modules and Imports for the full rules.

Module directory

public module prelude;
public module core;
public module alloc;
public module collections;
public module io;
public module fmt;
public module json;
public module encoding;
public module fs;
public module ffi;
public module sys;
public module env;
public module math;
public module time;
public module random;
public module net;
public module process;
public module thread;
public module sync;
public module future;
public module test;
ModuleWhat it covers
coreOption, Result, Slice, NonNull, Range, Ordering, and the trait vocabulary the language is defined against
allocLayout, the Allocator trait, Box, Rc, Arc, Arena, Pool
collectionsArray, Str, String, HashMap, HashSet, Pair
fmtDisplay, Debug, Formatter, the print family, f-string format specs, heap-free number writers
jsonRFC 8259 value model, parser, and serializer
encodingBase64 and SHA-1
ioRead / Write / Seek, the async traits, the standard streams, buffered adapters, Cursor, IoError
fsPath, PathBuf, File, directories, metadata
envArguments, environment variables, working directory, process exit
processCommand, Child, Stdio, ExitStatus, signals, the platform shell
timeDuration, Instant, SystemTime, DateTime, sleep
ffiThe C ABI boundary: libc and openssl
sysRaw syscalls, and the Win32 / NT surfaces
mathlibm wrappers, width-generic where it makes sense
randomRng (xoshiro256**), SecureRng, and distributions
syncAtomic, Mutex, RwLock, CondVar, Once, Barrier, mpsc channels
threadspawn, JoinHandle, Builder, scoped threads, thread-local storage
futureFuture, Poll, Context, Waker, the executor, reactor, blocking pool, and combinators
netIP addressing, DNS, async TCP, UDP, TLS, and the HTTP/1.1, HTTP/2, and WebSocket layers
testThe built-in unit-test framework

Conventions

The standard library follows a handful of rules consistently. User code is encouraged to mirror them, and knowing them up front means you can predict most signatures before reading them.

Result for expected failure, panic for broken invariants. A function returns Result<T, E> whenever failure is part of its contract — a file that might not exist, a parse that might not succeed. It panics only when the contract cannot be preserved at all, such as an out-of-bounds index on a method whose contract excludes it. Fallible constructors are usually spelled try_* next to a panicking sibling.

No NUL-terminated strings outside ffi. Every other module works in length-typed Str and String values. Translation to and from C strings happens at the boundary, in ffi.

Explicit resource management. Every owning type exposes drop(mut &this), and its documentation says who is responsible for calling it. In practice the compiler synthesises drops at scope exit — see Ownership, Copy, and Drop — and a manual .drop() remains available for early release.

Allocator-generic containers. Array<T, A>, HashMap<K, V, A>, String<A>, Box<T, A>, Rc<T, A>, and PathBuf<A> all take the allocator as a trailing type parameter defaulting to GlobalAlloc. The *_in constructors plug in an arena, a pool, or your own strategy without changing any other code.

Everything that waits is a future. Sockets, TLS, child processes, and timers expose no blocking calls; each operation that can wait is a Future driven by an Executor, and an operation owns what it works on — the handle and the buffer — handing both back on completion.

No magic numbers. Every numeric constant in the library is named. A bare literal in a signature is a bug report waiting to happen.

Reading the sources

Each page here documents the surface, but the library is short and readable, and its doc comments are the ground truth. The manifest at stdlib/lib.cryo lists every module, and each directory's _module.cryo describes what its files contain.