Why I rewrote my Rust keyboard firmware in Zig: consistency, mastery, and fun
After writing a lot of Rust, I recently did a small project with Zig to learn the language.<p>I&#x27;m especially impressed with the C interop. You can just import C headers, and Zig will use clang to analyze the header and make all symbols available as regular Zig functions etc. No need for manually writing bindings, which is always an awkward and error-prone chore, or use external tools like bindgen, which still takes quite a bit of effort. Things just work. Zig can also just compile C code.<p>Rust indeed can feel very heavy, bloated and complicated. The language has a lot of complex features and a steep learning curve.<p>On the other hand, Rust has an extremely powerful type system that allows building very clean abstractions that enforce correctness. I&#x27;ve never worked with a language that makes it so easy to write correct, maintainable and performant code. With Rust I can jump into almost any code base and contribute, with a high confidence that the compiler will catch most of the obvious issues.<p>The defining feature of Rust is also the borrow checker and thread safety (Send&#x2F;Sync), which contribute a lot to the mentioned correctness. Zigs doesn&#x27;t help you much here. The language is not much of an improvement over C&#x2F;C++ in this regard. The long-term plan for Zig seems to be static analysis, but if the many attempts for C&#x2F;C++ in this domain show anything is that this is not possible without severe restrictions and gaps.<p>Choosing to forego generics and do everything with a comptime abstraction makes Zig a lot easier to understand, compared to Rust generics and traits. The downside is that documentation and predictability suffers. Comptime abstractions can fail to compile with unexpected inputs and require quite a bit of effort. They are also problematic for composability, and require manual documentation, instead of getting nicely autogenerated information about traits and bounds.<p>Many design decisions in Rust are not inherently tied to the borrow checker. Rust could be a considerably simpler, more concise language. But I also think Rust has gotten many aspects right.<p>It will be very interesting to see how Zig evolves, but for me, the borrow checker, thread safety and ability to tightly scope `unsafe` would make me chose Rust over Zig for almost all projects.<p>The complexity of Rust is a pill you have to swallow to get those guarantees, unless you use something like Ada&#x2F;Spark or verifiable subsets of C - which are both more powerful than Rust in this regard, but also a lot more effort.<p>Some smaller paper cuts, which are partially just due to the relative youth of Zig:<p>* no (official) package manager yet, though this is aparently being worked on<p>* documentation is often incomplete and lacking<p>* error handling with inferred error sets and `try` is very nice! But for now errors can&#x27;t hold any data, they are just identifiers, which is often insufficient for good error reporting or handling.<p>* No closures! (big gotcha)