Skip to content

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.

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 — works
let c1 = Config { host: "prod", port: 443, tls: true }
// Explicit leniency — accept defaults for unlisted fields
let c2 = Config { host: "prod", ..defaults }
// COMPILE ERROR — missing 'tls', no ..defaults
let c3 = Config { host: "prod", port: 443 }

When a field is added to a struct:

  • Callsites with ..defaults compile 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.

_ in match is dead. else is the only wildcard. One symbol, one meaning:

SymbolPurposeContext
elseMatch fallbackmatch x { else => ... }
_Discard bindinglet _ = expr, catch |_|, tuple destructuring
match status {
.Ok => handle_success(),
.Retry => handle_retry(),
else => handle_failure(),
}

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"),
}
end
  • CachedImport.exported_error_variants was 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 CachedImport field — forces explicit initialization
  • emitUnionTagCheck: Fixed i1-to-i64 zero-extension for tag comparison results
  • emitBinaryOp: Added type coercion when operand widths differ
  • SPEC-017 (Grammar): Law 10 added, wildcard_pattern now 'else' only, variant patterns documented
  • SPEC-018 (:core Profile): Match examples use => (not ->), else (not _), .Variant patterns added
  • LANGUAGE-REFERENCE: All match and struct init sections updated
AreaFilesLines
Parserjanus_parser.zig+32 (..defaults + else wildcard)
ASTcore.zig+3 (default_spread node kind)
Loweringlower.zig+195 (Law 10 enforcement, variant patterns, dep cache)
LLVMllvm_emitter.zig+20 (tag check zext, binop coercion)
TestsVariousAll match/struct tests pass
  • Replace _ => with else => in all match expressions
  • Struct initializers that omit fields now require ..defaults
  • Enum match patterns can use .Variant instead of EnumType.Variant