This post covers Kit v2026.7.8. The notes below come from the release tag history and the project changelog.
Kit 2026.7.8 brings a new language feature and a deep round of backend hardening. Type
declarations can now carry derive (...) clauses that generate Show,
Eq, and JSON trait implementations, all-primitive records flow through monomorphized
functions as native structs, trait Eq/Ord implementations now drive the
== and < operators on both backends, and builtins finally behave as
first-class values — partially applied, passed to higher-order functions, or bound to names. The
compiled actor scheduler also stops pinning every core and fixes three message-loss races.
Release Snapshot
- Release: v2026.7.8
- Date: July 8, 2026
- Changelog entries since v2026.7.6: 33
- Primary areas: language, traits, monomorphization, codegen, concurrency, caching
What Changed
The headline language feature is derive: a type declaration can now end with a
derive (Show, Eq, StringEncode JSON, StringDecode JSON JSONParseError) clause and the
compiler generates the trait implementations as ordinary Kit source, spliced into the module so both
backends, module interfaces, and IL caches see them exactly like hand-written code. Nested field
types compose through the traits, so a hand-written implementation for a field type is picked up by
a derived outer one. Trait dispatch got matching fixes: == and < now
route through trait Eq/Ord implementations instead of ignoring them,
qualified trait calls like User.decode resolve statically, and partitioned builds share
one trait registry instead of duplicating it per compilation unit. The checker also rejects applied
undefined constructors instead of fabricating phantom values.
Builtins are now genuinely first-class. Partially applying a builtin (inc = Int.add 1)
or passing one as a function value (List.any? String.is-blank? xs) previously produced
[E003] errors, [C001] build failures, or silently wrong output depending
on the backend; lowering now synthesizes eta-expansion wrappers so the existing partial-application
machinery handles them on both backends. Missing runtime wrappers for Int.clamp,
String.humanize, and String.is-blank? were filled in, and
List.filter and List.partition now run their predicates exactly once per
element on both backends.
Thanks to
Greg for reporting
issue #371
on List.filter/List.partition running predicates twice per element and
issue #372
on partially-applied builtins losing their first-class representation. Both are fixed in this
release.
Performance work centers on monomorphization: records whose fields are all primitives are unboxed
into native Zig structs inside monomorphized functions, bringing a 100M-iteration Vec3
benchmark to parity with handwritten Zig and cutting the ray tracer benchmark from 30ms to 13.3ms.
Mono candidates are now serialized in the IL cache archive, so cached release builds keep the fast
path instead of running up to 33x slower than --no-cache builds, and functions with
lazy-accepting parameters are correctly excluded from monomorphization.
Concurrency got a substantial hardening pass. The compiled actor scheduler parks idle workers on a
condvar instead of busy-spinning — an idle actor program now costs ~0% CPU instead of saturating
every core — and three message-loss races in the work deque, actor tick, and idle-transition paths
were fixed. On the interpreter side, Parallel.run-timeout no longer crashes when its
worker outlives the call (abandoned workers are registered and joined before teardown), and spawn
failures no longer join uninitialized thread handles. Compiled authority derivation now honors the
capability hierarchy, so RootAuth-carrying environments derive parallel and network
authority the same way the interpreter grants them.
Elsewhere in the toolchain: kit build --target wasm emits a monolithic module instead
of crashing, the IL cache archive pins its buffer alignment so unlucky path lengths no longer panic,
KIT_CACHE_VERIFY runs on the live incremental cache path, the selfhost stage2 build
links libc, and the five parallel instruction emitters were consolidated after a first attempt left
a dead stub and gutted live emitter arms — the restoration is covered by new regression tests.
The website package docs were regenerated for this release, and the playground WASM binary was
rebuilt so kit version reports 2026.7.8.
Release Highlights
- Add
derive (...)clauses on type declarations forShow,Eq, and JSON traits. - Dispatch
==and<through traitEq/Ordimplementations; statically resolve qualified trait calls; share one trait registry across partitions. - Unbox all-primitive records in monomorphized functions — ray tracer benchmark 30ms → 13.3ms;
Vec3loop at parity with Zig. - Make builtins first-class: partial application and function-value references work on both backends via eta-expansion wrappers.
- Run
List.filter/List.partitionpredicates exactly once per element on both backends. - Park idle actor scheduler workers (~0% idle CPU) and fix three message-loss races.
- Fix
Parallel.run-timeoutuse-after-return and teardown crashes in the interpreter. - Serialize mono candidates in the IL cache so cached release builds stay fast.
- Make
kit build --target wasmemit a monolithic module instead of crashing. - Regenerate package docs and rebuild the playground WASM binary for
2026.7.8.
Release Commits
The list below uses the v2026.7.6..v2026.7.8 changelog range, with each short SHA linked to the
corresponding GitLab commit in kit-lang.
- feat(codegen): unify five parallel instruction emitters to reduce maintenance hazard (e0391999)
- fix(codegen): remove duplicate emitInstrWithDecl functions (c062545a)
- perf: drive unused-decl suppression off emitter-tracked function scopes (8e6abb4b)
- fix(codegen): restore emitMainInstr assign/call arms gutted by dead unification stub (b3325fd4)
- fix: run filter/partition predicates exactly once per element on both backends (ffcfb43a)
- fix(il): reify partially-applied builtins via eta-expansion wrappers (c7066f8a)
- fix(selfhost): pass -lc to zig build-exe so stage2 links libc (6380fc8a)
- fix(il): serialize mono candidates in the IL cache archive (f1e055ad)
- fix(il): never monomorphize functions with lazy-accepting parameters (ee59e0c2)
- feat(il,codegen): unbox all-primitive records in monomorphized functions (cd1914c3)
- chore: slim repo-root kit.toml to its actually-used sections (2f3ee029)
- fix(runtime): honor capability hierarchy in compiled authority derivation (6c7cd230)
- fix(interpreter): use-after-return crash when Parallel.run-timeout detaches its worker (1387be65)
- fix(parallel): never join uninitialized thread handles on spawn failure (eca575f3)
- fix(interp): join abandoned run-timeout workers before interpreter teardown (4aa7de15)
- fix(cache): guarantee archive buffer alignment; no panic on unlucky path lengths (9269a2eb)
- fix: make --target wasm build a monolithic module instead of crashing (f40072e2)
- ci: make test:kit failures diagnosable (bd9123fa)
- fix(codegen): statically resolve qualified trait calls; share trait registry across partition objects (84080c7d)
- feat: derive (...) clauses on type declarations for Show, Eq, and JSON traits (6412af75)
- fix(checker): reject applied undefined constructors instead of fabricating phantom values (f24d056e)
- fix(traits): dispatch == and < through trait Eq/Ord impls on both backends (afb9333d)
- fix(codegen): handle float16 in runtime fragment switches over Value (967c019a)
- docs: fix stale actor/parallel examples in AGENTS.md (d1adc747)
- fix(codegen): define kit_int_clamp runtime fragment so Int.clamp compiles (5ddeca3b)
- fix(codegen): register String.is-blank? closure wrapper for value position (83589891)
- fix(codegen): add missing kit_string_humanize runtime wrapper (7fc4a5a3)
- fix(codegen): reify builtins referenced as first-class values through eta wrappers (c3208ed5)
- fix(cache): run KIT_CACHE_VERIFY on the live incremental cache path (843cc7e7)
- fix(actor): park idle scheduler workers; fix three message-loss races (ea9974dc)