v2026.3.31 — Law 10, Match Overhaul, Dependency Fixes
v2026.3.31 — Law 10: Struct Initialization Completeness
Section titled “v2026.3.31 — Law 10: Struct Initialization Completeness”Released: March 31, 2026
A session that started with a confused AI agent banging its head on match syntax ended with a new language axiom. Three features landed, each born from a real bug.
What Changed
Section titled “What Changed”Law 10: ..defaults Struct Initialization Completeness
Section titled “Law 10: ..defaults Struct Initialization Completeness”Zig silently accepts missing fields when defaults exist. Rust forbids defaults entirely. Janus splits the difference: defaults exist, but omission requires explicit opt-in.
struct Config { host: str = "localhost", port: u16 = 8080, tls: bool = false,}
// All fields listed — workslet c1 = Config { host: "prod", port: 443, tls: true }
// Explicit leniency — accept defaults for unlisted fieldslet c2 = Config { host: "prod", ..defaults }
// COMPILE ERROR — missing 'tls', no ..defaultslet c3 = Config { host: "prod", port: 443 }When a field is added to a struct:
- Callsites with
..defaultscompile fine (they opted in) - Callsites listing all fields get a compile error (must add the new field)
- The right split emerges automatically
Grammar: ..defaults uses the existing .. range token followed by the defaults identifier. Parser, lowering, and LLVM emission all updated.
else as Match Fallback
Section titled “else as Match Fallback”_ in match is dead. else is the only wildcard. One symbol, one meaning:
| Symbol | Purpose | Context |
|---|---|---|
else | Match fallback | match x { else => ... } |
_ | Discard binding | let _ = expr, catch |_|, tuple destructuring |
match status { .Ok => handle_success(), .Retry => handle_retry(), else => handle_failure(),}.Variant Patterns in Match
Section titled “.Variant Patterns in Match”Type-inferred variant patterns are now working. The compiler knows the enum type from the match subject — repeating it on every arm is noise:
enum Color { Red, Green, Blue }
func describe(c: Color) do match c { .Red => println("warm"), .Green => println("natural"), .Blue => println("cool"), }endDependency Cache Fixes
Section titled “Dependency Cache Fixes”CachedImport.exported_error_variantswas missing from initialization in 2 sites — silently relying on struct defaults (ironic, given Law 10)- Diamond import replay debug output now includes error variant counts
- Removed unsafe struct default on
CachedImportfield — forces explicit initialization
LLVM Codegen Fixes
Section titled “LLVM Codegen Fixes”emitUnionTagCheck: Fixed i1-to-i64 zero-extension for tag comparison resultsemitBinaryOp: Added type coercion when operand widths differ
Specs Updated
Section titled “Specs Updated”- SPEC-017 (Grammar): Law 10 added,
wildcard_patternnow'else'only, variant patterns documented - SPEC-018 (:core Profile): Match examples use
=>(not->),else(not_),.Variantpatterns added - LANGUAGE-REFERENCE: All match and struct init sections updated
Files Changed
Section titled “Files Changed”| Area | Files | Lines |
|---|---|---|
| Parser | janus_parser.zig | +32 (..defaults + else wildcard) |
| AST | core.zig | +3 (default_spread node kind) |
| Lowering | lower.zig | +195 (Law 10 enforcement, variant patterns, dep cache) |
| LLVM | llvm_emitter.zig | +20 (tag check zext, binop coercion) |
| Tests | Various | All match/struct tests pass |
Migration
Section titled “Migration”- Replace
_ =>withelse =>in all match expressions - Struct initializers that omit fields now require
..defaults - Enum match patterns can use
.Variantinstead ofEnumType.Variant