From 11‑Day AI‑Powered Zig‑to‑Rust Rewrite to a 487‑Day Manual Rust‑to‑Zig Rewrite
The article contrasts Bun's 11‑day AI‑driven rewrite of 500 k lines of Zig to Rust with Roc's 487‑day manual rewrite of a 300 k‑line Rust compiler to Zig, analyzing the engineering motivations, performance benchmarks, memory‑safety bug counts, and ecosystem trade‑offs that led each team to choose its language.
Contrasting Two Extreme Language Rewrites
Bun announced that it used Claude AI to rewrite roughly 500 k lines of Zig code into Rust in just 11 days, while the Roc compiler team published a story about manually rewriting a 300 k‑line Rust compiler into Zig over a span of 487 days.
Root Cause of the Rewrite
The rewrite was not driven by a dislike of Rust; instead, a long‑standing architectural bug—"polymorphic defunctionalization"—made the existing Rust implementation untenable, prompting a full rewrite from scratch.
Why Zig Was Chosen
Build speed: Zig’s incremental build flag -fincremental completes in about 35 ms, roughly 100× faster than Rust’s 3.4 s.
Memory allocator control: Zig’s design passes allocators everywhere, matching Roc’s heavy use of arenas and struct‑of‑arrays layouts.
Ecosystem fit: Zig provides more ready‑made code for generating LLVM bitcode without relying on C++ libraries.
Unsafe‑code handling: The original Rust code contained about 1 200 unsafe blocks in 300 k lines, a proportion higher than Rust’s own codebase, making Zig’s safety‑net for unsafe code attractive.
Bug Statistics Without Borrow Checker
When the Rust borrow checker was omitted, the Zig version reported 10 memory‑corruption bugs versus 21 in the Rust version. All 21 Rust bugs originated in the generated machine code, demonstrating that the borrow checker still prevented many issues.
Build Performance Details
Incremental compilation with zig build --watch -fincremental took ~35 ms. The stable Zig 0.16.0 had a bug that broke -fincremental for the codebase, requiring a switch to the pre‑release 0.17.0 for full stability.
Architecture Red‑Line: Zero‑Parse Deserialization
Roc introduced a cache that stores data structures as index arrays on disk, allowing them to be read back into memory without any parsing step—essentially a memcpy‑speed deserialization.
Ecosystem Trade‑offs
Rust’s Drop mechanism helped Bun manage mixed JavaScript garbage‑collected and manually‑managed memory, while Zig’s explicit defer aligns with Roc’s arena‑based allocation strategy. Each ecosystem is optimized for its own project patterns.
What the Author Misses and Gains
Misses Rust’s automatic memory management, parametric polymorphism, private fields, snake_case conventions, the ergonomics of unsafe with the borrow checker, and seamless backward compatibility.
Appreciates Zig’s lack of macros, powerful comptime functions, fine‑grained data layout control (e.g., u7, u5, packed structs), excellent build toolchain, and error‑handling model that treats allocation failures as ordinary user‑level errors.
Conclusion
The two rewrites illustrate that language choice is dictated by concrete architectural debt and project constraints rather than abstract superiority. Rewrites should solve real engineering problems, and the “better language” is the one that best fits the specific needs of the codebase.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
TonyBai
Tony Bai's tech world (tonybai.com). Not satisfied with just "knowing how", we strive for mastery. Focused on Go language internals, high-quality engineering practices, and cloud‑native architecture, exploring cutting‑edge intersections of Go and AI. Gophers who pursue technology are welcome—follow me and evolve with Go.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
