# CHECKPOINT-METATYPE — comptime type metaprogramming (`declare` / `define`) Companion to [PLAN-METATYPE.md](PLAN-METATYPE.md). Update after every step (one step at a time, per the cadence rule). ## Last completed step **The `declare`/`define` floor — the compiler's only type-construction surface.** Two comptime `#builtin`s mint types; every constructor (`RecvResult`, `TryResult`, the one-shot form) is plain sx built over them. The compiler has ZERO knowledge of any named constructor. - `declare() -> Type` mints an empty (undefined) nominal slot; `define(handle, info) -> Type` decodes the `TypeInfo` value (variant names + payload Type-tags), names the slot from `EnumInfo.name`, completes it byte-identical to a source enum, and returns the handle (so the one-shot form chains: `T :: define(declare(), info)`). Interp executes both against a `mint` TypeTable handle (`setMintTable`); `defineEnum` + `decodeVariantElements` in `interp.zig`. - A `::` binding or type-fn body that calls a `Type`-returning fn is **comptime-evaluated** (`evalComptimeType`), running the `declare`/`define` builtins to mint the type — no constructor-name pattern-matching. `decl.zig` trigger = `fnReturnsTypeValue`; type-fn trigger = `returnExprMintsType` (return is a `define(…)` call or a bodied `-> Type` helper). - Nominal identity rides the type-fn instantiation cache (`renameNominalType` re-keys the minted type to the mangled name); `RecvResult(i64)` at two sites is ONE type. - The type NAME travels in `EnumInfo.name` — the compiler derives no name from a binding LHS. Examples green on the floor: `0614` (one-shot `define(declare(), …)`), `0615` (type-fn identity), `0617` (channel result types). `field_type` reflection still green (`0616`). Full suite green (673 examples). ## Current state - `modules/std/meta.sx`: `EnumVariant` / `EnumInfo{ name, variants }` / `TypeInfo` data types; `declare` / `define` / `type_info` / `field_type` `#builtin`s; `RecvResult($T)` / `TryResult($T)` sx constructors over `define(declare(), …)`. - Compiler primitives only: `declare`/`define` (construction), `field_type` (reflection). No constructor-name knowledge anywhere in the compiler — every named constructor is sx. - `type_info` still bails loudly (`call.zig:tryLowerReflectionCall`) — pending. ## Decision (kept) **Meta lives in `modules/std/meta.sx`, not the prelude.** Declaring its data types in the always-loaded prelude interns them into every module's type table and shifts every `.ir` snapshot. On-demand import keeps the prelude clean. ## Next step **Self-reference (recursive / mutually-recursive enums).** The two-statement form `List :: declare(); define(List, .enum(.{ … payload = *List … }))`: `declare` binds the handle, `define` completes it, and `*List` resolves because a pointer to an undefined slot is legal. Needs the top-level `define(…)` statement form to run at comptime in the window before any use of the type's layout (a bare top-level call doesn't parse today — decide the surface). Pairs with a `make_enum(variants: []EnumVariant)` sx helper (a computed, non-literal variant list — exercises the interpreter decoding a value-arg slice). Then: **`type_info($T) -> TypeInfo`** (reflect a type INTO a value — the inverse of `define`'s decode; widen `TypeInfo` past `` `enum `` + construct a `[]EnumVariant` value in the interp; its own focused effort) and **validation + loud diagnostics** (dup variants, by-value self-ref, never-defined `declare`, use-before-define). ## Known issues None. ## Log - **declare/define floor established.** The comptime type-construction surface is two primitives (`declare`/`define`); all named constructors are sx. A `::` binding or type-fn body that calls a `Type`-returning fn is comptime-evaluated (the builtins mint the type) — no syntactic constructor recognition in the compiler. Name travels in `TypeInfo`. Examples 0614 (one-shot) / 0615 (type-fn identity) / 0617 (channel results) run on the floor; `field_type` reflection (0616) unchanged. Full suite green (673). - **Stream carved (earlier).** Selected as the first async-first foundation: gates channel result types (`RecvResult($T)`) and `race`'s synthesized union, fully validated, self-contained, testable in isolation (`06xx` comptime).