Open-Source Wikis

/

Zig

/

How to contribute

/

Patterns and conventions

ziglang/zig

Patterns and conventions

Conventions visible from reading the source. There is no STYLE.md; what follows is what the codebase actually does.

Files and naming

  • One type per file when the file is named after a type. src/Compilation.zig, src/Zcu.zig, src/Sema.zig, lib/std/Build.zig, lib/std/Build/Step.zig are all pub const Self = @This();-style files. The file name matches the exported type.
  • lowercase for module-style files. src/codegen.zig, src/link.zig, src/target.zig, lib/std/mem.zig are namespaces, not types. They expose pub const X = ... and pub fn ....
  • fmt is enforced. zig fmt --check runs in CI.

Imports

Files start with imports at the top, grouped roughly as: stdlib first, then internal modules. Example from src/main.zig:

const std = @import("std");
const Compilation = @import("Compilation.zig");
const link = @import("link.zig");
const Package = @import("Package.zig");

Allocation

  • Pass Allocator explicitly. The compiler usually has a top-level arena (gpa) and per-stage arenas (comp.arena, zcu.gpa). Look at src/Compilation.zig for the canonical setup.
  • Container types in lib/std/ come in Managed (carries an allocator) and Unmanaged (does not) flavors; e.g. ArrayList and ArrayListUnmanaged. Compiler internals lean on the Unmanaged ones.
  • defer ... .deinit() is used everywhere to avoid leaks; many helpers also support errdefer.

Errors

  • All fallible functions return !T; the error set is usually inferred. When a function explicitly enumerates the set, the names are descriptive (e.g. error.OutOfMemory, error.Overflow, error.InvalidElfFile).
  • The compiler builds an ErrorBundle (see lib/std/zig/ErrorBundle.zig, ~33 KB) for diagnostics rather than printing inline. Zcu accumulates these and main.zig renders them at the end.
  • try is the dominant control flow; explicit catch is reserved for places that need to map or accumulate errors.

Comptime

  • Heavy use of comptime for compile-time tables, type generation, and sentinel checks.
  • inline fn and inline for/inline while are used where the optimizer should specialize per-type.
  • ZIR is the target of comptime evaluation; AIR contains only post-evaluation results.

Concurrency

  • The compiler's threading model is one ThreadPool plus per-decl work items. See src/Compilation.zig for the queues.
  • lib/std/Thread.zig (~72 KB) is the source for std.Thread; lib/std/atomic.zig for atomics.
  • The new lib/std/Io.zig model is the recommended path for I/O concurrency in user code.

Logging

  • std.log.warn, std.log.info, std.log.debug. Scopes are used liberally. src/main.zig's std_options sets the default log level by build mode (.debug in Debug, .info in ReleaseSafe/ReleaseFast, .err in ReleaseSmall).

Panic and asserts

  • std.debug.assert for invariants.
  • std.process.fatal (aliased as fatal in src/main.zig) for unrecoverable user-facing errors.
  • The compiler's panic handler is crash_report.panic (see Debugging).

Tests

  • test "name" { ... } blocks colocated with the code under test.
  • zig build test-behavior and zig build test-fmt are CI gates.
  • comptime { _ = ... } blocks are used to force the compiler to import test files at the bottom of namespaces (e.g. comptime { _ = start; } in lib/std/std.zig).

Self-deprecation markers

  • pub const @"bad O(N)" = void; in src/main.zig is a literal compile-time tag used to flag and grep for inappropriate linear searches the maintainers want to fix.
  • Deprecated; doc comments on aliases mark API churn (e.g. ArrayListAlignedarray_list.Aligned in lib/std/std.zig).

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Patterns and conventions – Zig wiki | Factory