Generics Reference
Generics Reference
Section titled “Generics Reference”Profile: :core
Spec: SPEC-026
Syntax
Section titled “Syntax”Generic Function Declaration
Section titled “Generic Function Declaration”Type parameters in square brackets between function name and argument list:
func identity[T](x: T) -> T do return xendMultiple parameters:
func zip[A, B](a: A, b: B) -> A do return aendTrait Bounds
Section titled “Trait Bounds”func min[T: Ord](a: T, b: T) -> T do if a <= b do return a end return bendMultiple bounds with +:
func clamp_and_add[T: Ord + Numeric](value: T, lo: T, hi: T, offset: T) -> T do if value < lo do return lo + offset end if value > hi do return hi + offset end return value + offsetendCall Site
Section titled “Call Site”Type argument is always explicit:
let result = min[i64](3, 7)let x = identity[i64](identity[i64](42))Trait Hierarchy
Section titled “Trait Hierarchy”trait Eq { func eq(self, other: Self) -> bool func ne(self, other: Self) -> bool}Enables == and !=. Satisfied intrinsically by all integer types, floats, and bool.
Ord: Eq
Section titled “Ord: Eq”trait Ord: Eq { func lt(self, other: Self) -> bool func le(self, other: Self) -> bool func gt(self, other: Self) -> bool func ge(self, other: Self) -> bool}Enables <, <=, >, >=. Implies Eq. Satisfied by all integer and float types.
Numeric: Ord + Eq
Section titled “Numeric: Ord + Eq”trait Numeric: Ord + Eq { func add(self, other: Self) -> Self func sub(self, other: Self) -> Self func mul(self, other: Self) -> Self func div(self, other: Self) -> Self}Enables +, -, *, /. Implies Ord and Eq.
Primitive Satisfaction Table
Section titled “Primitive Satisfaction Table”| Type | Eq | Ord | Numeric |
|---|---|---|---|
i8, i16, i32, i64 | ✓ | ✓ | ✓ |
u8, u16, u32, u64 | ✓ | ✓ | ✓ |
f32, f64 | ✓ | ✓ | ✓ |
bool | ✓ | — | — |
No impl blocks required for primitives. The TraitOracle resolves these intrinsically.
Supertrait Propagation
Section titled “Supertrait Propagation”The TraitOracle uses fixpoint iteration: if T satisfies Numeric, it automatically
satisfies Ord and Eq without any additional annotations.
Numeric → Ord → EqConstraint violation messages include supertrait context:
error: type `bool` does not satisfy trait bound `Ord` required for `min[T=bool]` note: `Ord` requires `Eq` (supertrait: `trait Ord: Eq`)std.core.math_generic
Section titled “std.core.math_generic”min[T: Ord]
Section titled “min[T: Ord]”Returns the smaller of a and b.
func min[T](a: T, b: T) -> T do if a <= b do return a end return bendmax[T: Ord]
Section titled “max[T: Ord]”Returns the larger of a and b.
func max[T](a: T, b: T) -> T do if a >= b do return a end return bendclamp[T: Ord]
Section titled “clamp[T: Ord]”Constrains value to [lo, hi].
func clamp[T](value: T, lo: T, hi: T) -> T do if value < lo do return lo end if value > hi do return hi end return valueendfunc main() do print_int(clamp[i64](2, 5, 10)) // 5 print_int(clamp[i64](7, 5, 10)) // 7 print_int(clamp[i64](15, 5, 10)) // 10endIntrinsic-Backed Generics
Section titled “Intrinsic-Backed Generics”Some generic functions are backed by compiler intrinsics with type-constant injection.
The lowerer resolves the concrete type from ctx.type_substitution and appends
type-specific constants before LLVM emission:
func truncate[T](value: i64) -> T do @intrinsic("truncate", value) // lowerer injects: bit_widthend
func toInt[T](value: i64) !T do @intrinsic("int_cast_checked", value) // lowerer injects: min, maxendSee std.core.conv for full documentation.
Implementation
Section titled “Implementation”Monomorphization in lower.zig:
- Call site with
[T=i64]collected into aTypeSubstitution - Function body lowered with
Tsubstituted throughout - Mangled name emitted (e.g.,
min_i64) - Result cached in
mono_cache— each unique(name, type_args)pair lowered once
Known Limitations (2026.3.14)
Section titled “Known Limitations (2026.3.14)”- No type inference —
[T]must be explicit at every call site - Single-param substitution —
ctx.type_substitutionuses first mapped type for intrinsic constant injection (sufficient for single-Tfunctions) - Pre-existing leak —
mono_cachemangled name strings not freed on teardown (tracked, non-blocking)