> Zig's comptime is a very large and all-encompassing feature that ultimately brings very little to the table that smaller features cannot.
> 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.
> But I oppositely believe the world needs more tech that treats professionals as experts, not kids.
Which part of expertise is rejecting the fact that safety through professional mind tricks in lieu of better underlying language design is unattainable?
> 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??
> But then some of us learned that no matter how smart we are, we can make mistakes that those things can actually prevent.
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.
It's not that subtle, the thing that we knew doesn't work still doesn't work.
Some of our problems are novelties because before Grace Hopper basically nobody is writing software so there aren't centuries of lessons in how to do it properly - but this problem isn't like that, all the safety critical industries could tell you that "professionalism" won't prevent the mistakes and what you need is mechanism so that the mistakes cannot happen.
Let me give you an example I like from the railways, which are about twice as old. One night, signaller comes on duty and during the day a team of engineers have been doing work on "his" signal box. Still, things seem to check out and he gets to work, a train approaches, he tries to give them their whole route but their next signal seems stuck and won't "pull off" from danger - he blames the engineers of course. In accordance with regulations the train's driver phones the signaller, signaller explains that he can't release the signal but gives the driver authoriation, per standard instructions, to pass only one signal and proceed at caution (ie slowly enough to stop short of any obstruction) to the next signal. The next signal though is the same, the signaller is annoyed, blames the engineers again, same order to proceed at caution. The next signal is the same again. But, just after the driver receives their authority and passes that signal the signaller gets another call. Funny, surely they haven't reached the next signal yet? No. They're face-to-face with another train. Some junction points ("switch" if you're American) have failed, the train has been sent into another, both stopped short and nobody is injured.
The points failure had been detected. If the signaller had carefully checked his instruments they'd have told him that this failure had occurred and that is why it wasn't clear to set those danger signals off which is why, try as hard as he could, they could not be pulled off. It is mechanically impossible, not because of professionalism, or capability or any other brave words but physically impossible to kill everybody by clearing the conflicting signals in this state.
Creating a language which is difficult to use and dangerous is not “lending humanity to the developer”. Humans make mistakes, and a language that doesn't account for this is ignoring the humanity of its users.
>> Much of Zig seems to me like "wishful thinking"; if every programmer was 150% smarter and more capable, perhaps it would work.
... 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.
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.
> 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
So if Rust is preferable to ATS because more people are productive with it despite ATS being able to guarantee more at compile-time, then by that logic a language that more people would be productive with than with Rust, despite Rust guaranteeing more at compile time, would be preferable to Rust.
You see, the problem is that these arguments cannot lead us to an objective preference unless we compared Rust to all other points on the spectrum, especially since Rust proponents already must accept that the best point is not on any extreme. So we know that languages that guarantee more than C but more productive than ATS are preferable. Guess what? Zig is right there, too, so that argument can't be used to prefer Rust over Zig.
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.
It's actually hard to find any language that has ever very popular (JS, TS, Python, Java, C++, C#, C, and you can even throw in PHP, Ruby, Go, Kotlin, and even COBOL and Fortran) that has such a low adoption rate at age 10. I'm not saying that means Rust won't buck the historical trend and achieve that, but its adoption clearly does not resemble that of any language that's ever become very popular.
I have admired many parts of Zig and its philosophy but I've never seen it as a language that I want to use. What I've noticed is that Zig users care most about explicitness, simplicity, and minimal indirection. This leads to a lot of syntax that is cumbersome to read (albeit unambiguous) like casting and a lack of "convenience" features. I can't help but think that maybe they're right and that this philosophy probably leads to better software because nothing is "hidden". But, I also think that there's a level of abstraction/indirection that makes code clearer and less error-prone. It's a tricky balance to achieve, and past languages have succeeded and failed at it to different degrees. Either way, I echo the OP's sentiment: if Zig is your jam, great, go make some awesome stuff with it. It's just not my go-to today.
Design choices that are appropriate for low-level programming may be less appropriate for high-level programming and vice versa. In low level programming, you may want to see "on the page" anything that could translate to some machine work, because in low-level programming, such details may be essential to the algorithm. In high-level programming, the same details are likely not essential to the algorithm, and so you don't want to see them.
What’s the opposite of damning with faint praise? “Removes many but not all of the C footguns. Self hosted compiler isn’t that much faster than Clang.”
The authors section on comptime makes me believe they have not used zig anything non trivial.
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.
I find a lot of these points persuasive (and I’m a big Rust fan so I haven’t spent much time with Zig myself because of the memory safety point), but I’m a little skeptical about the bug report analysis. I could buy the argument that Zig is more likely to lead to crashy code, but the numbers presented don’t account for the possibility that the relative proportions of bug “flavors” might shift as a project matures. I’d be more persuaded on the reliability point if it were comparing the “crash density” of bug reports at comparable points in those project’s lifetimes.
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.
The author refers to casting ints to floats but seems to actually be talking about converting. Casting is when you change the type, but don't change the data..
I don't really think much of Zig myself for other reasons, but comptime seems like a good design.
> Casting is when you change the type, but don't change the data..
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++.
Interest on various topics comes in waves on HN. This week it's Zig, next week it's Scheme, the week after is Erlang, etc. Nothing out of the ordinary.
Programming languages in general go through hype waves here; back in the mid 2000s it was some combination of Lisp -> Ruby -> JS with bits of Erlang in and around those.
I think there's a small trend upwards for Zig & Nim right now. I've seen a few different front page posts for them in the last couple weeks. It at least convinced me to clone ziglings and get a feel for it this last weekend.
There's bursts of them and every 3-6 months I see one like this, more practical, and remember I don't need to read the others. Then I forget in 3 months. Rinse, lather, repeat. (to this 16 year veteran of HN, it reminds of early 2010s Haskell)
> One extra register is all you ever need, even for an arbitrary parallel move!
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.
probably should define memory safety before using it as an evaluation criterion
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
I can see where you're coming from, but I do think there's a fair amount of meat here. I've never used Zig, but I initially thought of it as pretty similar to other modern languages like Go and Rust, and I liked their allocator approach, but the post gives compelling statistics (Bun has almost EIGHT times as many crash issues as Deno over a similar number of tickets) on Zig's memory safety approach and its issues that also line up with my experience. I used Bun for a small data-collection project, and I liked its performance, but I ran into a lot of issues with it segfaulting (even when just passing a command line argument that was added in the most recent version!). I think that does a good job of motivating OP's argument and how Zig's language semantics directly contribute to these issues.
Someone could know what memory safety is and still be persuaded (or reminded) by an argument that it's not okay to adopt a non-memory-safe language due to all the security issues. The author did cite evidence from the Chromium project, which to me elevates it above a mere rant.
It's interesting how much Rust has slowed down. There is still some development in linux otherwise people seem to be over it. I think Rust just doesn't offer enough in terms of features, and is overshadowed by languages like Go or C++ in terms of what developers are really looking for. Rust's popularity seems to be dropping or holding steady in indexes like TIOBE, and a lot of big "influencers" seem to be over Rust's hype cycle
> Rust's popularity seems to be dropping or holding steady in indexes like TIOBE, and a lot of big "influencers" seem to be over Rust's hype cycle
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).
There appears to be a lot of noise in the Tiobe already. What does it mean if Visual Basic is shooting up and C is near the top? They are surely in no way measuring the same programming market -- so who cares?
I find the point about memory safety to be pretty damning.
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 article works really well to illustrate a question I have: why is Zig so popular in posts here?
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.
Ok, that makes sense. So it’s a modern take on low level languages, like rust, but for those that dislike c for being cumbersome rather than for being less secure?
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.
For me, personally, it is nice because it's bare metal where I want it and not bare metal when I don't.
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 :))
I think the post gives an answer to this with "due to Zig's fairly minimalistic nature; it lacks a lot of features that one would otherwise use to solve problems. Of course, this is the appeal for many, but still". I have a lot of C/C++ experience, and they're what I reach for, but I often want C to be a little more like C++, and I often want both to have slightly better memory management, and I've never liked the different syntax for the main language, templates, and pre compiler macros. I also agree with Zig's dogmatic stance on no hidden control flow; I have been bitten by "magic" too many times.
Some people like Zig because it makes it easier to learn how to program the machine sitting in front of them.
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.
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.
> As a small example wrt Rust: resetting an arraylist/vector while reusing its memory is a weirdly complicated trick
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.
Low abstraction overhead and no ‘big ideas’. It tries to simplify the problem of low-level systems programming by learning from the lessons of the past 50 years.
A lot of people strive for something that is simple (not like Rust, and I am not only talking about the borrow checker) and explicit ("debug your program, not your knowledge of the language) but also doesn't bear the historical cruft and idiosyncrasies of C. The fact that it can integrate with C code means that if you are already using C you can adopt it incrementally, plus it works as a build system and cross-compiler and I believe a package manager too.
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 ?
I'm a casual fan of Zig for hobby development, so just as a data point:
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.
Turns out that "killer features" are frequently not killer enough. You mentioned Rust with its memory-safety killer-feature, and yet Rust is quite old now (about as old as Java was when JDK 6 came out or JS was when jQuery came out) and its adoption rate is low for such an old age.
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.
That falls into "spatial" memory safety, which Zig also provides. Rust's ownership and lifetime - the core of its design - go into eliminating use-after-free, aka "temporal" memory safety.
With all the hn hype around zig I ended up going through the docs and some example code and felt the same way. I'm not totally sure where this fits into my tool box of languages.
It doesn't seem bad, (though with some of rewrite of the std library? It doesn't seem quite ready) Im just not sure when I'll reach for it. I guess I'm comfortable enough with rust and both seem like languages that compile with llvm. Maybe if I didn't know rust it would feel like more useful.
> Zig does not have a way to iterate through a slice or similar in any way except one-at-a-time forwards. Anything else? You're using a while loop, and you'll enjoy it.
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.
This treatment of memory safety is becoming almost a cargo cult at this point. If this were a binary issue, then clearly Rust wouldn't cut it because it is quite common in Rust (much more so than in, say, Java) to rely on unsafe code. So if you think Rust is good at memory safety, that means that you must believe that some level of unsafety is acceptable. The only question is how much, and what you're willing to pay to reduce it.
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.
Limiting to the "top 5" vulnerabilities by number of CVEs feels like cherry-picking. It's true that spatial memory safety is lower-hanging fruit than temporal memory safety, sure; but the CVE list is dominated by vulnerabilities in web applications which are mostly already written in fully memory-safe languages (additionally, these vulnerabilities are typically mitigated by library/API design rather than by programming language design, in which case Rust gives you quite a lot more tools than Zig for designing APIs that have concepts of unsanitized/untrusted data, but I digress). If you filter for vulnerabilities relevant to applications that would typically be written in C/C++/Rust/Zig, use-after-free is easily within the top 5.
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.
> Zig must also be good for eliminating the same ones.
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.
I agree! Memory safety is important because it's the cause of some of the top vulnerabilities, which is precisely why it's great that both Rust's level of memory safety (which is not absolute) and Zig's level of memory safety (also not absolute), both eliminate those top weaknesses!
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.
> Zig's comptime is a very large and all-encompassing feature that ultimately brings very little to the table that smaller features cannot.
> 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.
> But I oppositely believe the world needs more tech that treats professionals as experts, not kids.
Which part of expertise is rejecting the fact that safety through professional mind tricks in lieu of better underlying language design is unattainable?
> 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??
When I was much dumber, I thought I was much smarter. Now that I'm smarter, I realize that I'm often quite dumb.
> But then some of us learned that no matter how smart we are, we can make mistakes that those things can actually prevent.
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.
Zig is a tool that helps professionals prevent those mistakes.
"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.
It's not that subtle, the thing that we knew doesn't work still doesn't work.
Some of our problems are novelties because before Grace Hopper basically nobody is writing software so there aren't centuries of lessons in how to do it properly - but this problem isn't like that, all the safety critical industries could tell you that "professionalism" won't prevent the mistakes and what you need is mechanism so that the mistakes cannot happen.
Let me give you an example I like from the railways, which are about twice as old. One night, signaller comes on duty and during the day a team of engineers have been doing work on "his" signal box. Still, things seem to check out and he gets to work, a train approaches, he tries to give them their whole route but their next signal seems stuck and won't "pull off" from danger - he blames the engineers of course. In accordance with regulations the train's driver phones the signaller, signaller explains that he can't release the signal but gives the driver authoriation, per standard instructions, to pass only one signal and proceed at caution (ie slowly enough to stop short of any obstruction) to the next signal. The next signal though is the same, the signaller is annoyed, blames the engineers again, same order to proceed at caution. The next signal is the same again. But, just after the driver receives their authority and passes that signal the signaller gets another call. Funny, surely they haven't reached the next signal yet? No. They're face-to-face with another train. Some junction points ("switch" if you're American) have failed, the train has been sent into another, both stopped short and nobody is injured.
The points failure had been detected. If the signaller had carefully checked his instruments they'd have told him that this failure had occurred and that is why it wasn't clear to set those danger signals off which is why, try as hard as he could, they could not be pulled off. It is mechanically impossible, not because of professionalism, or capability or any other brave words but physically impossible to kill everybody by clearing the conflicting signals in this state.
Mechanism.
Creating a language which is difficult to use and dangerous is not “lending humanity to the developer”. Humans make mistakes, and a language that doesn't account for this is ignoring the humanity of its users.
>> Much of Zig seems to me like "wishful thinking"; if every programmer was 150% smarter and more capable, perhaps it would work.
... 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.
> Why not ATS?
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.
> 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
So if Rust is preferable to ATS because more people are productive with it despite ATS being able to guarantee more at compile-time, then by that logic a language that more people would be productive with than with Rust, despite Rust guaranteeing more at compile time, would be preferable to Rust.
You see, the problem is that these arguments cannot lead us to an objective preference unless we compared Rust to all other points on the spectrum, especially since Rust proponents already must accept that the best point is not on any extreme. So we know that languages that guarantee more than C but more productive than ATS are preferable. Guess what? Zig is right there, too, so that argument can't be used to prefer Rust over Zig.
> a relatively advanced age.
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.
It's actually hard to find any language that has ever very popular (JS, TS, Python, Java, C++, C#, C, and you can even throw in PHP, Ruby, Go, Kotlin, and even COBOL and Fortran) that has such a low adoption rate at age 10. I'm not saying that means Rust won't buck the historical trend and achieve that, but its adoption clearly does not resemble that of any language that's ever become very popular.
> But I oppositely believe the world needs more tech that treats professionals as experts, not kids.
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.
I have admired many parts of Zig and its philosophy but I've never seen it as a language that I want to use. What I've noticed is that Zig users care most about explicitness, simplicity, and minimal indirection. This leads to a lot of syntax that is cumbersome to read (albeit unambiguous) like casting and a lack of "convenience" features. I can't help but think that maybe they're right and that this philosophy probably leads to better software because nothing is "hidden". But, I also think that there's a level of abstraction/indirection that makes code clearer and less error-prone. It's a tricky balance to achieve, and past languages have succeeded and failed at it to different degrees. Either way, I echo the OP's sentiment: if Zig is your jam, great, go make some awesome stuff with it. It's just not my go-to today.
Design choices that are appropriate for low-level programming may be less appropriate for high-level programming and vice versa. In low level programming, you may want to see "on the page" anything that could translate to some machine work, because in low-level programming, such details may be essential to the algorithm. In high-level programming, the same details are likely not essential to the algorithm, and so you don't want to see them.
What’s the opposite of damning with faint praise? “Removes many but not all of the C footguns. Self hosted compiler isn’t that much faster than Clang.”
[delayed]
The authors section on comptime makes me believe they have not used zig anything non trivial.
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.
> X is first class and thus Y [implemented in terms of X] is too.
Is everything first class, then?
In theory it can encode 0 and 1 so anything really, right?
I would argue C preprocessor macros are not first class. They are optional.
This anything implements with macros are not first class
I find a lot of these points persuasive (and I’m a big Rust fan so I haven’t spent much time with Zig myself because of the memory safety point), but I’m a little skeptical about the bug report analysis. I could buy the argument that Zig is more likely to lead to crashy code, but the numbers presented don’t account for the possibility that the relative proportions of bug “flavors” might shift as a project matures. I’d be more persuaded on the reliability point if it were comparing the “crash density” of bug reports at comparable points in those project’s lifetimes.
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.
The author refers to casting ints to floats but seems to actually be talking about converting. Casting is when you change the type, but don't change the data..
I don't really think much of Zig myself for other reasons, but comptime seems like a good design.
> Casting is when you change the type, but don't change the data..
Is that the case? That's not what I think of when I think of C-style casts.
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++.
Casting and type conversion are synonyms: https://en.wikipedia.org/wiki/Type_conversion
Why have I been seeing a Zig post every day for the past week? Is there some kind of a marketing push?
Interest on various topics comes in waves on HN. This week it's Zig, next week it's Scheme, the week after is Erlang, etc. Nothing out of the ordinary.
Programming languages in general go through hype waves here; back in the mid 2000s it was some combination of Lisp -> Ruby -> JS with bits of Erlang in and around those.
I think there's a small trend upwards for Zig & Nim right now. I've seen a few different front page posts for them in the last couple weeks. It at least convinced me to clone ziglings and get a feel for it this last weekend.
still less than Rust posts.
There's bursts of them and every 3-6 months I see one like this, more practical, and remember I don't need to read the others. Then I forget in 3 months. Rinse, lather, repeat. (to this 16 year veteran of HN, it reminds of early 2010s Haskell)
What about more people using it? More than anything this looks to be natural evolution of language.
> One extra register is all you ever need, even for an arbitrary parallel move!
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.
[0] https://inria.hal.science/inria-00289709
probably should define memory safety before using it as an evaluation criterion
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
I can see where you're coming from, but I do think there's a fair amount of meat here. I've never used Zig, but I initially thought of it as pretty similar to other modern languages like Go and Rust, and I liked their allocator approach, but the post gives compelling statistics (Bun has almost EIGHT times as many crash issues as Deno over a similar number of tickets) on Zig's memory safety approach and its issues that also line up with my experience. I used Bun for a small data-collection project, and I liked its performance, but I ran into a lot of issues with it segfaulting (even when just passing a command line argument that was added in the most recent version!). I think that does a good job of motivating OP's argument and how Zig's language semantics directly contribute to these issues.
Someone could know what memory safety is and still be persuaded (or reminded) by an argument that it's not okay to adopt a non-memory-safe language due to all the security issues. The author did cite evidence from the Chromium project, which to me elevates it above a mere rant.
my point with memory safety is that it is not a single well defined concept
so if you wanna talk about it you at least gotta say which definition you're using
It's interesting to see how popular Zig is becoming, I thought it would get overshadowed by Rust and it would go nowhere.
It's interesting how much Rust has slowed down. There is still some development in linux otherwise people seem to be over it. I think Rust just doesn't offer enough in terms of features, and is overshadowed by languages like Go or C++ in terms of what developers are really looking for. Rust's popularity seems to be dropping or holding steady in indexes like TIOBE, and a lot of big "influencers" seem to be over Rust's hype cycle
> Rust's popularity seems to be dropping or holding steady in indexes like TIOBE, and a lot of big "influencers" seem to be over Rust's hype cycle
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).
Rust has been adopted by Microsoft, Amazon, etc. It's past the hype phase and well into the "languages people use for work and complain about" phase.
I still like it -- for systems programming, that is. It's a much better C++ basically.
> Rust's popularity seems to be dropping or holding steady in indexes like TIOBE
Oh, 14th [1]. That's a lot lower than I would have expected, based purely on the amount of noise surrounding Rust.
[1] https://www.tiobe.com/tiobe-index/
There appears to be a lot of noise in the Tiobe already. What does it mean if Visual Basic is shooting up and C is near the top? They are surely in no way measuring the same programming market -- so who cares?
> It's interesting how much Rust has slowed down
Rust has a SDK from the 3 big cloud providers, Rust IS mainstream.
But they are not even competitors.
Zig is a better C. No abstractions. Close to bare metal.
Rust is a better C++. Abstractions to simplify application level programming.
I find the point about memory safety to be pretty damning.
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 article works really well to illustrate a question I have: why is Zig so popular in posts here?
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).
> for Ruby is ergonomics…
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.
Ok, that makes sense. So it’s a modern take on low level languages, like rust, but for those that dislike c for being cumbersome rather than for being less secure?
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.
For me, personally, it is nice because it's bare metal where I want it and not bare metal when I don't.
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 :))
I think the post gives an answer to this with "due to Zig's fairly minimalistic nature; it lacks a lot of features that one would otherwise use to solve problems. Of course, this is the appeal for many, but still". I have a lot of C/C++ experience, and they're what I reach for, but I often want C to be a little more like C++, and I often want both to have slightly better memory management, and I've never liked the different syntax for the main language, templates, and pre compiler macros. I also agree with Zig's dogmatic stance on no hidden control flow; I have been bitten by "magic" too many times.
Some people like Zig because it makes it easier to learn how to program the machine sitting in front of them.
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.
> As a small example wrt Rust: resetting an arraylist/vector while reusing its memory is a weirdly complicated trick
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.
> 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...
Nitpicking? Let’s show an example on creating an interface in Zig to see all complicated tricks.
Low abstraction overhead and no ‘big ideas’. It tries to simplify the problem of low-level systems programming by learning from the lessons of the past 50 years.
A lot of people strive for something that is simple (not like Rust, and I am not only talking about the borrow checker) and explicit ("debug your program, not your knowledge of the language) but also doesn't bear the historical cruft and idiosyncrasies of C. The fact that it can integrate with C code means that if you are already using C you can adopt it incrementally, plus it works as a build system and cross-compiler and I believe a package manager too.
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 ?
I'm a casual fan of Zig for hobby development, so just as a data point:
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.
Turns out that "killer features" are frequently not killer enough. You mentioned Rust with its memory-safety killer-feature, and yet Rust is quite old now (about as old as Java was when JDK 6 came out or JS was when jQuery came out) and its adoption rate is low for such an old age.
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
> Rust spends almost all of its complexity on eliminating weaknesses that don't even make the top 5 in either list
Uh? Number 2 in CWE is an out-of-bounds write, and the same vulnerability is number 1 in the KEV list.
That falls into "spatial" memory safety, which Zig also provides. Rust's ownership and lifetime - the core of its design - go into eliminating use-after-free, aka "temporal" memory safety.
Zig for me is “C with namespaces”. Other selling points are just complimentary.
> for Ruby is ergonomics…
In other words, "I kinda enjoy it"?
With all the hn hype around zig I ended up going through the docs and some example code and felt the same way. I'm not totally sure where this fits into my tool box of languages.
When I first heard about zig, I sat down and read the entire doc from start to end. It was so refreshing and was an instant fan
It doesn't seem bad, (though with some of rewrite of the std library? It doesn't seem quite ready) Im just not sure when I'll reach for it. I guess I'm comfortable enough with rust and both seem like languages that compile with llvm. Maybe if I didn't know rust it would feel like more useful.
> Zig does not have a way to iterate through a slice or similar in any way except one-at-a-time forwards. Anything else? You're using a while loop, and you'll enjoy it.
Although actual BLISS-77 had inclusive semantics for the upper bounds in both forms. Which, on one hand, allows you to write 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.That looks a lot like Common Lisp LOOP macro!
Honestly, that's been the standard form of FOR loops since Fortran and Algol-60 until C decided to spice things up.
That may be, but I was born only 40-something years ago, so I haven't had the pleasure to see that other than in Lisp.
This treatment of memory safety is becoming almost a cargo cult at this point. If this were a binary issue, then clearly Rust wouldn't cut it because it is quite common in Rust (much more so than in, say, Java) to rely on unsafe code. So if you think Rust is good at memory safety, that means that you must believe that some level of unsafety is acceptable. The only question is how much, and what you're willing to pay to reduce it.
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
Limiting to the "top 5" vulnerabilities by number of CVEs feels like cherry-picking. It's true that spatial memory safety is lower-hanging fruit than temporal memory safety, sure; but the CVE list is dominated by vulnerabilities in web applications which are mostly already written in fully memory-safe languages (additionally, these vulnerabilities are typically mitigated by library/API design rather than by programming language design, in which case Rust gives you quite a lot more tools than Zig for designing APIs that have concepts of unsanitized/untrusted data, but I digress). If you filter for vulnerabilities relevant to applications that would typically be written in C/C++/Rust/Zig, use-after-free is easily within the top 5.
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.
> Zig must also be good for eliminating the same ones.
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.
There's no magic wand that can make memory safety unimportant, even doing other important things.
I agree! Memory safety is important because it's the cause of some of the top vulnerabilities, which is precisely why it's great that both Rust's level of memory safety (which is not absolute) and Zig's level of memory safety (also not absolute), both eliminate those top weaknesses!
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.