Comptime

24.1 What Comptime Is

Zig can execute ordinary Zig code at compile time. Types are values of type type, available at comptime.

Comptime replaces macros, templates, constexpr, and code generation.

24.2 Comptime Variables, Blocks and Expressions

Container-level const initializers are evaluated at comptime automatically.

Comptime execution has a branch quota (default 1000 backward branches). Raise it with @setEvalBranchQuota(n).

fn fib(n: u64) u64 { return if (n < 2) n else fib(n - 1) + fib(n - 2); }

const fib20 = comptime fib(20);               // computed during compilation

const squares = blk: {                        // build a lookup table at comptime
    var table: [16]u32 = undefined;
    for (&table, 0..) |*e, i| e.* = @intCast(i * i);
    break :blk table;
};

pub fn main() void {
    comptime var i = 0;                       // comptime-mutable variable
    inline while (i < 3) : (i += 1) {
        std.debug.print("{d} ", .{i});
    }
    comptime {
        std.debug.assert(@sizeOf(usize) >= 4); // compile-time assertion
    }
}

24.3 Comptime Parameters

fn repeat(comptime n: usize, value: u8) [n]u8 {
    return [_]u8{value} ** n;            // array size depends on a comptime parameter
}
const r = repeat(4, 'x');                // [4]u8

fn printTimes(comptime msg: []const u8, comptime times: u32) void {
    inline for (0..times) |_| std.debug.print(msg ++ "\n", .{});
}

24.4 Compile Errors and Logs

fn onlyInts(comptime T: type) void {
    if (@typeInfo(T) != .int) @compileError("expected an integer type, got " ++ @typeName(T));
}
comptime { @compileLog("debug value:", 42); }   // prints during compilation (then fails the build)

24.5 Comptime Strings and Format

const greeting = "Hello, " ++ "World";          // comptime concatenation
const banner = "=" ** 20;
const msg = std.fmt.comptimePrint("v{d}.{d}", .{ 1, 2 });   // comptime formatting
_ = .{ greeting, banner, msg };

24.6 Embedding Files and Build-Time Data

const logo = @embedFile("assets/logo.png");     // []const u8 baked into the binary
const shader_src = @embedFile("shaders/main.glsl");
const build_options = @import("build_options"); // values from build.zig (b.addOptions)
_ = .{ logo, shader_src, build_options };

24.7 Comptime Limitations

No syscalls, no allocator heap (use comptime arrays and slices), no pointer-to-int arithmetic on runtime memory, and no non-deterministic operations.

Comptime code must be deterministic and terminate (within the branch quota).