v1.0.0
LatestMajorThe first stable release. The compiler is self-hosted, the standard library is written entirely in Cryo, and the public surface is frozen under semver.
Compiler
- Self-hosted compiler with an LLVM 20 backend. Every release is built
by the previous release;
make selfhost-checkruns a 3-round (6-stage) byte-identical IR check that gates every push tomain. - Type system: static, monomorphic generics with
wherebounds, no implicit conversions. Local type inference onconst/mutbindings: a binding adopts its initializer's concrete type, so an explicit: Tis required only when there is no initializer to infer from (or to widen the declared type).typeof(expr)in type position. - Traits: trait declarations with default methods; impls on primitives,
structs, classes, and enums; coherence checks (a trait may be implemented
at most once per type) enforced uniformly within a file and across
modules, keyed on the import-resolved impl head so generic traits
(
From<i8>vsFrom<i16>), generic targets, andwhere-bounds are all distinguished. - Associated types. A trait may declare an associated type
(
type Item;) and refer to it by projection (This::Iteminside the trait,I::Itemoff a generic parameter). Each impl binds it positionally (implement trait Iterator<i32> for X- sugar forIterator<Item = i32>, available when the trait has no generic params of its own) or with the explicit body form (type Item = i32;). Two diagnostics enforce the binding rules:E0309(a declared associated type left unbound by an impl) andE0310(an associated type bound positionally on a trait that also has generic params - use the explicit body formtype Out = ...;instead). Declaration-site bounds on an associated type (type Item: Copy;) are enforced against each impl's concrete binding (E0306). Opaqueimplement Iterator<T>bindings now cross-check<T>against the iterator's actualItem(E0200on a category-level mismatch). Seedocs/cryo.mdsection 11.5. - Classes: single-inheritance with virtual dispatch, destructors,
protected/privatevisibility,overrideandvirtualmodifiers. - Enums: algebraic enums with explicit discriminants and discriminant
base type (
type enum X : u8 { ... }), exhaustive match enforcement on enum subjects. - Pattern matching: literal, identifier-binding, wildcard,
enum-destructure (including nested sub-patterns such as
Some(Some(n))andBranch(Leaf(x), r), with discrimination on literal payloads likeSome(5)), range patterns (a..band the explicita..=b; both are inclusive in pattern position), or-patterns (a | b | c), and guard clauses (pattern if (cond) => ..., checked after the pattern matches with a false guard falling through to the next arm). Exhaustiveness accounts for nested coverage (Wrap(A)+Wrap(B(n))coversWrap). - Ownership:
CopyandDroptraits with automatic recursive drop glue through struct fields, enum payloads, and container elements.- Fatal use-after-move (E0452), partial-move out of owning aggregate (E0453), and loop-carried move detection.
![sink]attribute for methods that consume the receiver.
- Layout directives:
![repr(...)]and![align(N)]honored per generic instantiation. - ABI: SysV-amd64 lowering with eightbyte classification, DirectPair,
sret,byval, and<2 x float>packing for both extern-C and Cryo-internal calls. - FFI:
extern "C"functions, variadic functions viaVaArgs::new(...), the![link]directive for extern symbols. - Operators:
?error propagation,|>pipeline,??null-coalescing,T?optional-type sugar (desugars toOption<T>),a..b/a..=brange expressions (desugar toRange::new/RangeInclusive::new; valid in any expression position, looser than arithmetic). - f-strings (
f"...{expr}...{expr:?}..."): string interpolation. The parser desugars each f-string into a chain ofstd::fmt::interpbuilder calls that produce an ownedString;{expr}formats the value throughDisplayand{expr:?}throughDebug(so it works for any type that implements them, includingOption/Result/Array). Embedded expressions are full expressions (f"{a + b}");{{/}}are literal braces.std::fmt::interpis auto-imported into any module that uses an f-string. The printf-styleprint/println(C%d/%sspecifiers, variadic, not type-checked) remain available for raw formatted output. for (x in iter)iteration: the parser desugars toloop { match (iter.next()) { Some(x) => { ... } None => break; } }, evaluating the scrutinee exactly once. The scrutinee may be anyIterator(stdlibRange<T>/RangeInclusive<T>or anyimplement trait Iterator<T>), a range literal (for (i in 0..n)), an iterable exposingiter()(Array<T>,Slice<T>), or a fixed-size arrayT[N](viewed as aSlice<T>).- Lambdas and closures:
(params) -> Ret { body }function literals. Non-capturing lambdas compile to anonymous function pointers; capturing lambdas overCopybindings (i32/u64/bool/char/references and any![derive(Copy)]type) compile to a synthesised anonymous closure struct with a__call__method. Both forms call directly with zero overhead. Closures bound to a(Args) -> Ret-typed parameter are delivered via per-call-site receiver specialisation, so the body dispatches through__call__without an indirect call; that specialisation is wired for non-generic free functions only, so a capturing closure passed to a generic function, a method, or a scope-resolution call is E0458 (non-capturing lambdas are function pointers and bind anywhere). Generic type-parameter inference from function-typed arguments (opt.map(lambda)infersU). - Modules:
_module.cryoaggregators,public/private/protectedvisibility, import cycle detection.
Build system
- New build-directory layout. The final artifact is hoisted to the
root of the build directory -
build/<name>for an executable,build/lib<name>.afor a library - so it runs asbuild/<name>regardless of profile. All intermediates live under a visible, per-profile cache tree (build/target/<profile>/) grouped by package origin: the standard library (std/), the local project (local/), and one subtree per third-party dependency (<depname>/), each holding its owndeps/*.oandir/*.ll. The combined IR dump isbuild/<name>.ll. (Breaking for tooling that hardcodedbuild/bin/,build/obj/, orbuild/.cryo/.) - Build manifest. A successful build writes a per-profile
build/target/<profile>/build-manifest.json(schema v2) recording the profile, target type/triple, optimization level, debug-info and emit-llvm flags, the linked stdlib archive, the[link]lists, every source module (namespace + path + origin/kind + object + size), and the input fingerprint. - Build profiles.
release(O2, no debug info; the default) anddebug(O0 + DWARF), selectable with--release/--dev/--profile=NAME, or[profile] default = "..."in cryoconfig. Each profile keeps its ownbuild/target/<profile>/cache. An explicit[compiler] optimizeor--opt-level=Nstill overrides the profile's level;-gforces debug info. - Incremental builds.
cryo buildnow skips the entire compile+link when no input changed (sources, resolved knobs, the compiler binary, or the linked stdlib) and the artifact still exists, printing<name> is up to date. The fingerprint is content-based and keyed per target.--no-incrementalforces a full rebuild. (Whole-build granularity is sound under Cryo's whole-program monomorphization; per-module reuse is future work, and the manifest already carries per-module hashes for it.)
Standard library
alloc:Allocatortrait,GlobalAlloc,Arena,Pool,Box<T>,Rc<T>,Arc<T>(all allocator-generic).collections:Array<T>,String,HashMap<K,V>,HashSet<T>,Pair<A,B>,Slice<T>,Str.core:Copy/Drop/Clone/Eq/Ord/Hash/Default/From/Into/TryFrom/TryInto/Display/Debug/FmtWrite/Iteratortraits;Option<T>,Result<T,E>, and the catch-allErrorstruct (there is no unifyingErrortrait — each module defines its own precise error type).core::iter:Iteratorwith an associatedtype Item(one requirednext() -> Option<This::Item>); the legacy generic-param formIterator<T>remains accepted as positional sugar forIterator<Item = T>in impls,where I: Iterator<T>bounds, andimplement Iterator<T>opaque returns. Default consumerscount/fold/for_each/any/all/findand lazy combinator adapters.take(n)/.map(f)/.filter(pred)/.chain(other)/.enumerate()/.zip(other)(returningTakeIter/MapIter/FilterIter/ChainIter/EnumerateIter/ZipIter);f/predmust be non-capturing, since the adapters are methods and a capturing closure may only be passed to a non-generic free function (E0458 - seedocs/cryo.mdsection 2.5 for the full boundary)..enumerate()yieldsPair<u64, Item>,.zip(other)yieldsPair<Item, B>and stops at the shorter side (Pairis the element type so the adapters stay monomorphization-friendly). Combinators chain freely (r.take(n).map(f).filter(p),r.chain(b).map(f),a.zip(b).count(), longer mixed chains) and feed.count()/.fold(..)/for (x in ..). The adapters resolve on any concreteIteratorreceiver, including a user struct thatimplementsIterator(mut c: Counter = ...; c.take(3).map(f)), not just stdlib iterators; bind an adapter to a concrete-typed local (mut z: ZipIter<.., ..> = a.zip(b)) or chain on the expression directly when you need a named local.collections::array::from_iter(it)collects into anArray<T>(a free function, fixed by the expectedArray<T>at the call site).io:Read/Writetraits with defaultread_all/read_byte/read_line/read_to_end/write_all;Stdin/Stdout/Stderr/BufReader<R>/BufWriter<W>/LineWriter<W>.fs: files (read/write/read_to_string/open/create/seek/copy) and whole-path operations (remove_file,rename,create_dir/create_dir_all,remove_dir/remove_dir_all,read_dir,canonicalize) overPath/PathBuf;metadata/symlink_metadata/exists/is_file/is_dirbacked bystat/lstat/access.net:TcpStream,TcpListener,UdpSocket,IpAddr/IpV4Addr/IpV6Addr,SocketAddr;dnsname resolution;tls(OpenSSL) withhttpson top;ws(RFC 6455) over anyRead + Writetransport. HTTP/1.1 server with keep-alive and read timeouts, HTTP client, router with route registration. HTTP/2 (net::http2): HPACK (RFC 7541), framing (RFC 7540), h2c client + server over any stream, generic over the transport.json: parser and serializer forJsonValue/JsonObject/JsonNumber; round-trip clean.process:Command/Child/ExitStatusviafork + execve;spawn/status/output/wait/try_wait/kill/send_signal.env:args(),var,set_var,remove_var,process_exit.sync: a genericAtomic<T>(T=u8/u32/u64/i32/i64/boolean, dispatched at compile time viastatic match),MemoryOrder,fence,compiler_fence,Mutex<T>,RwLock<T>,CondVar,Once,Barrier.Send/Syncauto-derive with call-site enforcement.thread:ThreadLocal<T>viapthread_key; OS threads viaspawn/try_spawn/JoinHandle<T>(returns the body's value onjoin),spawn_with_attr, scoped threads (thread::Scope),current/yield_now/sleep/sleep_ms. Channels insync::mpsc(channel,Sender,Receiver).Builderfor configured spawns (stack_size,name;spawn/try_spawn).math:square_root,cube_root,power,sine/cosine/tangent,natural_log/log_base2/log_base10/exponential,absolute(f64) /absolute_f32,abs_i32/abs_i64,is_nan/is_infinite/is_finite,hypot.time:Duration(normalized seconds + sub-second nanos; built and read in seconds/millis/micros/nanos;add/saturating_sub,Eq/Ord),Instant(monotonic clock -now/elapsed/duration_since),SystemTime(wall clock -now/duration_since_epochfor a Unix timestamp), andsleep(Duration). Differences saturate at zero.random:Rng, a fast non-cryptographic xoshiro256** generator seeded deterministically (from_seed) or from the OS (from_os):next_u64/next_u32/next_bool/next_f64, unbiasedbelow(bound)/range_u64(lo, hi), andfill_bytes.secure_bytes(buf, len)pulls cryptographically secure bytes from the kernel CSPRNG (getrandom).fmt:Display/Debug/FmtWritetraits,Formatter<W>,print/println/eprint/eprintln,format_to_string,format_debug_to_string, floating-point formatting.test: thecryo testframework -![test],![ignore],![should_panic],expect_*assertion helpers.ffi:CStr/CString/NulError;libcbindings (~2k LoC); syscall layer (~2k LoC).
Tooling
cryoCLI subcommands:build,run,test,check,init,fetch,update,raw,demangle,version,help.cryoconfigpackage format with[project],[compiler],[dependencies], optional[[bin]]and[lib]sections. Git-backed dependencies (git = "..."withversion/tag/branch/rev),cryoconfig.locklockfile written bycryo fetch, content-addressed cache under$CRYO_HOME/$XDG_CACHE_HOME/$HOME/.cache.- Language Server (
bin/cryolsp): hover, go-to-definition, completion (member + scope-resolution with trigger characters.and:), semantic tokens, code actions, code lenses, push diagnostics. - CryoAnalyzer VS Code extension: custom
cryo-diagnostic:virtual document scheme with themed rendering, code-lens/code-action wiring, LSP server auto-discovery. - CI:
make cryo+ smoke-test +make teston every PR and push;make selfhost-check(stage-3 == stage-4 byte-identity) on every PR and push as well.
Diagnostics
- Over 200 defined error codes (in the E0000-E0999 range) with source-span underlines, fix suggestions, and machine-applicable quickfixes where applicable.
- ANSI color rendering respecting
NO_COLOR/FORCE_COLOR/CLICOLOR_FORCEwithisatty(2)fallback. - Quickfix system covering literal coercions (E0218/E0200), parser punctuator misses (E0100), undefined-type "did you mean" suggestions (E0203), and use-after-move move-site anchors (E0452).
Examples
Fourteen worked examples under examples/, covering hello-world,
fizzbuzz, recursion, structs and methods, Array<T> ownership, file
I/O and HashMap, traits with where bounds, 2D simulation,
std::json parsing, recursive-descent parsing, an HTTP server,
stdin-driven interactive I/O, capturing closures, and OS threads with
thread::spawn / JoinHandle / mpsc channels.
Target triples
Verified end-to-end - compile, link, run, and a self-host byte-identity gate
(make selfhost-check) - on x86_64:
x86_64-*-linux-gnu- native host builds; the canonical dev/CI host.x86_64-pc-windows-gnu- native Windows host builds and Linux->Windows cross-compilation via the mingw-w64 toolchain: Win64 ABI, COFF objects,.exelinking, and a native 6-stage self-host fixed point.
The host C toolchain (header preprocessor + linker) is auto-detected
(clang-20 -> clang -> gcc -> cc) and the standard library is auto-located
relative to the cryo binary, so a stock toolchain needs neither CRYO_CC
nor CRYO_STDLIB.
Known limitations (deferred to post-1.0)
These are not bugs against 1.0 - the language deliberately ships
without them and the grammar reserves the relevant syntax. See
docs/cryo.md section 21 for the
authoritative list.
- Async / await / coroutines.
- Macros / user-defined
![attr]directives. - macOS / Darwin targets (no Mach-O backend or toolchain wiring yet). See Target triples above for the supported set.