compare · Zig
fastC vs Zig
The closest in spirit. Zig is excellent at cross-compilation and C interop; fastC chooses capability typing and contracts as the wedge.
Zig and fastC share a lot of taste: no hidden control flow, explicit syntax, "C but better" framing, fast cross-compilation, manual memory management with safety help, and a deep respect for binary size. The two languages diverge on which checks they push into the type system. Zig's wedge is comptime and explicit allocators; fastC's wedge is capability-typed I/O and mandatory contracts.
Row by row
| Dimension | fastC | Zig | Note |
|---|---|---|---|
| Memory safety without GC | Yes (partial) — runtime checks + contracts | Partial — explicit allocators, no borrow checker | Roughly even; both ship safety-via-runtime-checks. |
| Capability-typed I/O | Yes — CapFsRead, CapNetConnect, ... in signatures | No — std.fs / std.net are ambient | fastC's wedge over Zig. |
| Compile-time contracts | Yes — @requires/@ensures, three-tier discharge | Partial — comptime asserts, no postconditions | Different goals; SPARK-style vs metaprogramming. |
| No executable build scripts | Yes — declarative fastc.toml | No — build.zig is arbitrary Zig | Same critique Washburn made of Zig's package manager. |
| Outputs portable C11 | Yes — auditable C | No — emits LLVM IR directly | Differentiated use case for fastC. |
| Cross-compilation | 8 presets via `zig cc` | 50+ targets natively, no sysroot | Zig wins. fastC literally uses Zig's `zig cc` as backend. |
| C interop (ingesting C) | No — emits C, does not parse C | Yes — `@cImport` works on real C headers | Zig wins. Different threat model. |
| Comptime / metaprogramming | No — kept the surface small | Yes — comptime is a major feature | Zig wins on expressiveness; trade-off for surface area. |
| Package system | Vendor-first, content-hashed, no central registry | Zon manifest; arbitrary build.zig | fastC's no-executable-build wins on supply chain. |
| Stripped 'hello' binary | 53 KB | 50 KB | Roughly tied. |
| Provenance on releases | Sigstore + SLSA L3 | Project-by-project | fastC structural. |
| Status / stability | v1.0 feature-complete; v1.x roadmap | Pre-1.0; rapid breaking changes | fastC chose to commit to v1.0 earlier. |
| Agent-first toolchain (MCP, structured diagnostics) | Yes — fastc-mcp + JSON output everywhere | Standard CLI output | fastC's wedge for the agent use case. |
| Safety on the T5 large_sum benchmark | 3/3 correct, 0 silent-wrong | 0/3 compiled (refused on signed `/` without `@divTrunc`) | Different failure modes; both refused to ship wrong bytes. |
Where fastC wins
fastC wins where the threat model is supply chain (no build.zig), capability-aware I/O, contracts as compile-time obligations, agent-first tooling (MCP, structured JSON diagnostics), and stability commitments. The capability and contract systems are the parts of language design Zig deliberately did not take on.
Where Zig wins
Zig wins where the threat model is C-interop-first (ingesting existing C codebases via `@cImport`), comptime metaprogramming, the broadest cross-compile target list, or where pre-1.0 instability is acceptable for access to a more aggressive feature roadmap. Zig is also the better tool for projects that want LLVM IR optimization quality directly.
The honest framing
We genuinely admire Zig. fastC's `--target` presets are implemented by shelling out to `zig cc`. The disagreement is narrow: should I/O be ambient (Zig) or capability-typed (fastC), and should pre/postconditions live in the language (fastC) or in comptime asserts (Zig). On the supply-chain side, we and Washburn appear to agree; Zig has not yet shipped that.