I would say it's well on the way to becoming the best language for giving you control as a programmer over the computer. Compared to say Rust focusing on safety first, execution speed second, ergonomics third; Or Go on maintainable systems at large corp scale.
To list some specific examples:
- No headers.
- No complex build and linkage systems.
- Fast compilation (and no explosion of compile time as headers import headers.)
- A small and distinct set of fundamental types, with true enums, unions, and arbitrary size integers.
- Code formatting, which is a feature that feels kind of invisible, but means arbitrary code you look at will be formatted in a familiar way. A subtle but powerful difference.
- It doesn't try to remove undefined behavior. Instead it does a really good job of catching you hitting it when building in a development version. Imo, often code wrote simply will have undefined behavior that is meaningless because it will never be called with that behavior. It's fine to code that way in C until you accidentally hit it and have a hell of a time figuring out why something isn't working.* A concurrency mechanism that's very easy to use, because it doesn't have the function coloring problem of async/await.
* Extra assistance with memory safety, via its "release-safe" mode. Not a silver bullet, but it does help!
* Good tooling; zig cc can cross-compile from any major OS to any major OS.
* Comptime, a pretty brilliant system that does what generics does for other languages, with a fraction of the complexity.
Again, memory safety has never really been a problem for me where I use C; and if I want it, I'd want something as strong as Rust's borrow checker or at least the smart pointers of C++.
zig cc can't cross-compile on all platforms, particularly not esoteric and proprietary embedded targets or game hardware, and so that's a nothingburger for me.
std.HashMap
std.ArrayHashMap
std.MultiArrayList
std.heap.ArenaAllocator
defer/errdefer, try, catch
Debug mode: stack traces, safety checks, segfault handler, error return tracing, valgrind integration, undefined bytes set to 0xAA, GeneralPurposeAllocator finds leaks, double frees, and use-after-frees
Comptime instead of macros
Unit testing
Tagged unions _kind of suck_, and the alternatives are preprocessor abuse, _Generic, or similar. Just not as appealing as comptime, really.