For most languages I can usually see one or two “killer features” that push the language: For Rust is taking C space with memory safety + modern semantics, for Go is being easy to learn by most engineers + parallelization, for Ruby is ergonomics…
I don’t see any similar pitch for zig other than a general “I kinda enjoy it”, and the language seems to have a couple red flags, so why focus on it? (Honest question).
My impression is that this is the main thing for Zig too. The intersection of the set of languages that let you write very low-level code where you have full control over memory and allocation and the set of languages that are enjoyable to program in is pretty small.
C is in there if you've internalized many of its warts are fine with all of the many many footguns it has. C++ is in there if you much of your enjoyment comes from the machismo of feeling like you have conquered C++'s beastly language complexity. Rust is in there if proving to the compiler that you know what you're doing is satisfying to you.
Zig sort of gets out of your way like C does, even when what you're trying to do is potentially harmful. But it's more modern and expressive and doesn't have all of C's historical baggage.
Is that a stated goal of the language? Other than the feature to gradually move from c++ it wasn’t super clear from the main pitch.
I have no idea if Zig will be successful or not, but even if you look just at memory safety, I think it does a better job at that than Rust. If you look at MITRE's top 25 dangerous weaknesses [1] or top 10 exploited weaknesses [2], you'll see that Rust spends almost all of its complexity on eliminating weaknesses that don't even make the top 5 on either list, while Zig's more limited memory safety addresses the more dangerous memory-safety-related problems without paying so dearly to solve less severe issues.
Now, I personally think that Zig's combination of expressivity and simplicity, while still being low-level, is an unprecedented killer feature (I wrote more about it here: https://news.ycombinator.com/item?id=45852774) which makes the language design quite revolutionary and fascinating. This could perhaps translate to correctness benefits.
[1]: https://cwe.mitre.org/top25/archive/2024/2024_cwe_top25.html
[2]: https://cwe.mitre.org/top25/archive/2024/2024_kev_list.html
If it was about just lifetimes, Rust would be a much friendlier language. Sometimes I wonder if a less rigorous Rust would be more popular.
Uh? Number 2 in CWE is an out-of-bounds write, and the same vulnerability is number 1 in the KEV list.
C is very basic and (especially when you stick to something like C99), can be very tedious to write. In C, if I hope for smarter things I need to write them by hand; usually there are no ways of achieving some goals without just crunching out the code. Zig preserves C qualities but also gives some extra tools that are completely optional and makes it less tedious than C.
I believe that Zig's popularity is also caused by general tendency of some people. Some prefer to fix a segfault than spend half a day refactoring something that was supposed to be easy but is causing half of the codebase to be rewritten.
(Oh, and Zig is also an escape hatch to easy CGo :))
It's better at that than Rust because it's less abstracted, and it's better at that than C because you don't have to worry all the toolchain nonsense / weird conventions / weak type system of the C ecosystem.
As a small example wrt Rust: resetting an arraylist/vector while reusing its memory is a weirdly complicated trick https://lobste.rs/s/emvkea/why_we_didn_t_rewrite_our_feed_ha...
I think I don't need to provide references for C.
It's a new pathway to mastery that really works well for some people. That in itself is much more valuable than any new specific feature the language has to offer, although the ability of the toolchain to cross-compile reliably not only Zig but also C and C++ code does play into that.
And, while not yet 100% there, instant incremental rebuilds also help to achieve faster feedback loops.
People like Zig because it's a tool that helps them become better programmers, faster.
A bit of a nitpick here: the trick is for creating a new vector of a different type, that reuses the allocation of an existing vector, using only safe code. "Resetting an arraylist/vector while reusing its memory" is just vec.clear() if you're not changing the type. And it's trivial to change the type of a vector with unsafe (the docs even have examples of this); the only advantage of the "trick" is to ensure you'll get a panic if you screw up the alignment of the types.
And after that blog post, the Rust team accepted a proposal to introduce a vec.recycle() function to change the type of a vector without needing that trick (and with compile-time checks for alignment compatibility): https://github.com/rust-lang/rust/pull/148416
But that example aside, I agree with your overall premise -- Zig and Rust share different design goals here, and Zig's lower level of abstraction makes it more approachable to learn than a language like Rust.
Nitpicking? Let’s show an example on creating an interface in Zig to see all complicated tricks.
I find Zig to be a pleasant option for code that requires high performance. I find it strictly dominates C as an option, as Zig outperforms C on every criteria I care about in a language's developer experience.
I often see people compare Zig to Rust and complain that Zig doesn't have Rust's safety guarantees. I don't know Rust, but looking at it casually, the language itself seems to have a lot of complexity that doesn't appeal to me, and I'd still prefer Zig to Rust. If I need memory safety, I'd rather write in Go or Python.
When I read articles like these, the gotchas they find don't seem that compelling to me. It's always like if you write your code in a deliberately confusing way to confuse the compiler, you can get incorrect results, but I don't care because I would never write code like that.
So to sum up : A powerful C without the quirks that manages to keep things simple but is also a batteries-included experience with a smooth adoption path. What's not to love ?
Every single commonly-used programming language has a couple red flags, often much more than a couple. Javascript, C, C++, Go, Python - these languages all have serious flaws and are nonetheless used by extremely large numbers of people for all sorts of tasks.
In other words, "I kinda enjoy it"?
> I am personally a proponent of a good macro system.
Comptime is much more constraint than any macro system: no code generation (including AST rewrite), no arbitrary tokens. Thus it's much harder to "go overboard" with Zig's comptime. This constraints of cource have their drawbacks, but code generation is still a thing.
> Much of Zig seems to me like "wishful thinking"; if every programmer was 150% smarter and more capable, perhaps it would work.
Nice way to put it! But I oppositely believe the world needs more tech that treats professionals as experts, not kids.
That’s how it was until around the turn of the century. Who needs types, we’re adults after all. Memory safety and garbage collection? Oh please go back to kindergarten.
But then some of us learned that no matter how smart we are, we can make mistakes that those things can actually prevent. And those mistakes can have catastrophic consequences. Professionals should go for tools that help them prevent those mistakes, right??
That's true but it's deeper than that -- no matter how much time goes by, there will always be people new to the language, and they will always make newbie mistakes if the language allows them to. So "just be an expert and don't write shoddy code" doesn't scale, no matter how hard you personally try.
"Memory safe languages" are tools that prevent professionals from making those mistakes.
It's a subtle but important difference. Zig attempts to leave some humanity to the developer.
When someone says they are incapable of earning or deserving that, I feel sad.
Which part of expertise is rejecting the fact that safety through professional mind tricks in lieu of better underlying language design is unattainable?
This made me think about Rust borrow checker: given the amount of people struggling with it, I would think the number of experts is much lower than I would initially assume.
Seconded. I've really come to loathe tech that is constantly trying to "help me" unprompted and do things I didn't ask/want it to do or burying settings/configurations if not obfuscating them away entirely and acting as if it's doing me a favor by removing features in the name of "simplicity" or some shit. And let's not forget built-in obsolescence moonlighting with privacy-disrespecting dark patterns masquerading together as "Smart Devices."
This attitude is why we still have bounds checking memory bugs in new software in 2025.
IMHO an artisan should want superior tools that produce better results.
Great post on what comptime won't do: https://matklad.github.io/2025/04/19/things-zig-comptime-won...
... and the same could be said about Rust, only with Rust we can already see that it suffers from relatively low adoption at a relatively advanced age.
The funny thing about that claim is that it leads to an obvious question: if working harder to satisfy the compiler is something that requires less competence than other forms of thinking about a program, then why Rust? Why not ATS? After all, Rust does let you eliminate certain bugs at compile time, but ATS lets you eliminate so many more.
Maybe you and I have different working definitions of "relative", but Rust hit 1.0 only 10 years ago, whereas the age of the most popular languages is 30+ years. In that sense Rust is relatively young. Indeed, Rust is the youngest language in the TIOBE top 20, and it's more popular than other languages which have been around much longer. The only language which comes close is Swift, and that one had the advantage of Apple pushing it as the main language for iOS development, Rust never had that kind of marketing and corporate support.
What are we measuring? Lines of code? Number of programmers employed? Number of new applications started?
Rust is in: Linux, Windows, Azure, all over AWS, Amazon's Prime video, Cloudflare's proxy, Firefox, Python's `cryptography` package, Zed editor. This is just the sample I know of.
Is this low adoption?
As in, why not use a language with much stronger formal verification? Because people have tried it and failed.
Like you said, Rust is hard, it already feels at the limit of what people can handle.
But unlike ATS, many people have tried Rust and succeeded, and some Rust programmers even claim that they become very productive with it after a while. I very much doubt the same could be said about ATS.
I can see another language having a more expressive type system, I've come up against the limitations of Rust's type system more than once, but the tradeoff isn't worth it if I have to go 20 years back in time in terms of tooling.
How much adoption should we expect Rust to have at this point, and how does it compare to other languages? I certainly don't have the impression that Rust has relatively low adoption in a general sense, although I'm also a fan of the language and make a point of being in programming communities that are interested in Rust too.
Of course it's subjective, but I think there is a perception of perceived benefit over effort. Zig gives much perceived benefit over low effort. Rust gives much perceived benefit over more effort. Even more effort for ATS. But the benefit is relative: nobody cares to create totally bug-free software when the software is not critical at all. In addition, most programmers think that solving bugs is part of the job more than preventing them. Solving segfaults is often easier than thinking about formal systems, so the perceived benefit is higher in Zig than ATS - at least for programmers that know C, pointers and the like. Note how the majority of programmers don't deal with memory allocations at all: they use JavaScript and Python, memory is managed. For them, solving memory bugs is not something that makes sense, so the effort of dealing with memory is enough to renounce that freedom altogether. Rust is a very good middle ground: it's a complex language, but there's lot of room for improving its ergonomics.
It is correct that the hype is past its peak, however, the TIOBE trend (if one wants to use that) is actually steadily increasing.
> There is still some development in linux
"Some development" is a miscarachterization - the official addition to the Linux kernel itself is a very big deal, and its adoption is increasing and will continue to do so.
I think that Rust has found its niche in safe low-level programming, and it will slowly have an increasingly dominant role in (although the ceiling of this area is certainly limited in the global landscape).
Oh, 14th [1]. That's a lot lower than I would have expected, based purely on the amount of noise surrounding Rust.
Rust has a SDK from the 3 big cloud providers, Rust IS mainstream.
Zig is a better C. No abstractions. Close to bare metal.
Rust is a better C++. Abstractions to simplify application level programming.
The reason we care about memory-safety so much, compared to other invariants we'd like our programs to have is because, as the article notes, a very high portion of vulnerabilities are due to memory-safety violations. This is why preventing or reducing such violations is important in the first place.
But if we look at vulnerability rankings [1][2], we see that Zig's memory safety covers the top weaknesses just as well as Rust, and much better than C. The vast difference in the complexity of these two languages is because Rust pays a lot to also prevent less dangerous vulnerabilities, outside the top 5.
So if Rust is good because it eliminates some very common dangerous vulnerabilities thanks to its memory safety, then Zig must also be good for eliminating the same ones. Calling it C-like because it doesn't eliminate some less common/dangerous vulnerabilities just because Rust does, is just a misunderstanding of why this is all important in the first place. (Plus, if it's important to reduce the security vulnerabilities due to memory safety violations, isn't it better to make avoiding the worst outcomes more approachable?)
In software correctness there are few easy choices. Everything boils down to how much you can and should pay to improve your confidence that a certain level of damage won't occur. It's a complicated subject, and trying to present it as a simple one does it a great disservice.
In fact, both Rust and Zig address some of the most common/dangerous vulnerabilities — more than use-after-free - just as well as C, which is to say, not, or barely, at all. I.e. there are worse vulnerabilities that neither one of them eliminates than the ones Rust eliminates and Zig doesn't.
There is no doubt that Rust and Zig are meant to appeal to people with different aesthetic preferences, but the attempt to distinguish them by turning the matter of memory-safety into a binary one simply doesn't make sense. The property of memory safety is itself not binary in both languages, and the impact of memory safety is split between more and less important effects.
I understand why people wish to find objective metrics to prefer one language over another, but often such metrics are hard to come by, and extrapolation based on questionable assumptions is not really objective.
But if you choose to only focus on security weaknesses, and you choose to ignore the language design's impact on code reviews or the fact that allocations are much more visible in Go than in C (which is not very objective, but perhaps you consider these harder to quantify), you would still have to conclude that there's a big difference - on your chosen metric alone - between Zig and C, and a rather small difference between Rust and Zig.
What I think really happens, though, is that most of the preference boils down to aesthetics, and then we desperately seek some objective measures to rationalise it.
> Much of Zig seems to me like "wishful thinking"; if every programmer was 150% smarter and more capable, perhaps it would work.
But if working harder to satisfy the compiler is something that requires less competence than other forms of thinking about a program, then why Rust? Why not ATS? After all, Rust does let you eliminate more bugs at compile time than Zig, but ATS lets you eliminate so many more. So, if this is an objective measure to reject Zig in favour of Rust, then it must also be used to reject Rust in favour of ATS.
Neither Rust nor Zig are anywhere near either extreme on compile-time guarantees in general and memory-safety in particular. They're closer to each other on the spectrum than either one of them is to either C or ATS. They both compromise heavily. It's perfectly fine to prefer one compromise over the other, but to a measure that would settle which of these compromises is objectively better is just not something we have at this time.
[1]: https://cwe.mitre.org/top25/archive/2024/2024_cwe_top25.html
[2]: https://cwe.mitre.org/top25/archive/2024/2024_kev_list.html
The exact positioning within the top 10 is also quite noisy: if you look at last year's list, UAF is in the #1 spot for actively exploited vulnerabilities, even beating out all the web ones: https://cwe.mitre.org/top25/archive/2023/2023_kev_list.html
Lastly, filtering on CVEs has a high selection bias: just because security researchers go for the easy vulnerabilities first doesn't mean that the harder ones can be ignored. As high-profile projects adopt tooling and mitigations to reduce the impact of spatial memory safety problems, it's common to see a sudden increase in CVEs related to temporal memory safety. This is not because use-after-free bugs somehow became more common or severe -- it's because once you eliminate the easy source of vulnerabilities, the attackers shift their attention to the new lowest-hanging fruit.
The point isn't about limiting to the top 5. The point is that once you get to the things Rust prevents and Zig doesn't, there are quite a few more things that neither prevents, so it's just silly to draw a a particular sharp line between Rust and Zig because they perform exactly the same (in terms of sound guarantees; we're ignoring any softer effects) for most top weaknesses.
Even if you think that difference is so important that it justifies downsides that Rust may have in comparison, you still have to admit that Zig is much, much closer to Rust than to C by that measure.
And this "closer" matters because Rust's memory safety is also not absolute, and Rust proponents must accept that the cost of memory safety is an important factor, too, and sometimes not worth it, or else Rust wouldn't have been invented in the first place. After all, languages that are as memory-safe as Rust and more were more popular than Rust will ever be before it was even invented.
So Rust proponents must accept that eliminating dangerous vulnerabilities is good (unlike C), that productivity and cost do matter (unlike ATS), and that non-absolute memory safety is acceptable. And Zig satisfies all of these points, too.
The reason it's hard to find an objective metric to draw the line between Rust and Zig is because they're actually quite close to each other, at least on this front of trying to find a useful compromise between productivity and guarantees.
> Lastly, filtering on CVEs has a high selection bias: just because security researchers go for the easy vulnerabilities first doesn't mean that the harder ones can be ignored.
Sure, but then you might as well also consider softer effects. For example, maybe a language that's easier to review because it's more explicit, or a language that's faster to compile and is easier to test wins.
And I agree that we should consider all these, but then we start seeing why correctness is such a complicated topic, and we could speculate just as easily that it is Zig that "clearly" wins.
Anyway, it's perfectly fine for people to prefer Rust because they like it. But the attempt to find objective reasons for this preference is not based on any truly objective foundations, and just looks like some desperate rationalisation.
And BTW,
> relevant to applications that would typically be written in C/C++/Rust/Zig
If you think that Rust and Zig are designed to target the exact same domains, then some of the "softer" aspects I mentioned could play even a larger role. I mean, the portion of software written in low level languages has been declining steadily for a long time with no sign of a change in the trend. To me it seems that Zig has internalised the narrower and more focused and role of low-level languages today compared to what C++ imagined it would be in the eighties.
But Zig does not eliminate them, but rather it might catch them at runtime. The difference here is that Rust promises that it will detect them at compile time, long before I ship my code.
> The property of memory safety is itself not binary in both languages
In this case it is: either you catch the issue at compile time, or you don't. This is the same as type safety: just because Python can detect type errors at runtime it does not mean that it's as "type safe" as, for ex. Haskell. This might be due to imprecise usage of terms but that's just the way it's discussed in the craft.
So does Rust. That's what we mean by eliminating them. Zig/Rust will panic, but you won't get a vulnerability.
> The difference here is that Rust promises that it will detect them at compile time, long before I ship my code.
No, Rust doesn't guarantee catching spatial-memory-safety violations at compile-time. Neither do Java, Python, or JS/TS, by the way.
But once you've taken care of the top weaknesses, it becomes harder to justify putting more effort into eliminating some weaknesses that could go into reducing more common/dangerous ones. If vulnerabilities are the justification, it definitely makes more sense to reduce, say, #4 on the list than #7.
For example, it would be interesting to compare how many Rust bugs mentioned crashes back when there were only 13k bugs reported, and the same for the JS VM comparison. Don’t get me wrong, as a Rust zealot I have my biases and still expect a memory safe implementation to be less crashy, but I’d be much happier concluding that based on stronger data and analysis.
Actual SIGSEGVs are pretty rare, even during development. There was a pretty interesting one that affected our fuzzing infra a little bit ago: https://ziggit.dev/t/stack-probe-puzzle/10291
Almost all of the time we hit either asserts or panics or other things which trigger core dumps intentionally!
- deno 44: https://github.com/denoland/deno/issues?q=is%3Aissue%20state...
- bun 464: https://github.com/oven-sh/bun/issues?q=is%3Aissue%20state%3...
That is a bias. You want all your "memory safety" to be guaranteed at compile time. Zig is willing to move some of that "memory safety" to run time.
Those choices involve tradeoffs. Runtime checks make Zig programs more "crashy", but the language is much smaller, the compiler is vastly faster, "debug" code isn't glacially slow, and programs can be compiled even if they might have an error.
My personal take is that if I need more abstraction than Zig, I need something with managed memory--not Rust or C++. But, that is also a bias.
You may potentially like D. Its tooling leaves much to be desired but the language itself is pretty interesting.
otherwise, not sure who the audience of this piece is supposed to be, but it's written in a pretty combative tone, which will not be persuasive to anyone who isn't already persuaded, so i guess more of a rant than anything worth sharing here
That's because Zig defers a bunch of checks to runtime that Rust will force you to deal with before it will let you compile at all.
That is a tradeoff. Developer velocity vs memory safety.
Given that Bun seems to be beating Deno on most metrics, it seems like that was the correct choice for Bun.
so if you wanna talk about it you at least gotta say which definition you're using
I don’t think comptime as just some macro system. It is closer to a reflection system. I use comptime to access types. You can create specialized paths depending on type.
Also imo generics are “first class” in zig. Comptime is first class and thus generics are too.
Is everything first class, then?
This anything implements with macros are not first class
I don't really think much of Zig myself for other reasons, but comptime seems like a good design.
Is that the case? That's not what I think of when I think of C-style casts.
float val = 12.4;
int val_i = (int) val;
The representation in memory of `val` should not match that of `val_i`, right? The value is encoded differently and the quantity is not preserved through this transformation. I don't think that means that the data weren't changed.Maybe you're thinking of aliasing/type-punning? Casts in C do perform conversions as they do in C++.
INCR[U] i FROM 0 TO len(arr) [BY 1] DO ...
DECR[U] i FROM len(arr) TO 0 [BY 1] DO ...
Although actual BLISS-77 had inclusive semantics for the upper bounds in both forms. Which, on one hand, allows you to write DECRU i FROM UINT_MAX TO 0 DO ...
and expect it to Just Work™ (hopefully? No idea if it worked on actual implementation ― but would've been nice, writing the same in e.g. C is kinda annoying; good luck with Golang pre-1.22 and even then, getting that one last iteration is quirky) but on the other hand, inclusive upper bounds require you to write add that "-1" almost everywhere.People think it's a slight on their abilities. "I can write memory safe code!" Maybe you can. There are two huge problems here, and they're problems that will never go away no matter how good you are.
The first is that this doesn't scale. As soon as you add more programmers to a project, you multiply the odds of bugs like this. Even if everyone's just as good, not everyone will have the whole program in their head or code in exactly the same style.
The second is that code rots. Your new C (or Zig) program might be totally correct and memory safe when it's first written. Then you commit it to a repo. Then you move on to another project for a while. Then someone else fixes something and you merge a PR. Then you come back to it three months later and you're under pressure to implement something. Then you work in a new feature a year later and you've forgotten some of the really nit-picky details of how things work. It's very easy over time for bugs to creep in, and if the language doesn't catch them they'll sit in the code until they cause random crashes or, worse, a CVE.
These aren't avoidable issues. They're inherent to software and its life cycle. Memory safe languages (and secure computing systems in general) are the only way to deal with them.
This statement, albeit true, is highly misleading. In the example given, you ought to be concerned with parallel assignments not parallel moves. See [0] for more details on the distinction.