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.
I think, but I may be wrong, Zig wants to be high level assembly that could replace C. If people are viewing it from Python, Ruby, JS, and then C++ and Java POV, Zig may be a little too "raw". But then I don't think Zig intends to compete with C++ or Java. May be there will be a Zig ++ or Objective-Zig someday that will do that.
It really comes down to a matter of opinion where the line between "nothing hidden" and convenience lies. Technically, a loop is an abstraction of convenience that hides the comparative jump underneath.
> 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.
> 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.
Zig is famously simple to pick up and write with, so I don't know what you mean by "difficult". Software is dangerous. Memory safety is one of a million ways it can be dangerous. A compiler barfing when it thinks you are doing something unsafe with pointers is one approach to dealing with one of the ways that code can be dangerous to execute.
Zig does not ignore that particular danger, it just takes a different approach to dealing with it than some other modern languages. An approach that, I believe, leaves the developer with a little more humanity by allowing them the benefit of the doubt that they know what they are doing.
Everyone that has not built a systems language, or has not built a real application with both Zig and a memory safe language, that is reacting emotionally to what I've said should put a lot of consideration into whether they are cargo culting or using critical thought. Consider that we still do not yet know what is best, and shutting down attempts to explore different ideas with things like "creating [and using] this language is ignoring the humanity of the end user" is, well.. dumb.
I have never heard anyone calling Zig "famously simple" before. In fact, people tend to say it has quite the learning curve.
Of course, caveats apply: it is certainly simple compared to some languages, but certainly not compared to others. "Famously simple" seems to indicate it is one of the simplest languages to learn, which seems wrong unless there are some serious qualifications to that statement?
C, C++, Rust, Zig. Rust and C++ have an infamous learning curve. If you know anything about using any systems language other than Zig, Zig is incredibly simple to pick up, like C. Unlike C, it pushes you toward making less mistakes.
If you don't know anything about using a systems language, Zig makes it easier for the people who do to review your code and make sure you didn't mess it up. It does this with very intentional design that makes it easier to understand the full impact of code quickly, reducing the cost of review, making review practical to catch the issues. It also has many other fail safes to catch these problems before they ever reach a production release.
So, yeah, it's totally depending on where you are coming from -- but Zig is not a tool built for a web developer who doesn't know anything about memory to go and ship an application within their first week. It does make it easier for that person to learn the ropes at a steady pace.
Meanwhile, everyone complaining that Zig is not memory safe doesn't seem to care that applications written in Zig do not have the vulnerabilities that memory safety solves on the scale that C does[0].
If you have not written a real application in Zig and evaluated it for vulnerabilities, but are claiming that creating Zig was irresponsible, and using it is too; you are cargo culting.
If you have, you probably understand there is a niche that Zig fits in and that it isn't surprising it exists to fill it. Like all things in our industry, there is a cost/benefit analysis required for choosing the tools you build with.
No one reasonable has claimed that memory safe languages should not exist, but there is a maddening number of people being disrespectful toward those who think there are other ways of addressing the same problems.
If you are comparing Zig to Rust and C++, which are very well known to be difficult to learn, then that is not really saying anything about the ease of learning it. Compare it to Swift, D or Odin. Is it "incredibly simple" compared to those languages as well?
Similarly, one can claim that pretty much anything compiles "incredibly fast" if one compares with Rust, C++ and Swift.
But comparing to worst in class doesn't actually say anything.
One note about this:
> If you have not written a real application in Zig and evaluated it for vulnerabilities, but are claiming that creating Zig was irresponsible, and using it is too; you are cargo culting.
I don't know what this has to do with my comments at all, but I want to point out that you are using "cargo culting" wrong. This describes imitating practices of something successful, thinking that by this imitation, success will follow as well.
> No one reasonable has claimed that memory safe languages should not exist,
Again, I have not talked anything about whether memory safe languages should or should not exist. You are confusing me with someone else.
>Zig is famously simple to pick up and write with, so I don't know what you mean by "difficult".
It's easy to get in a car and put your foot on the pedal, but usage entails not crashing.
>Memory safety is one of a million ways it can be dangerous.
We have the statistics on this. It is 7 out of 10 ways it is dangerous, going by proportion of CVEs, so it's likely higher in less well tested software. Your estimation was off by 5 orders of magnitude.
>leaves the developer with a little more humanity
I could care less if the developer is afforded humanity. I want to write software and I want a programming language that helps me to do that. Whatever humanity I'm sacrificing by writing in memory safe languages is more than made up for by the comparative ease of not having to worry about memory safety.
>reacting emotionally
You are reacting emotionally. You are judging programming languages by their emotional value rather than their features. “Humanity” is not a measurable feature. 70% fewer CVEs is a measurable feature.
> 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?
> But I oppositely believe the world needs more tech that treats professionals as experts, not kids.
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.
> But I oppositely believe the world needs more tech that treats professionals as experts, not kids.
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."
>> 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.
> ... 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.
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.
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.
Sure, that makes sense. I agree this is all very subjective, given we don't have the benefit of hindsight for what Zig can accomplish yet.
I think where we disagree is that you believe Zig is as safe as Rust (by making it easier to make other things safer). I don't believe so (my first impression of Zig was Bun repeatedly segfaulting), and I'm just sad that people are choosing the easy route and going for more insecure software, when it finally looked like we made such great progress, with a language people can actually use. I agree with simpler, but there's so many other things that can be changed or removed from Rust, and still leave in lifetimes, or something similar.
> I think where we disagree is that you believe Zig is as safe as Rust
Quite the opposite. Rust is definitely safer in the simple sense that it guarantees more memory safety. But that's very different from saying that Zig is closer to C than to Rust (Zig's memory safety is much closer to Rust's than to C's), and it also doesn't mean that it's easier to write more correct/secure software in Rust (because there are just too many factors).
> and I'm just sad that people are choosing the easy route and going for more insecure software
The jump from "segfaulting" to "insecure" is unjustified, as not all causes of segfaults map to equally exploitable vulnerabilities. Java programs, for example, segfault much less than Rust programs. Does that mean Rust programs are significantly less secure?
> Zig's memory safety is much closer to Rust's than to C's
This is arguable. Zig's issues with memory safety are not limited to such things as use-after-free ("temporal" memory safety in a rather obvious sense). Without something very much like Rust's borrow checker and affine types, you can't feasibly prevent a program from inadvertently e.g. stashing a pointer somewhwere to an inner feld of a tagged union, and reusing that pointer later even though the union itself may have mutated to a different tag, which results in undetected type punning and potentially wild pointers. The issue of iterators to a collection being invalidated by mutation is quite similar in spirit, and again has nothing to do with the heap per se. Rust prevents these issues across the board. The fact that it also manages to prevent temporal memory unsafety altogether is simply a bonus that essentially comes "for free" given the borrow checking approach.
That's not arguable. Because if we say that memory safety is important because it prevents some common and dangerous vulnerabilities, then Zig clearly prevents the most dangerous of those, while C doesn't.
> you can't prevent a program from inadvertently...
Now you're naming more problems that aren't as high on the list as the ones Zig does prevent (and C doesn't). It's true that type confusion is also rather high on the list, but Zig clearly reduces type confusion much more than C does.
Nobody denies that Rust prevents more issues than Zig via sound guarantees - albeit at what I think is a significant cost, and we can argue, subjectively, over whether those issues are worth that cost or not - but Zig's guarantees are still closer to Rust's than to C's if eliminating very common/dangerous vulnerabilities is what we're judging by.
The underlying issue is that Zig turns out to have no feasible safe subset, just like C - unless you go as far as to declare things like using tagged unions in combination with pointers "unsafe" which is both insanely restrictive and hard to check programmatically. People might complain about having to fight the borrow checker, but they'd complain a whole lot more if the standard approach to safety-subsetting a language was just bounds-checked array access plus "you can write FORTRAN in any language!"
> The underlying issue is that Zig turns out to have no feasible safe subset
It does have a safe subset with respect to spatial memory safety, which is the more important kind of memory safety if what we judge by is dangerous vulnerabilities.
> People might complain about having to fight the borrow checker, but they would complain a lot more if the standard approach to safety-subsetting a language was just bounds-checked array access plus "you can write FORTRAN in any language!"
I don't know how you can say that this is an objectively-supported claim given Rust's poor adoption at its age.
Rust's real superpower is its tooling. Cargo handles package management, building, testing, documentation, and publishing. The compiler's errors explain what went wrong and where it happened. Installing the toolchain with rustup is quick and painless, even on Windows. I can't know that it's best in class, but it's certainly the best I've used.
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.
Rust is much older than Zig, though, and there's nothing stopping Zig (or any future language that doesn't adopt Rust's precise set of guarantees) from having the same, or possibly better. Given Zig's immaturity, I certainly wouldn't use it for any serious production software today.
BTW, I'm not saying Rust is bad. All I'm saying is that the attempt at proving it's objectively best by leaning on memory-safety is not really as objective as the people who make that claim seem to think it is.
I hadn't heard of ATS before, and I think that I mistook your using it as an example of "more isn't always better" and thought you were suggesting it as an actual alternative.
I'm looking for the next thing I want to learn, and have been leaning towards logic programming and theorem provers, so you inadvertently piqued my interest.
> ... 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.
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.
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'm curious, do you have figures for this? I was not around when C or C++ were 10, but I was when python was and as a long time python user I would say that the pycommunity was much smaller at 10 then the rust community at 10. So my gut feeling is that your statement is false at least wrt python, but I'm happy to change my mind if you have sound data.
Edit: just to add some more anecdotal evidence from my memory of languages I used: java community was pretty bigger than rust at 10. Go's was much smaller than rust at 10. I'd be happy to check my beliefs against actual data :)
I wasn't programming yet when C was 10 years old, but I was when C++ was 10 years old (1995), and its adoption was an order of magnitude higher than Rust's is today.
I agree that of all popular languages, Python is the latest bloomer, but while it became popular for applications and data processing rather late, it was used a lot for scripting well before then.
> Go's was much smaller than rust at 10
Go turned 10 (if we want to count from 1.0) only 3 years ago, and Go's adoption in 2022 was much bigger than Rust's today.
I don’t have a dog in this race but I was also around at that time and one reason is there was far less choice in 1995 about where you would go from C. C++ was also a vastly simpler language back then (no templates, no exceptions, barely a few hundred command line options). So I am not sure what its adoption then can teach us about language adoption now.
I don't think it's true there was far less choice in 1995. Around that time (a few years later) I was working on a project that was half Ada half C++, and there were a few more exotic choices around. Aside from those, and C, there were still projects in the company back then written in Fortran and even in Jovial. At university, I learnt Esterel for formally-verified embedded software. And that's not even touching on the higher level space, where VB, Delphi, some Smalltalk, and a large selection of other "RAD tools" were being used (my first summer job was on what today would be called an ERP system written in a language called Business Basic). At university, the language I was taught at intro to compsi was Scheme (that was also the embedded-scrpting language we used at work). We were also taught ML and a bit of Haskell.
It's true that not many languages that seemed a reasonable choice at the time survived to this day as reasonable choices.
Typescript is a tool more than a language, so that's not fair at all.
And the rest of those basically had no competition in their domain when they started 30+ years ago. Rust now has to grow next to 30 years of those languages maturing, and convince people to abandon all existing community resources - whereas those languages did not.
Having a low adoption rate is normal in this day and age. Go is kind of an anomaly caused by it's backing by Google.
But it doesn't help that Rust is also in the native space, whose devs are especially stubborn, and is a difficult language with painful syntax.
I dunno, I think you're trying to split hairs if top 20 isn't "very popular".
But I don't think the comparison you're trying to make works, because then isn't now.
In general, in order to convince someone to leave their current tools, you have to not only be better but a lot better. As in, you need to offer the entire feature set of the old tool plus something else compelling enough to overcome the network effects (ecosystem + years of experience + job prospects) of the prior environment.
So when C++ came on the scene, they had to compete against ~20 years of accumulated legacy systems and language history. Rust had to compete with 50 years of legacy systems and language history.
Moreover, developer expectations are a lot different today. Back then, C++ was what, a compiler and some docs? Python was an interpreter and some docs? Maybe an IRC channel? Today, it's not enough to reach 1.0, you also have to deliver a package manager, robust 3rd party library ecosystem, language server tooling, a robust community with support for new devs, etc. So timescales for language development are getting longer than they were back then.
Also, I don't know why you've chosen "very popular" as a metric. Very popular isn't something a language needs to be, it just needs to be big enough to sustain a community. Being top 20 within 10 years is certainly in that realm. You can see that other language communities have existed for longer and are much smaller. And anyway, the entire developer population today is much larger than it was back then; you can have a small percentage of all developers but still large enough to be robust. I don't know the math, maybe someone can figure it out, but I wouldn't be surprised if 1% of developers today is inflation adjusted to like 10%-20% of developers in 1996. So Rust is probably as big as it needs to be to sustain itself, it doesn't have to be a "very popular" language if that means being in the top 5 or whatever the threshold is.
> In general, in order to convince someone to leave their current tools, you have to not only be better but a lot better.
I agree.
> So when C++ came on the scene, they had to compete against ~20 years of accumulated legacy systems and language history. Rust had to compete with 50 years of legacy systems and language history.
Ok, but Go and TypeScript are pretty much the same age, and when Java came out, it took over much of C++'s market very quickly.
I agree Rust has some clear benefits over C++, but it also has intrinsic challenges that go well beyond mere industry momentum (and other languages have shown that momentum is very much defeatable).
> Moreover, developer expectations are a lot different today.
But there are more programmers today, and many more people worked on Rust than on C++ in its early years. And besides, Rust has had all those things you mentioned for quite some time, and C++ still doesn't have some of them.
> Also, I don't know why you've chosen "very popular" as a metric. Very popular isn't something a language needs to be, it just needs to be big enough to sustain a community.
I agree it doesn't need to be very popular to survive. But popularity is a measure of the actual benefit a language brings or, at least, lack of popularity is a measure of lack of sufficient benefit, because software is a competitive business. So claims that Rust is some huge game-changer don't really square with its rate of adoption.
> I agree it doesn't need to be very popular to survive. But...
I think that's the end of it then, yeah? We've established it's popular enough (you set a lower bound at Haskell, which has been around for 35 years, has an active and vibrant community, and is still used in industry), we agree it doesn't need to be more popular, so then this threshold of "very popular" you invented (which I guess is the top 10) is arbitrary and therefore not relevent.
> Ok, but Go and TypeScript are pretty much the same age, and when Java came out, it took over much of C++'s market very quickly.
These two languages were created and pushed by two of the largest corporations on the planet. Typescript is basically Javascript++, and it came at a time when Javascript was to a large degree the only language for the browser. So they had: 1) one of the largest corporations in the world backing it with effectively unlimited money as part of a larger campaign to win web developer mindshare 2) a large developer base of people who already spoke the language 3) guaranteed job opportunities (at least at Microsoft, so more quickly followed) for people who invested in it. Microsoft was also instrumental in defining the platform on which Typescript ran, so they had that benefit as well. That's one way to achieve success for a language, but it requires only offering a very small delta in features; Typescript could only do what it did by being Javascript + types.
Likewise with Go, they bootstrapped that community with Googlers. Bootstrapping a community is way harder than bootstrapping a language, so having a built-in community is quite an advantage. People wanted to learn Go just to have it on their resume, because they heard it would help them land a job there. Plenty of my students took that route. Google threw their weight around where they could for Go, even going as far as to steal the name right out from another language developer and telling him to pound sand when he complained about it.
I mean, Google could afford to hire Robert Griesemer, Rob Pike, AND Ken Thompson to create Go; whereas Rust came from the side project of a lowly Mozilla software engineer. We're looking at two very different levels of investment in these respective languages.
This seems to me like cherry picking. You're taking the best-case scenarios and then comparing it to something not like that at all. When it pales in comparison, you conclude it's not sufficient. But here's the thing: if we want programming as a field to evolve, not every new language can be ExistingLang++. Some languages are going to have to take big swings, and they're not going to be as popular as the easy road (big swings mean big divisions and polarized views; Javascript + types is an easy and agreeable idea). That doesn't mean they aren't just as if not more beneficial to programming languages as a field.
> But there are more programmers today, and many more people worked on Rust than on C++ in its early years.
Yes, and that completely muddles your point, which is why these comparisons don't make sense. It's like comparing the success of a new NFL team to teams from 50 years ago. Yeah they're ostensibly playing the same game but in many important ways they're actually not.
So at best in order to make the claim you're trying to make, you'd have to normalize the data from then and now. You haven't done that so you can't say Rust hasn't achieved arbitrary threshold of popularity after 10 years and therefore... I'm not exactly sure what your conclusion is actually. Therefore it won't survive? Therefore it's not all people make it out to be? I don't know, you're not being clear.
> But popularity is a measure of the actual benefit a language brings or, at least, lack of popularity is a measure of lack of sufficient benefit
If you're going to make this claim you've gotta back it up with some data. "popular", "actual benefit", "sufficient benefit" are all fuzzy words that mean one thing in your head but mean something different in everyone else. Many people live long enough to understand "popular" and "best" are not often synonymous.
> So claims that Rust is some huge game-changer don't really square with its rate of adoption.
Did anyone make that claim here? Rust is programming language like any other, and at best it's an incremental improvement over current languages, just like all of the top new languages of the last 50 years. The closest thing to a "game changer" I've seen is LLM vibe coding, but otherwise the game in Rust is the same as it's always been: 1) press keyboard buttons to write code in text buffer, 2) compile, 3) dodge bugs, 4) goto 1. Rust makes the first and second parts marginally worse, while making the third part marginally better. It doesn't change the game, but it makes it more fun to play (IMO).
> These two languages were created and pushed by two of the largest corporations on the planet.
I don't think Rust lacks in hype and marketing. It doesn't buy ads in print magazines, but no language does anymore (that's exactly how VB, Delphi, FoxPro, Visual C++, and Java were marketed). And don't forget that while being well-known is necessary for success, it's far from sufficient.
There's also the matter that large corporations may let certain star personalities work on vanity projects, they tend not to invest too heavily in projects they think are unlikely to succeed. In other words, even corporations can't market their path to success, at least not for long. That's why they try to market the things they already believe have a chance of success. Sun acquired technologies developed for Smalltalk and diverted them to Java because they believed Java had a better chance of success.
> This seems to me like cherry picking
Quite the opposite, I think. I can't find a single example of a language with Rust's adoption at age 10 that ended up very popular.
> whereas Rust came from the side project of a lowly Mozilla software engineer
So did C++.
> If you're going to make this claim you've gotta back it up with some data.
I'm backing it up with the market and the idea that in a highly competitive market, any technology that carries a significant competitive advantage in shorter time-to-market or in better reputation etc. should be picked up - at least if it is well-known. It's the claim that a technology gives its adopter a competitive advantage and yet doesn't spread as quickly as previous similar technologies that requires explanation.
> Did anyone make that claim here?
This whole debate is over whether Rust has some "superabled" and unique bottom-line-affecting capabilities compared to Zig.
> Rust is programming language like any other, and at best it's an incremental improvement over current languages
If you see Rust as one avenue for incremental improvement over C++, then we're in complete agreement :)
Let's remember: Dancin' Duke Java Applets distributed with Netscape's web browser.
"Sun is giving away Java and HotJava free, in a fast-track attempt to make it a standard before Micro-soft begins shipping a similar product"
I have received 3 transmissions from you so far, and you have yet to define "success" or "popularity", nor have you specified the threshold between "popular" and "very popular", despite having agreed with me that these things are not important for languages. Moreover, you haven't brought any figures to bear in supporting your claims. I think if we are going to continue this discussion, you have to substantiate your position -- otherwise I don't think you've said anything here that I haven't already responded to.
A specific definition of "popular" doesn't matter. What we can say is that Rust's market share at age 10 is lower than that of Fortran, COBOL, C, C++, VB, Python, JS, Java, C#, PHP, Ruby, TS, Kotlin, and Go at that age, but it's bigger than that of ML, Haskell, Erlang, and Clojure at that age. I don't know if I can compare its market share to that of Ada at that age. I'm nearly certain that much larger (and definitely more important) programs were written in Ada circa 1990 than are being written in Rust today, but it's hard for me to compare the number of programs.
> 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.
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.
> Rust is a very good middle ground: it's a complex language, but there's lot of room for improving its ergonomics.
I certainly agree Rust is a much better middle ground than either C or ATS. But so is Zig. What's harder to support objectively is that Rust is a better middle ground than Zig (or vice-versa). We just don't know! They both make different tradeoffs that we can't objectively rule on.
So all I'm saying is that we're left with subjective preferences, and that's fine, because that's all we have! So let's stick to saying "I like Rust's design better" or "I like Zig's design better", and stop trying to come up with objective reasons that are just not well-founded.
At the very least, people should stop comparing Zig to C as part of an argument that claims Rust is good because it prevents the vulnerabilities associated with memory-safety violations, as Zig prevents the most dangerous of those, too.
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.
I had the same thought. But one thing was actually very useful to compare "bug densities": deno vs bun. They have comparable codebase sizes as well as comparable ages (7y vs 4y). I'd like to see the same stats for tigerbeetle, which is very carefully designed: if segfaults were relatively high on that as too, well...
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!
> Don’t get me wrong, as a Rust zealot I have my biases and still expect a memory safe implementation to be less crashy
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.
I understand that I have a bias, which is why I was disclosing it. I think it strengthens my question since naively I'd expect a self-professed zealot to buy into the narrative in the blog post without questioning the data.
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)
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++.
The post gave the example of casting a float to an int. That is a (type) conversion.
The point is that certain casts/type conversions can change the underlying data.
> like the int with value 3 landing in memory after calling atoi("3").
That's something else entirely. People may colloquially call this "converting a string to an integer", but what we're realling doing here is parsing a string as an integer.
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.
> 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.
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.
A segfault is not the program performing a runtime check and doing a controlled shutdown. A segfault is the OS detecting the program doing something it's not allowed to and killing it.
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.
> 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.
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.”
Jai isn't open source so it is completely and totally irrelevant.
Zig builds C faster than most C compilers. You're going to have to do better than just mention it.
However, if those are the only things that are even possibly faster than Zig, then the Zig compiler qualifies as fast, not slow--which was my original point.
”Zig builds C faster than most C compilers” is a nonsense statement, which I don’t know how to answer.
The fact is simply that despite Zig uses LLVM as a backend in the same way Odin and C3 does, it compiles much slower. Exactly why that is, is something I can only guess at, but the fact is that Zig cached is still much slower to compile than Odin or C3.
(There are a few possible candidates as to why this is so that I identified and can share if it is interesting)
In any case, Zig is only ”fast to compile” if you compare to the triad of infamously slow languages: Swift, C++ and Rust.
This is just a convenient excuse. If Zig is to be fast to compile, it doesn’t help to make excuses for it.
Saying something it ”fast enough” because one is comparing with even slower languages is likely what made both Rust and Swift so slow to compile - they all just compared with C++, and it wasn’t until much later - when larger projects appeared - that the problem was taken more seriously. But at that time core architectural and language design concerns were already locked in.
This is why it’s not good for Zig to rest on its laurels and compare with worst of the class. And actually, faster Zig compile times benefits Jai, Odin and C3 as well, because then THOSE compilers can’t afford to slow down either. It’s a win-win.
If we compare with the worst though, then that’s a lose-lose proposition.
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).
Here's my 2 cents - a programming language (or any technology, smartphones, LLMs etc) has a honeymoon phase - during which everyone's excited about it and extols its virtues and focuses on how different it is from everything else.
Once that's over, people start looking at it with a more pragmatic eye - how much better is this really than what I had before. People start focusing less on the gimmicks and more on everyday usability.
For a programming language to be really popular, it needs that something that captures people's imaginations, but ultimately the stay power is determined by how useful it turns out.
Kotlin and Swift are very practical, but never had any wow features, so they never got hyped, they just quietly got more popular. Go had it with its green threads and channels, but nowadays most people seem to be not using those that much (I don't think there are a ton of instances of Go processes in prod with 10k threads), but otherwise its a solid language.
Rust - it's a solid language as well, and an improvement over C++ in some aspects like package management, but it's borrow checker and programming style is divisive.
Thing is, unlike goroutines there's no avoiding the borrow checker, so a lot of people don't really commit to Rust.
> Go had it with its green threads and channels, but nowadays most people seem to be not using those that much (I don't think there are a ton of instances of Go processes in prod with 10k threads)
Err..this is incorrect. Some projects who scale to 10k go-routines on a single instance regularly are loki and CockroachDB. Even your common NATS server can scale 5k+ go-routines on single instance and it is not uncommon.
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 feel like I'm on another planet here. Basically every new piece of software in my space (DB/query engines/streaming engines) is being written in Rust these days. There are like three production projects, total, written in Zig.
Same! I feel like I'm on crazy pills. Multiple folks in this thread are saying stuff like, "yeah, Rust, cool, but it has zero use". How are Linux, Microsoft, AWS, Cloudflare, Firefox, Python's `cryptography`, etc., not real use?
Rust is targeted at strategically important systems (proxies, databases, OSs, VMs, hypervisors, high-throughput servers, cryptography, browsers) and by any measure is making significant inroads into those kinds of systems in real industrial applications, and I'm to believe that Rust adoption is languishing? Am I going insane?
I hear this a lot, but there are many things for which you can use both, so they're competitors. Also most Rust developers want to use it everywhere, including areas where you normally reach out to C, so if people that like Rust want to use it for things that are usually made with C, and Zig is a replacement for C, it seems to me they're competitors, no?
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.
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.
And the thing is Rust's borrow checker isn't such a difficult customer to just eliminate use after free - it's to stop all undefined behavior, like mutable aliasing, data races etc.
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.
Not in the sense I meant to make the comparison - Zig doesn't even pretend to do memory safety - if you don't free something manually it won't get freed - this is way worse level of safety than even what C++ with unique_ptr.
In contrast if Rust only ensured that a reference doesn't outlive the scope it's valid in (allocated and cleaned up via RAII), a lot of problems with Rust would go away, like you could have 2 mutable references pointing to the same thing - it'd still be leak free, but you could have data races, and would need some aliasing heuristics like you have in C.
Still most of the complaining of the borrow checker would go away. Imo this is an idea worth exploring in a language, but I'm sure doing this would upset Rust purists.
> Zig doesn't even pretend to do memory safety - if you don't free something manually it won't get freed
Preventing memory leaks isn't normally what people mean by "memory safety".
As an aside: a common memory management approach used in Zig is to have a dedicated memory pool for an operation and simply free all of the memory after the operation is over instead of freeing individual allocations.
> Preventing memory leaks isn't normally what people mean by "memory safety".
People do sometimes expect it to be encompassed by memory safety, even though the Rust documentation clearly states that it does not prevent memory leaks in safe code and offers several obvious ways to deliberately leak memory.
This is simply untrue. Zig offers the same spatial memory safety as Rust does, and that is the kind of memory safety that prevents more dangerous vulnerabilities [1] than the kind Rust offers and Zig doesn't (temporal memory safety).
> if you don't free something manually it won't get freed
Rust also isn't free of memory leaks, and doesn't even pretend to guarantee that all allocations are freed. Lack of memory leaks doesn't fall under what Rust defines as memory safety (which Rust defines as guarantees it does provide, excluding those it doesn't).
You're responding to the emotional appeal part of my post, not the argument itself - I'm sorry for including it, as it had sidetracked the useful conversation.
Zig doesn't have the memory safety mechanisms of C++ level shared_ptr/unique_ptr.
It's essentially C's malloc/free with the added safety of defer (or possibly arenas), but making sure that the program doesn't leak memory (or have use-after-free bugs) falls on the programmer.
And memory leaks are a much lesser problem, as they usually lead to crashes in OoM situation, than gaining access to random blocks of memory.
Besides, the way you trigger memory leaks in Rust/C++ is with circular references, which are much harder to create than just missing a free() somewhere.
If you have memory that's not tied to a function scope's lifetime in Zig (or the scope of an allocator), then you're essentially have to go by C rules
> Zig doesn't have the memory safety mechanisms of C++ level shared_ptr/unique_ptr.
Zig's memory-safety is spatial, which is the more dangerous kind. Your examples are all temporal, and I don't know if I would call them "safety" as the language doesn't enforce or even encourage their use. For example, I work on one of the world's most foundational C++ projects (the HotSpot virtual machine), where neither shared_ptr nor unique_ptr are used at all; the language doesn't complain. There are reference-counted pointer libraries for Zig, too (although I don't think they're popular).
> It's essentially C's malloc/free with the added safety of defer
No, it isn't. First, unlike C or C++, it offers Rust-like spatial memory safety (again, the more important kind). Second, allocation in Zig is much more explicit than in C or C++.
> Besides, the way you trigger memory leaks in Rust/C++ is with circular references, which are much harder to create than just missing a free() somewhere.
They're also much harder to detect, especially when you have a very explicit memory allocation scheme.
> If you have memory that's not tied to a function scope's lifetime in Zig (or the scope of an allocator), then you're essentially have to go by C rules
Again, Zig doesn't seek to offer temporal memory safety, but it does offer the same level of spatial memory safety as Rust does, and while the "rules" of temporal management are similar to C, the way allocation works in Zig makes for a very different experience. An allocating function in Zig looks very different from its C counterpart.
Zig rejects the temporal memory management schemes of C, C++, and Rust - each for different reasons - and prefers a different kind. Of those, only Rust offers temporal memory safety (in the sense that it's controlled by the language) - albeit for a price - and the rest don't.
I don't understand the distinction between spatial and temporal memory safety - from what I gather, spatial memory safety is just preventing out of bounds access of arrays, dereferencing uninitialized or otherwise invalid pointers. But use after free absolutely results in the same kinds of errors (accessing unused memory, or memory used by someone else).
I also don't understand how one can sidestep the issue of ownership of memory - let's say you have a situation where a given piece of memory has changing or ambiguous ownership - like an event sent between two components, that has allocated some dynamic memory.
I'm not saying this just because, I've encountered this exact issue before - many C libraries have event systems where the ownership is not obvious coming from the code - like the sender owns the event, and if you store a reference to it, then you have a dangling pointer if the sender decides to clean it up.
That's why it's important to make it either obvious who owns what, or have some automatic system like GC or unique_ptr or the borrow checker.
This is a very real issue and the only way you can fix it is to follow strong informal conventions the language has no way of enforcing or even communicating to the user.
You mention Zig has a temporal memory management solution of a different kind - may I ask you what it is, because I haven't really seen it.
> But use after free absolutely results in the same kinds of errors (accessing unused memory, or memory used by someone else).
That two bugs result in the same or similar outcome doesn't mean they're as common or as equally exploitable, which is why, in practice, it is distinctly a more dangerous weakness in the lists maintained by MITRE.
> I also don't understand how one can sidestep the issue of ownership of memory
It's not about side-stepping. There are many kinds of bugs in software, and while we'd like to avoid all of them, some problems are, in practice, more problematic. After all, Rust similarly "sidesteps" - as in doesn't prevent - all non-memory-safety-related weaknesses, some of which are more dangerous than dynamic memory safety. If Zig isn't good enough because it doesn't prevent temporal memory safety violations, then by the exact same logic, Rust isn't good enough because it doesn't prevent, say, injection vulnerabilities, that are more dangerous than temporal memory safety vulnerabilities.
> I'm not saying this just because, I've encountered this exact issue before
Sure, it's a real and serious issue. But injection is a more serious issue, which Rust doesn't prevent, and spatial memory violations are also a more serious issue, which Zig prevents just as Rust does.
> That's why it's important to make it either obvious who owns what, or have some automatic system like GC or unique_ptr or the borrow checker.
It is, but it's even more important to prevent code injection attacks, yet Rust doesn't do that. It all comes down to how much it's worth it to pay to prevent certain bugs.
Rust was built because its designers believed that memory safety wasn't worth paying the higher memory footprint or the lower predictability of more popular memory-safe languages, or else there would have been no need for Rust in the first place. Similarly, it's just as reasonable to believe that the price you pay for temporal memory safety in Rust is not worth it.
> You mention Zig has a temporal memory management solution of a different kind - may I ask you what it is, because I haven't really seen it.
It's not a safe solution by any means (as the language doesn't enforce temporal memory safety, just as C++ doesn't), but memory allocation and deallocation in Zig is not the same as in C or C++. In particular, Zig functions that allocate are explicitly marked by having an Allocator parameter (https://zig.guide/standard-library/allocators/). Unlike in C, in Zig you know which functions allocate and using which allocator. That's how Zig is such a great fit for arenas.
I feel like one thing that wasn't made clear - it's not necessarily the job of the programming language to prevent certain issues - SQL injection for example is something that should be handled by the framework (by not allowing to write SQL directly, but using commands with parameters). All the other higher priority issues are like that, it's not within the scope of a language to prevent such issues, just as Rust or Zig or whatever will never prevent phishing attacks.
As for temporal vs spatial memory safety issues, I agree that Zig does maybe help in that a bit (if component A sends an event to B, then A,B and the events having a separate allocator would work) - though I'm not sure if it doesn't introduce its own footguns (how do I know which allocator needs to free which object).
I don't know I haven't used Zig at all, so no idea how all this works out in practice. Memory issues are 100% solved by languages like Java with GC and I wouldn't say they have made software that much less buggy.
Use after free is number 8 and 9 on the lists respectively... Not like it's way down the list. And most of the things the things above it (other than out of bounds writes/reads which you addressed in another comment) are not something I would consider a programming language can directly affect (e.g. SQL injection, CSRF)
I'm not saying it's not important, but we do have to consider whether it's worth the cost.
> And most of the things the things above it (other than out of bounds writes/reads which you addressed in another comment) are not something I would consider a programming language can directly affect (e.g. SQL injection, CSRF)
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.
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.
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.
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 ?
It's doing something novel in the systems programming space, and makes a bunch of different trade-offs compared to Rust. That's interesting, even if you might reasonably conclude that Rust is still a better language to use in most cases. It's good to explore different corners of the programming language design space.
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.
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.
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.
> 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.
> Limiting to the "top 5" vulnerabilities by number of CVEs feels like cherry-picking.
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.
> 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.
There is a very clear sharp line between them in that Rust has no undefined behavior outside of an unsafe block. This matters because the effects of undefined behavior -- particularly memory-corrupting undefined behavior -- are unbounded. Security issues caused by logic bugs are limited to only having local effects on the program -- a SQL injection bug can lead to the wrong SQL query being executed, a path traversal bug can lead to the wrong path being accessed, and a shell escaping bug can lead to execution of the wrong shell command. These are severe problems that can lead to data exfiltration or remote code execution, but the relationship between bug and effect is straightforward: "I'm passing user input to a shell here; this could have catastrophic consequences so I'd better review this carefully." In contrast, undefined behavior can happen anywhere in your program, and it can do anything. That is a clear and measurable difference, and emperical evidence from the last 10 years clearly indicates both that it is nigh impossible to write large C/C++ applications without both spatial and temporal memory safety vulnerabilities, and that adopting Rust measurably decreases the incidence of such vulnerabilities.
Zig is certainly an improvement over C on this front, but it is still a UB-heavy language, and that's where the sharp line is. It's hard to make emperical comparisons because Zig is so young, but the comparision between Deno and Bun in the article is a reasonably strong demonstration that Zig has not achieved a comparable level of memory safety to Rust.
> 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.
This doesn't really have anything to do with my point that the CVE list does not provide evidence to dismiss temporal memory safety as irrelevant; it's more of a general statement on writing correct software. But regardless, "Zig has nullability and bounds checks" and "Rust has an affine type system, statically-checked immutability and exclusivity, language-level resource management, and no undefined behavior" are not in the same league of program correctness. Rust wasn't designed after some ideal of memory safety at the expense of clarity and correctness: the lifetime and type system came from a goal of reducing logic bugs in complex concurrent programs, and the fact that it is powerful enough to achieve memory safety without garbage collection was a happy accident. The emperical results that Rust programs have fewer memory-safety vulnerabilities demonstrate that Rust's static approach to software correctness is successful, and not just for the specific problem of memory safety, because Rust's tooling for achieving program correctness is generalizable to arbitrary application invariants. This lines up with my own experience; software I write using Rust is far easier to get right, more reliable, and easier to successfully maintain and refactor than anything else I've done.
Certainly Zig has its strong points as well -- explicitness can reduce complexity and compile times, but it also has downsides of pushing complexity into application code (thus making it harder to review and introducing more opportunities to create mistakes). A proper comparison of the two approaches is worthwhile, but just as "Rust is more memory safe" is an overly reductive generalization of the langauges' approach to software correctness, "there's a rather small difference between Rust and Zig" simply isn't true.
> There is a very clear sharp line between them in that Rust has no undefined behavior outside of an unsafe block.
Yes, but that's an intrinsic language feature whose value needs to be justified somehow. If you justify it by saying it prevents dangerous vulnerabilities, we're back to my point.
> This matters because the effects of undefined behavior -- particularly memory-corrupting undefined behavior -- are unbounded...
While I appreciate this explanation (and I've seen it many times), I hope you understand that it's more speculative and subjective than an empirical finding. At the end of the day, to measure the danger of a problem, we need to see what the actual vulnerabilities/exploits are and how common they are. Clearly, not all undefined behaviours are equally exploitable. That's why we see differences in weakness severity among different kinds of UB.
> emperical evidence from the last 10 years clearly indicates both that it is nigh impossible to write large C/C++ applications without both spatial and temporal memory safety vulnerabilities
Right, and that same empirical evidence shows that spatial violations are the more dangerous ones, and that's exactly why Zig prevents them.
> but the comparision between Deno and Bun in the article
What article? It seems that Bun has had one CVE. If you're talking about undefined behaviour you're, again, making an unjustified extrapolation from it to security. Some undefined behaviour leads to easily exploitable vulnerabilities, some does not.
It's true that in the presence of UB, the compiler could hypothetically do anything, but to get a dangerous vulnerability it has to actually do something that's exploitable, and when we look at vulnerabilities caused by UB, we see that some kinds are more dangerous than others because of that.
BTW, this touches on something that is sometimes misunderstood about UB. UB is defined with respect to a language specification, i.e. in the presence of UB, the language specification does not assign a program a meaning, but the compiler certainly does, because machine code has no UB. The program with the UB needs to compile to an exploitable binary for a vulnerability to exist.
> and that's where the sharp line is
I agree it's a sharp intrinsic line, just as saying that Zig avoids macros is a sharp line, but the impact of that line is anything but sharp. To draw the practical conclusion from it you don't follow the findings, but ignore them!
> This doesn't really have anything to do with my point that the CVE list does not provide evidence to dismiss temporal memory safety as irrelevant
I wasn't dismissing it as irrelevant. I was saying that if Rust's value is in eliminating dangerous vulnerabilities, then Zig has that value, too, and the difference between them isn't large on that particular front.
> are not in the same league of program correctness
Software correctness is something I've been dealing with and writing about for many years, especially formal verification (https://pron.github.io), and I can tell you that you're downright wrong on that. That "more sound guarantees is always the most effective form of improving correctness" is something we know (at least since the nineties) not to be generally true, which is also why the field is looking more and more into unsound methods. For example, Rust and Zig are more likely to effectively write correct programs than ATS, even though ATS is "in a different league" from both of them when it comes to sound guarantees.
We know that sound guarantees can help, but that their cost matters a lot. We also know that reviews and tests and dynamic verification are very effective, sometimes more than sound guarantees.
Rust proponents are free to speculate that, ultimately, Rust's approach leads to more correctness than Zig, and they can base that belief on some findings, and Zig proponents can do exactly the same in the opposite direction, also based on other findings, but both are speculations. People are free to choose which they are more inclined to believe, but the question isn't settled.
> This lines up with my own experience; software I write using Rust is far easier to get right, more reliable, and easier to successfully maintain and refactor than anything else I've done.
I'm not doubting that that's your experience. I'm saying we have no evidence that it's universal, likely to be universal etc. (and I know of some opposite experiences with Rust). Sometimes certain languages just click with certain people, but we can't extrapolate without more observation.
> "there's a rather small difference between Rust and Zig" simply isn't true.
The correctness difference between the two is unknown. It could be small or large and in either direction. The intrinsic differences are, of course, known, but don't really help reach an objective preference. My point was only that if we judge Rust by the vulnerabilities it soundly eliminates, then Zig is not far on that particular metric, and it's certainly much closer to Rust than to C.
Maybe we should be using ATS. Or more likely, maybe we should be using some novel language that doesn't exist yet that brings the benefits of ATS to a language with good tooling and good DX that you can use to build practical system software with - that is, a Rust for ATS instead of C/C++. I think we should be designing programming languages that help eliminate as many classes of bug as possible, and Rust is not the culmination of the line here.
One of the lessons of the past 50 years in software correctness is that sound guarantees are not always the most effective path to correctness. The problem is that proving something correct takes a lot of effort (and there are fundamental computational complexity reasons for that), while unsound methods are significantly cheaper and surprisingly effective in practice. A famous 1996 paper by Tony Hoare [1] expresses amazement at how software had become so reliable without proofs, something that in the 1970s was thought impossible. Since then, the field has moved to enthusiastically adopt more unsound methods.
And remember that a software system, unlike an abstract algorithm, is a physical system that cannot be proven correct, since the behaviour of the physical hardware cannot be proven. We're always dealing in probabilities, and so the question is: how do we get the most value (in terms of reducing the probability of costly bugs) for a unit of effort.
Since the 1970s, the size of software that can be proven correct in practice using deductive methods has only fallen compared to the average size of a program (i.e. the size of acceptably-reliable software we write has grown much more rapidly than the size of software we can prove correct using deductive methods). The largest programs ever proven correct using deductive methods are on the order of 10KLOC.
So the field of software correctness has long ago abandoned the position (held by some in the 70s) that proof is always the most effective way toward correctness.
> 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.
I think a lot of the absolutists around memory safety are just using it as a bludgeon to evangelize their preferred programming language. Otherwise, the position of "memory safety is the most important thing, but we should ignore other languages that provide stronger guarantees" is absurd.
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.
I think, but I may be wrong, Zig wants to be high level assembly that could replace C. If people are viewing it from Python, Ruby, JS, and then C++ and Java POV, Zig may be a little too "raw". But then I don't think Zig intends to compete with C++ or Java. May be there will be a Zig ++ or Objective-Zig someday that will do that.
It really comes down to a matter of opinion where the line between "nothing hidden" and convenience lies. Technically, a loop is an abstraction of convenience that hides the comparative jump underneath.
> 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.
> 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.
It's deeper to note people who know nothing will make the mistake, than "I, an expert, will make the mistake"? :)
Okay broader then?
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.
Zig is famously simple to pick up and write with, so I don't know what you mean by "difficult". Software is dangerous. Memory safety is one of a million ways it can be dangerous. A compiler barfing when it thinks you are doing something unsafe with pointers is one approach to dealing with one of the ways that code can be dangerous to execute.
Zig does not ignore that particular danger, it just takes a different approach to dealing with it than some other modern languages. An approach that, I believe, leaves the developer with a little more humanity by allowing them the benefit of the doubt that they know what they are doing.
Everyone that has not built a systems language, or has not built a real application with both Zig and a memory safe language, that is reacting emotionally to what I've said should put a lot of consideration into whether they are cargo culting or using critical thought. Consider that we still do not yet know what is best, and shutting down attempts to explore different ideas with things like "creating [and using] this language is ignoring the humanity of the end user" is, well.. dumb.
I have never heard anyone calling Zig "famously simple" before. In fact, people tend to say it has quite the learning curve.
Of course, caveats apply: it is certainly simple compared to some languages, but certainly not compared to others. "Famously simple" seems to indicate it is one of the simplest languages to learn, which seems wrong unless there are some serious qualifications to that statement?
C, C++, Rust, Zig. Rust and C++ have an infamous learning curve. If you know anything about using any systems language other than Zig, Zig is incredibly simple to pick up, like C. Unlike C, it pushes you toward making less mistakes.
If you don't know anything about using a systems language, Zig makes it easier for the people who do to review your code and make sure you didn't mess it up. It does this with very intentional design that makes it easier to understand the full impact of code quickly, reducing the cost of review, making review practical to catch the issues. It also has many other fail safes to catch these problems before they ever reach a production release.
So, yeah, it's totally depending on where you are coming from -- but Zig is not a tool built for a web developer who doesn't know anything about memory to go and ship an application within their first week. It does make it easier for that person to learn the ropes at a steady pace.
Meanwhile, everyone complaining that Zig is not memory safe doesn't seem to care that applications written in Zig do not have the vulnerabilities that memory safety solves on the scale that C does[0].
If you have not written a real application in Zig and evaluated it for vulnerabilities, but are claiming that creating Zig was irresponsible, and using it is too; you are cargo culting.
If you have, you probably understand there is a niche that Zig fits in and that it isn't surprising it exists to fill it. Like all things in our industry, there is a cost/benefit analysis required for choosing the tools you build with.
No one reasonable has claimed that memory safe languages should not exist, but there is a maddening number of people being disrespectful toward those who think there are other ways of addressing the same problems.
[0]: https://mitchellh.com/writing/ghostty-gtk-rewrite
If you are comparing Zig to Rust and C++, which are very well known to be difficult to learn, then that is not really saying anything about the ease of learning it. Compare it to Swift, D or Odin. Is it "incredibly simple" compared to those languages as well?
Similarly, one can claim that pretty much anything compiles "incredibly fast" if one compares with Rust, C++ and Swift.
But comparing to worst in class doesn't actually say anything.
One note about this:
> If you have not written a real application in Zig and evaluated it for vulnerabilities, but are claiming that creating Zig was irresponsible, and using it is too; you are cargo culting.
I don't know what this has to do with my comments at all, but I want to point out that you are using "cargo culting" wrong. This describes imitating practices of something successful, thinking that by this imitation, success will follow as well.
> No one reasonable has claimed that memory safe languages should not exist,
Again, I have not talked anything about whether memory safe languages should or should not exist. You are confusing me with someone else.
>Zig is famously simple to pick up and write with, so I don't know what you mean by "difficult".
It's easy to get in a car and put your foot on the pedal, but usage entails not crashing.
>Memory safety is one of a million ways it can be dangerous.
We have the statistics on this. It is 7 out of 10 ways it is dangerous, going by proportion of CVEs, so it's likely higher in less well tested software. Your estimation was off by 5 orders of magnitude.
>leaves the developer with a little more humanity
I could care less if the developer is afforded humanity. I want to write software and I want a programming language that helps me to do that. Whatever humanity I'm sacrificing by writing in memory safe languages is more than made up for by the comparative ease of not having to worry about memory safety.
>reacting emotionally
You are reacting emotionally. You are judging programming languages by their emotional value rather than their features. “Humanity” is not a measurable feature. 70% fewer CVEs is a measurable feature.
> 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?
> But I oppositely believe the world needs more tech that treats professionals as experts, not kids.
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.
> But I oppositely believe the world needs more tech that treats professionals as experts, not kids.
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."
Not an expert, but isn't Zig's comptime essentially an AST generator?
Kind of, but such functionality is not exposed to the user.
Great post on what comptime won't do: https://matklad.github.io/2025/04/19/things-zig-comptime-won...
>> 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.
> ... 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.
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?
> 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.
Sure, that makes sense. I agree this is all very subjective, given we don't have the benefit of hindsight for what Zig can accomplish yet.
I think where we disagree is that you believe Zig is as safe as Rust (by making it easier to make other things safer). I don't believe so (my first impression of Zig was Bun repeatedly segfaulting), and I'm just sad that people are choosing the easy route and going for more insecure software, when it finally looked like we made such great progress, with a language people can actually use. I agree with simpler, but there's so many other things that can be changed or removed from Rust, and still leave in lifetimes, or something similar.
> I think where we disagree is that you believe Zig is as safe as Rust
Quite the opposite. Rust is definitely safer in the simple sense that it guarantees more memory safety. But that's very different from saying that Zig is closer to C than to Rust (Zig's memory safety is much closer to Rust's than to C's), and it also doesn't mean that it's easier to write more correct/secure software in Rust (because there are just too many factors).
> and I'm just sad that people are choosing the easy route and going for more insecure software
The jump from "segfaulting" to "insecure" is unjustified, as not all causes of segfaults map to equally exploitable vulnerabilities. Java programs, for example, segfault much less than Rust programs. Does that mean Rust programs are significantly less secure?
> Zig's memory safety is much closer to Rust's than to C's
This is arguable. Zig's issues with memory safety are not limited to such things as use-after-free ("temporal" memory safety in a rather obvious sense). Without something very much like Rust's borrow checker and affine types, you can't feasibly prevent a program from inadvertently e.g. stashing a pointer somewhwere to an inner feld of a tagged union, and reusing that pointer later even though the union itself may have mutated to a different tag, which results in undetected type punning and potentially wild pointers. The issue of iterators to a collection being invalidated by mutation is quite similar in spirit, and again has nothing to do with the heap per se. Rust prevents these issues across the board. The fact that it also manages to prevent temporal memory unsafety altogether is simply a bonus that essentially comes "for free" given the borrow checking approach.
> This is arguable
That's not arguable. Because if we say that memory safety is important because it prevents some common and dangerous vulnerabilities, then Zig clearly prevents the most dangerous of those, while C doesn't.
> you can't prevent a program from inadvertently...
Now you're naming more problems that aren't as high on the list as the ones Zig does prevent (and C doesn't). It's true that type confusion is also rather high on the list, but Zig clearly reduces type confusion much more than C does.
Nobody denies that Rust prevents more issues than Zig via sound guarantees - albeit at what I think is a significant cost, and we can argue, subjectively, over whether those issues are worth that cost or not - but Zig's guarantees are still closer to Rust's than to C's if eliminating very common/dangerous vulnerabilities is what we're judging by.
The underlying issue is that Zig turns out to have no feasible safe subset, just like C - unless you go as far as to declare things like using tagged unions in combination with pointers "unsafe" which is both insanely restrictive and hard to check programmatically. People might complain about having to fight the borrow checker, but they'd complain a whole lot more if the standard approach to safety-subsetting a language was just bounds-checked array access plus "you can write FORTRAN in any language!"
> The underlying issue is that Zig turns out to have no feasible safe subset
It does have a safe subset with respect to spatial memory safety, which is the more important kind of memory safety if what we judge by is dangerous vulnerabilities.
> People might complain about having to fight the borrow checker, but they would complain a lot more if the standard approach to safety-subsetting a language was just bounds-checked array access plus "you can write FORTRAN in any language!"
I don't know how you can say that this is an objectively-supported claim given Rust's poor adoption at its age.
Rust's real superpower is its tooling. Cargo handles package management, building, testing, documentation, and publishing. The compiler's errors explain what went wrong and where it happened. Installing the toolchain with rustup is quick and painless, even on Windows. I can't know that it's best in class, but it's certainly the best I've used.
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.
Rust is much older than Zig, though, and there's nothing stopping Zig (or any future language that doesn't adopt Rust's precise set of guarantees) from having the same, or possibly better. Given Zig's immaturity, I certainly wouldn't use it for any serious production software today.
BTW, I'm not saying Rust is bad. All I'm saying is that the attempt at proving it's objectively best by leaning on memory-safety is not really as objective as the people who make that claim seem to think it is.
I hadn't heard of ATS before, and I think that I mistook your using it as an example of "more isn't always better" and thought you were suggesting it as an actual alternative.
I'm looking for the next thing I want to learn, and have been leaning towards logic programming and theorem provers, so you inadvertently piqued my interest.
> ... 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.
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.
> 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.
I'm curious, do you have figures for this? I was not around when C or C++ were 10, but I was when python was and as a long time python user I would say that the pycommunity was much smaller at 10 then the rust community at 10. So my gut feeling is that your statement is false at least wrt python, but I'm happy to change my mind if you have sound data.
Edit: just to add some more anecdotal evidence from my memory of languages I used: java community was pretty bigger than rust at 10. Go's was much smaller than rust at 10. I'd be happy to check my beliefs against actual data :)
I wasn't programming yet when C was 10 years old, but I was when C++ was 10 years old (1995), and its adoption was an order of magnitude higher than Rust's is today.
I agree that of all popular languages, Python is the latest bloomer, but while it became popular for applications and data processing rather late, it was used a lot for scripting well before then.
> Go's was much smaller than rust at 10
Go turned 10 (if we want to count from 1.0) only 3 years ago, and Go's adoption in 2022 was much bigger than Rust's today.
I don’t have a dog in this race but I was also around at that time and one reason is there was far less choice in 1995 about where you would go from C. C++ was also a vastly simpler language back then (no templates, no exceptions, barely a few hundred command line options). So I am not sure what its adoption then can teach us about language adoption now.
I don't think it's true there was far less choice in 1995. Around that time (a few years later) I was working on a project that was half Ada half C++, and there were a few more exotic choices around. Aside from those, and C, there were still projects in the company back then written in Fortran and even in Jovial. At university, I learnt Esterel for formally-verified embedded software. And that's not even touching on the higher level space, where VB, Delphi, some Smalltalk, and a large selection of other "RAD tools" were being used (my first summer job was on what today would be called an ERP system written in a language called Business Basic). At university, the language I was taught at intro to compsi was Scheme (that was also the embedded-scrpting language we used at work). We were also taught ML and a bit of Haskell.
It's true that not many languages that seemed a reasonable choice at the time survived to this day as reasonable choices.
> Go's was much smaller than rust at 10.
There's no way that can be true.
Typescript is a tool more than a language, so that's not fair at all.
And the rest of those basically had no competition in their domain when they started 30+ years ago. Rust now has to grow next to 30 years of those languages maturing, and convince people to abandon all existing community resources - whereas those languages did not.
Having a low adoption rate is normal in this day and age. Go is kind of an anomaly caused by it's backing by Google.
But it doesn't help that Rust is also in the native space, whose devs are especially stubborn, and is a difficult language with painful syntax.
I dunno, I think you're trying to split hairs if top 20 isn't "very popular".
But I don't think the comparison you're trying to make works, because then isn't now.
In general, in order to convince someone to leave their current tools, you have to not only be better but a lot better. As in, you need to offer the entire feature set of the old tool plus something else compelling enough to overcome the network effects (ecosystem + years of experience + job prospects) of the prior environment.
So when C++ came on the scene, they had to compete against ~20 years of accumulated legacy systems and language history. Rust had to compete with 50 years of legacy systems and language history.
Moreover, developer expectations are a lot different today. Back then, C++ was what, a compiler and some docs? Python was an interpreter and some docs? Maybe an IRC channel? Today, it's not enough to reach 1.0, you also have to deliver a package manager, robust 3rd party library ecosystem, language server tooling, a robust community with support for new devs, etc. So timescales for language development are getting longer than they were back then.
Also, I don't know why you've chosen "very popular" as a metric. Very popular isn't something a language needs to be, it just needs to be big enough to sustain a community. Being top 20 within 10 years is certainly in that realm. You can see that other language communities have existed for longer and are much smaller. And anyway, the entire developer population today is much larger than it was back then; you can have a small percentage of all developers but still large enough to be robust. I don't know the math, maybe someone can figure it out, but I wouldn't be surprised if 1% of developers today is inflation adjusted to like 10%-20% of developers in 1996. So Rust is probably as big as it needs to be to sustain itself, it doesn't have to be a "very popular" language if that means being in the top 5 or whatever the threshold is.
> I dunno, I think you're trying to split hairs if top 20 isn't "very popular".
It's very popular compared to Prolog or Haskell, but not compared to languages people use professionally: https://www.devjobsscanner.com/blog/top-8-most-demanded-prog...
> In general, in order to convince someone to leave their current tools, you have to not only be better but a lot better.
I agree.
> So when C++ came on the scene, they had to compete against ~20 years of accumulated legacy systems and language history. Rust had to compete with 50 years of legacy systems and language history.
Ok, but Go and TypeScript are pretty much the same age, and when Java came out, it took over much of C++'s market very quickly.
I agree Rust has some clear benefits over C++, but it also has intrinsic challenges that go well beyond mere industry momentum (and other languages have shown that momentum is very much defeatable).
> Moreover, developer expectations are a lot different today.
But there are more programmers today, and many more people worked on Rust than on C++ in its early years. And besides, Rust has had all those things you mentioned for quite some time, and C++ still doesn't have some of them.
> Also, I don't know why you've chosen "very popular" as a metric. Very popular isn't something a language needs to be, it just needs to be big enough to sustain a community.
I agree it doesn't need to be very popular to survive. But popularity is a measure of the actual benefit a language brings or, at least, lack of popularity is a measure of lack of sufficient benefit, because software is a competitive business. So claims that Rust is some huge game-changer don't really square with its rate of adoption.
> I agree it doesn't need to be very popular to survive. But...
I think that's the end of it then, yeah? We've established it's popular enough (you set a lower bound at Haskell, which has been around for 35 years, has an active and vibrant community, and is still used in industry), we agree it doesn't need to be more popular, so then this threshold of "very popular" you invented (which I guess is the top 10) is arbitrary and therefore not relevent.
> Ok, but Go and TypeScript are pretty much the same age, and when Java came out, it took over much of C++'s market very quickly.
These two languages were created and pushed by two of the largest corporations on the planet. Typescript is basically Javascript++, and it came at a time when Javascript was to a large degree the only language for the browser. So they had: 1) one of the largest corporations in the world backing it with effectively unlimited money as part of a larger campaign to win web developer mindshare 2) a large developer base of people who already spoke the language 3) guaranteed job opportunities (at least at Microsoft, so more quickly followed) for people who invested in it. Microsoft was also instrumental in defining the platform on which Typescript ran, so they had that benefit as well. That's one way to achieve success for a language, but it requires only offering a very small delta in features; Typescript could only do what it did by being Javascript + types.
Likewise with Go, they bootstrapped that community with Googlers. Bootstrapping a community is way harder than bootstrapping a language, so having a built-in community is quite an advantage. People wanted to learn Go just to have it on their resume, because they heard it would help them land a job there. Plenty of my students took that route. Google threw their weight around where they could for Go, even going as far as to steal the name right out from another language developer and telling him to pound sand when he complained about it.
I mean, Google could afford to hire Robert Griesemer, Rob Pike, AND Ken Thompson to create Go; whereas Rust came from the side project of a lowly Mozilla software engineer. We're looking at two very different levels of investment in these respective languages.
This seems to me like cherry picking. You're taking the best-case scenarios and then comparing it to something not like that at all. When it pales in comparison, you conclude it's not sufficient. But here's the thing: if we want programming as a field to evolve, not every new language can be ExistingLang++. Some languages are going to have to take big swings, and they're not going to be as popular as the easy road (big swings mean big divisions and polarized views; Javascript + types is an easy and agreeable idea). That doesn't mean they aren't just as if not more beneficial to programming languages as a field.
> But there are more programmers today, and many more people worked on Rust than on C++ in its early years.
Yes, and that completely muddles your point, which is why these comparisons don't make sense. It's like comparing the success of a new NFL team to teams from 50 years ago. Yeah they're ostensibly playing the same game but in many important ways they're actually not.
So at best in order to make the claim you're trying to make, you'd have to normalize the data from then and now. You haven't done that so you can't say Rust hasn't achieved arbitrary threshold of popularity after 10 years and therefore... I'm not exactly sure what your conclusion is actually. Therefore it won't survive? Therefore it's not all people make it out to be? I don't know, you're not being clear.
> But popularity is a measure of the actual benefit a language brings or, at least, lack of popularity is a measure of lack of sufficient benefit
If you're going to make this claim you've gotta back it up with some data. "popular", "actual benefit", "sufficient benefit" are all fuzzy words that mean one thing in your head but mean something different in everyone else. Many people live long enough to understand "popular" and "best" are not often synonymous.
> So claims that Rust is some huge game-changer don't really square with its rate of adoption.
Did anyone make that claim here? Rust is programming language like any other, and at best it's an incremental improvement over current languages, just like all of the top new languages of the last 50 years. The closest thing to a "game changer" I've seen is LLM vibe coding, but otherwise the game in Rust is the same as it's always been: 1) press keyboard buttons to write code in text buffer, 2) compile, 3) dodge bugs, 4) goto 1. Rust makes the first and second parts marginally worse, while making the third part marginally better. It doesn't change the game, but it makes it more fun to play (IMO).
> These two languages were created and pushed by two of the largest corporations on the planet.
I don't think Rust lacks in hype and marketing. It doesn't buy ads in print magazines, but no language does anymore (that's exactly how VB, Delphi, FoxPro, Visual C++, and Java were marketed). And don't forget that while being well-known is necessary for success, it's far from sufficient.
There's also the matter that large corporations may let certain star personalities work on vanity projects, they tend not to invest too heavily in projects they think are unlikely to succeed. In other words, even corporations can't market their path to success, at least not for long. That's why they try to market the things they already believe have a chance of success. Sun acquired technologies developed for Smalltalk and diverted them to Java because they believed Java had a better chance of success.
> This seems to me like cherry picking
Quite the opposite, I think. I can't find a single example of a language with Rust's adoption at age 10 that ended up very popular.
> whereas Rust came from the side project of a lowly Mozilla software engineer
So did C++.
> If you're going to make this claim you've gotta back it up with some data.
I'm backing it up with the market and the idea that in a highly competitive market, any technology that carries a significant competitive advantage in shorter time-to-market or in better reputation etc. should be picked up - at least if it is well-known. It's the claim that a technology gives its adopter a competitive advantage and yet doesn't spread as quickly as previous similar technologies that requires explanation.
> Did anyone make that claim here?
This whole debate is over whether Rust has some "superabled" and unique bottom-line-affecting capabilities compared to Zig.
> Rust is programming language like any other, and at best it's an incremental improvement over current languages
If you see Rust as one avenue for incremental improvement over C++, then we're in complete agreement :)
Let's remember: Dancin' Duke Java Applets distributed with Netscape's web browser. "Sun is giving away Java and HotJava free, in a fast-track attempt to make it a standard before Micro-soft begins shipping a similar product"
https://archive.gyford.com/1997/wired-uk/1.08/features/java....
I have received 3 transmissions from you so far, and you have yet to define "success" or "popularity", nor have you specified the threshold between "popular" and "very popular", despite having agreed with me that these things are not important for languages. Moreover, you haven't brought any figures to bear in supporting your claims. I think if we are going to continue this discussion, you have to substantiate your position -- otherwise I don't think you've said anything here that I haven't already responded to.
A specific definition of "popular" doesn't matter. What we can say is that Rust's market share at age 10 is lower than that of Fortran, COBOL, C, C++, VB, Python, JS, Java, C#, PHP, Ruby, TS, Kotlin, and Go at that age, but it's bigger than that of ML, Haskell, Erlang, and Clojure at that age. I don't know if I can compare its market share to that of Ada at that age. I'm nearly certain that much larger (and definitely more important) programs were written in Ada circa 1990 than are being written in Rust today, but it's hard for me to compare the number of programs.
> 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.
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.
> Rust is a very good middle ground: it's a complex language, but there's lot of room for improving its ergonomics.
I certainly agree Rust is a much better middle ground than either C or ATS. But so is Zig. What's harder to support objectively is that Rust is a better middle ground than Zig (or vice-versa). We just don't know! They both make different tradeoffs that we can't objectively rule on.
So all I'm saying is that we're left with subjective preferences, and that's fine, because that's all we have! So let's stick to saying "I like Rust's design better" or "I like Zig's design better", and stop trying to come up with objective reasons that are just not well-founded.
At the very least, people should stop comparing Zig to C as part of an argument that claims Rust is good because it prevents the vulnerabilities associated with memory-safety violations, as Zig prevents the most dangerous of those, too.
> 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.
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?
I would argue C preprocessor macros are not first class. They are optional.
This anything implements with macros are not first class
In theory it can encode 0 and 1 so anything really, right?
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.
I had the same thought. But one thing was actually very useful to compare "bug densities": deno vs bun. They have comparable codebase sizes as well as comparable ages (7y vs 4y). I'd like to see the same stats for tigerbeetle, which is very carefully designed: if segfaults were relatively high on that as too, well...
> I'd like to see the same stats for tigerbeetle
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!
bun has 10x the issues matching "segfault" as deno
- 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...
> Don’t get me wrong, as a Rust zealot I have my biases and still expect a memory safe implementation to be less crashy
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.
I understand that I have a bias, which is why I was disclosing it. I think it strengthens my question since naively I'd expect a self-professed zealot to buy into the narrative in the blog post without questioning the data.
> My personal take is that if I need more abstraction than Zig, I need something with managed memory--not Rust or C++
You may potentially like D. Its tooling leaves much to be desired but the language itself is pretty interesting.
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.
It may be due to the async/io changes which may have caused a wave of renewed interest in the language
Advent of code is coming, maybe lots of people looking for a language to learn with it?
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.
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
The post didn't say "type conversion", just conversion, like the int with value 3 landing in memory after calling atoi("3").
The post gave the example of casting a float to an int. That is a (type) conversion.
The point is that certain casts/type conversions can change the underlying data.
> like the int with value 3 landing in memory after calling atoi("3").
That's something else entirely. People may colloquially call this "converting a string to an integer", but what we're realling doing here is parsing a string as an integer.
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.
> 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.
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.
A segfault is not the program performing a runtime check and doing a controlled shutdown. A segfault is the OS detecting the program doing something it's not allowed to and killing it.
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
> 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
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.”
Lauding with faint blame ? :)
> The Zig compiler is not particularly fast.
This really makes me question the accuracy of the rest of the article.
I'm really struggling to come up with a compiler that is faster than Zig.
Go, maybe? That's ... about the end of my shortlist.
Odin, Jai, C3, C.
Odin? Isn't that built on llvm?
It uses LLVM as the backend yes.
Jai isn't open source so it is completely and totally irrelevant.
Zig builds C faster than most C compilers. You're going to have to do better than just mention it.
However, if those are the only things that are even possibly faster than Zig, then the Zig compiler qualifies as fast, not slow--which was my original point.
”Zig builds C faster than most C compilers” is a nonsense statement, which I don’t know how to answer.
The fact is simply that despite Zig uses LLVM as a backend in the same way Odin and C3 does, it compiles much slower. Exactly why that is, is something I can only guess at, but the fact is that Zig cached is still much slower to compile than Odin or C3.
(There are a few possible candidates as to why this is so that I identified and can share if it is interesting)
In any case, Zig is only ”fast to compile” if you compare to the triad of infamously slow languages: Swift, C++ and Rust.
Anything else is just hype.
It sure would be nice to have some concrete numbers from those projects to compare to for example ...
Note the discussion about "Incremental Build (libghostty-vt)" https://mitchellh.com/writing/zig-builds-getting-faster
https://biggo.com/news/202506090712_Zig_x86_Backend_Performa...
Embergen is 400kloc Odin, it compiles in about 2s. No incremental compilation or caching to speed it up.
And this is with LLVM as backend.
> Jai isn't open source so it is completely and totally irrelevant.
Worse, there's not even a compiler available. I don't even think there's even a spec.
This is just a convenient excuse. If Zig is to be fast to compile, it doesn’t help to make excuses for it.
Saying something it ”fast enough” because one is comparing with even slower languages is likely what made both Rust and Swift so slow to compile - they all just compared with C++, and it wasn’t until much later - when larger projects appeared - that the problem was taken more seriously. But at that time core architectural and language design concerns were already locked in.
This is why it’s not good for Zig to rest on its laurels and compare with worst of the class. And actually, faster Zig compile times benefits Jai, Odin and C3 as well, because then THOSE compilers can’t afford to slow down either. It’s a win-win.
If we compare with the worst though, then that’s a lose-lose proposition.
> This is just a convenient excuse.
Jai not relevant until open sourced. Period. End of discussion. Do not mention again.
C3 and Odin numbers and discussion certainly welcome.
I answered above.
> Saying something it ”fast enough” because..
Did you mean to reply to me? I was just making a point about the status of the Jai language.
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).
Here's my 2 cents - a programming language (or any technology, smartphones, LLMs etc) has a honeymoon phase - during which everyone's excited about it and extols its virtues and focuses on how different it is from everything else.
Once that's over, people start looking at it with a more pragmatic eye - how much better is this really than what I had before. People start focusing less on the gimmicks and more on everyday usability.
For a programming language to be really popular, it needs that something that captures people's imaginations, but ultimately the stay power is determined by how useful it turns out.
Kotlin and Swift are very practical, but never had any wow features, so they never got hyped, they just quietly got more popular. Go had it with its green threads and channels, but nowadays most people seem to be not using those that much (I don't think there are a ton of instances of Go processes in prod with 10k threads), but otherwise its a solid language.
Rust - it's a solid language as well, and an improvement over C++ in some aspects like package management, but it's borrow checker and programming style is divisive.
Thing is, unlike goroutines there's no avoiding the borrow checker, so a lot of people don't really commit to Rust.
> Go had it with its green threads and channels, but nowadays most people seem to be not using those that much (I don't think there are a ton of instances of Go processes in prod with 10k threads)
Err..this is incorrect. Some projects who scale to 10k go-routines on a single instance regularly are loki and CockroachDB. Even your common NATS server can scale 5k+ go-routines on single instance and it is not uncommon.
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.
> I still like it -- for systems programming, that is.
Just curious, what language(s) do you prefer for things that you don't classify as "systems programming"?
Go and TypeScript are both nice.
> 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/
Rust is #10 on the PyPL (PopularitY of Programming Language) https://pypl.github.io/PYPL.html
But PYPL has shown Objective-C rising to #4 in the last few months....
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 feel like I'm on another planet here. Basically every new piece of software in my space (DB/query engines/streaming engines) is being written in Rust these days. There are like three production projects, total, written in Zig.
Same! I feel like I'm on crazy pills. Multiple folks in this thread are saying stuff like, "yeah, Rust, cool, but it has zero use". How are Linux, Microsoft, AWS, Cloudflare, Firefox, Python's `cryptography`, etc., not real use?
Rust is targeted at strategically important systems (proxies, databases, OSs, VMs, hypervisors, high-throughput servers, cryptography, browsers) and by any measure is making significant inroads into those kinds of systems in real industrial applications, and I'm to believe that Rust adoption is languishing? Am I going insane?
> 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 hear this a lot, but there are many things for which you can use both, so they're competitors. Also most Rust developers want to use it everywhere, including areas where you normally reach out to C, so if people that like Rust want to use it for things that are usually made with C, and Zig is a replacement for C, it seems to me they're competitors, no?
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 those that dislike c for being cumbersome rather than for being less secure?
I wouldn't say "cumbersome", but perhaps "full of warts and historical baggage".
They have some more details here: https://ziglang.org/learn/why_zig_rust_d_cpp/
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
And the thing is Rust's borrow checker isn't such a difficult customer to just eliminate use after free - it's to stop all undefined behavior, like mutable aliasing, data races etc.
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.
"A less rigorous Rust" is in some ways what Zig is trying to be, although that's not the only thing that differentiates the two languages.
Not in the sense I meant to make the comparison - Zig doesn't even pretend to do memory safety - if you don't free something manually it won't get freed - this is way worse level of safety than even what C++ with unique_ptr.
In contrast if Rust only ensured that a reference doesn't outlive the scope it's valid in (allocated and cleaned up via RAII), a lot of problems with Rust would go away, like you could have 2 mutable references pointing to the same thing - it'd still be leak free, but you could have data races, and would need some aliasing heuristics like you have in C.
Still most of the complaining of the borrow checker would go away. Imo this is an idea worth exploring in a language, but I'm sure doing this would upset Rust purists.
> Zig doesn't even pretend to do memory safety - if you don't free something manually it won't get freed
Preventing memory leaks isn't normally what people mean by "memory safety".
As an aside: a common memory management approach used in Zig is to have a dedicated memory pool for an operation and simply free all of the memory after the operation is over instead of freeing individual allocations.
> Preventing memory leaks isn't normally what people mean by "memory safety".
People do sometimes expect it to be encompassed by memory safety, even though the Rust documentation clearly states that it does not prevent memory leaks in safe code and offers several obvious ways to deliberately leak memory.
> Zig doesn't even pretend to do memory safety
This is simply untrue. Zig offers the same spatial memory safety as Rust does, and that is the kind of memory safety that prevents more dangerous vulnerabilities [1] than the kind Rust offers and Zig doesn't (temporal memory safety).
> if you don't free something manually it won't get freed
Rust also isn't free of memory leaks, and doesn't even pretend to guarantee that all allocations are freed. Lack of memory leaks doesn't fall under what Rust defines as memory safety (which Rust defines as guarantees it does provide, excluding those it doesn't).
[1]: https://cwe.mitre.org/top25/archive/2024/2024_cwe_top25.html - Rust and Zig's memory safety prevent #2 and #6 on the list. Rust, additionally, prevents #8. C prevents none of those.
You're responding to the emotional appeal part of my post, not the argument itself - I'm sorry for including it, as it had sidetracked the useful conversation.
Zig doesn't have the memory safety mechanisms of C++ level shared_ptr/unique_ptr.
It's essentially C's malloc/free with the added safety of defer (or possibly arenas), but making sure that the program doesn't leak memory (or have use-after-free bugs) falls on the programmer.
And memory leaks are a much lesser problem, as they usually lead to crashes in OoM situation, than gaining access to random blocks of memory.
Besides, the way you trigger memory leaks in Rust/C++ is with circular references, which are much harder to create than just missing a free() somewhere.
If you have memory that's not tied to a function scope's lifetime in Zig (or the scope of an allocator), then you're essentially have to go by C rules
> Zig doesn't have the memory safety mechanisms of C++ level shared_ptr/unique_ptr.
Zig's memory-safety is spatial, which is the more dangerous kind. Your examples are all temporal, and I don't know if I would call them "safety" as the language doesn't enforce or even encourage their use. For example, I work on one of the world's most foundational C++ projects (the HotSpot virtual machine), where neither shared_ptr nor unique_ptr are used at all; the language doesn't complain. There are reference-counted pointer libraries for Zig, too (although I don't think they're popular).
> It's essentially C's malloc/free with the added safety of defer
No, it isn't. First, unlike C or C++, it offers Rust-like spatial memory safety (again, the more important kind). Second, allocation in Zig is much more explicit than in C or C++.
> Besides, the way you trigger memory leaks in Rust/C++ is with circular references, which are much harder to create than just missing a free() somewhere.
They're also much harder to detect, especially when you have a very explicit memory allocation scheme.
> If you have memory that's not tied to a function scope's lifetime in Zig (or the scope of an allocator), then you're essentially have to go by C rules
Again, Zig doesn't seek to offer temporal memory safety, but it does offer the same level of spatial memory safety as Rust does, and while the "rules" of temporal management are similar to C, the way allocation works in Zig makes for a very different experience. An allocating function in Zig looks very different from its C counterpart.
Zig rejects the temporal memory management schemes of C, C++, and Rust - each for different reasons - and prefers a different kind. Of those, only Rust offers temporal memory safety (in the sense that it's controlled by the language) - albeit for a price - and the rest don't.
I don't understand the distinction between spatial and temporal memory safety - from what I gather, spatial memory safety is just preventing out of bounds access of arrays, dereferencing uninitialized or otherwise invalid pointers. But use after free absolutely results in the same kinds of errors (accessing unused memory, or memory used by someone else).
I also don't understand how one can sidestep the issue of ownership of memory - let's say you have a situation where a given piece of memory has changing or ambiguous ownership - like an event sent between two components, that has allocated some dynamic memory.
I'm not saying this just because, I've encountered this exact issue before - many C libraries have event systems where the ownership is not obvious coming from the code - like the sender owns the event, and if you store a reference to it, then you have a dangling pointer if the sender decides to clean it up.
That's why it's important to make it either obvious who owns what, or have some automatic system like GC or unique_ptr or the borrow checker.
This is a very real issue and the only way you can fix it is to follow strong informal conventions the language has no way of enforcing or even communicating to the user.
You mention Zig has a temporal memory management solution of a different kind - may I ask you what it is, because I haven't really seen it.
> But use after free absolutely results in the same kinds of errors (accessing unused memory, or memory used by someone else).
That two bugs result in the same or similar outcome doesn't mean they're as common or as equally exploitable, which is why, in practice, it is distinctly a more dangerous weakness in the lists maintained by MITRE.
> I also don't understand how one can sidestep the issue of ownership of memory
It's not about side-stepping. There are many kinds of bugs in software, and while we'd like to avoid all of them, some problems are, in practice, more problematic. After all, Rust similarly "sidesteps" - as in doesn't prevent - all non-memory-safety-related weaknesses, some of which are more dangerous than dynamic memory safety. If Zig isn't good enough because it doesn't prevent temporal memory safety violations, then by the exact same logic, Rust isn't good enough because it doesn't prevent, say, injection vulnerabilities, that are more dangerous than temporal memory safety vulnerabilities.
> I'm not saying this just because, I've encountered this exact issue before
Sure, it's a real and serious issue. But injection is a more serious issue, which Rust doesn't prevent, and spatial memory violations are also a more serious issue, which Zig prevents just as Rust does.
> That's why it's important to make it either obvious who owns what, or have some automatic system like GC or unique_ptr or the borrow checker.
It is, but it's even more important to prevent code injection attacks, yet Rust doesn't do that. It all comes down to how much it's worth it to pay to prevent certain bugs.
Rust was built because its designers believed that memory safety wasn't worth paying the higher memory footprint or the lower predictability of more popular memory-safe languages, or else there would have been no need for Rust in the first place. Similarly, it's just as reasonable to believe that the price you pay for temporal memory safety in Rust is not worth it.
> You mention Zig has a temporal memory management solution of a different kind - may I ask you what it is, because I haven't really seen it.
It's not a safe solution by any means (as the language doesn't enforce temporal memory safety, just as C++ doesn't), but memory allocation and deallocation in Zig is not the same as in C or C++. In particular, Zig functions that allocate are explicitly marked by having an Allocator parameter (https://zig.guide/standard-library/allocators/). Unlike in C, in Zig you know which functions allocate and using which allocator. That's how Zig is such a great fit for arenas.
Because Zig is built around custom allocators, you can also choose allocators that offer use-after-free, double-free, and memory-leak protection, and do so selectively (unlike in C): https://sinclairtarget.com/blog/2025/09/getting-my-allocator...
I feel like one thing that wasn't made clear - it's not necessarily the job of the programming language to prevent certain issues - SQL injection for example is something that should be handled by the framework (by not allowing to write SQL directly, but using commands with parameters). All the other higher priority issues are like that, it's not within the scope of a language to prevent such issues, just as Rust or Zig or whatever will never prevent phishing attacks.
As for temporal vs spatial memory safety issues, I agree that Zig does maybe help in that a bit (if component A sends an event to B, then A,B and the events having a separate allocator would work) - though I'm not sure if it doesn't introduce its own footguns (how do I know which allocator needs to free which object).
I don't know I haven't used Zig at all, so no idea how all this works out in practice. Memory issues are 100% solved by languages like Java with GC and I wouldn't say they have made software that much less buggy.
Use after free is number 8 and 9 on the lists respectively... Not like it's way down the list. And most of the things the things above it (other than out of bounds writes/reads which you addressed in another comment) are not something I would consider a programming language can directly affect (e.g. SQL injection, CSRF)
> Not like it's way down the list
I'm not saying it's not important, but we do have to consider whether it's worth the cost.
> And most of the things the things above it (other than out of bounds writes/reads which you addressed in another comment) are not something I would consider a programming language can directly affect (e.g. SQL injection, CSRF)
It actually can.
> 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.
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.
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.
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 ?
It's doing something novel in the systems programming space, and makes a bunch of different trade-offs compared to Rust. That's interesting, even if you might reasonably conclude that Rust is still a better language to use in most cases. It's good to explore different corners of the programming language design space.
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.
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.
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.
> 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.
> Limiting to the "top 5" vulnerabilities by number of CVEs feels like cherry-picking.
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.
> 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.
There is a very clear sharp line between them in that Rust has no undefined behavior outside of an unsafe block. This matters because the effects of undefined behavior -- particularly memory-corrupting undefined behavior -- are unbounded. Security issues caused by logic bugs are limited to only having local effects on the program -- a SQL injection bug can lead to the wrong SQL query being executed, a path traversal bug can lead to the wrong path being accessed, and a shell escaping bug can lead to execution of the wrong shell command. These are severe problems that can lead to data exfiltration or remote code execution, but the relationship between bug and effect is straightforward: "I'm passing user input to a shell here; this could have catastrophic consequences so I'd better review this carefully." In contrast, undefined behavior can happen anywhere in your program, and it can do anything. That is a clear and measurable difference, and emperical evidence from the last 10 years clearly indicates both that it is nigh impossible to write large C/C++ applications without both spatial and temporal memory safety vulnerabilities, and that adopting Rust measurably decreases the incidence of such vulnerabilities.
Zig is certainly an improvement over C on this front, but it is still a UB-heavy language, and that's where the sharp line is. It's hard to make emperical comparisons because Zig is so young, but the comparision between Deno and Bun in the article is a reasonably strong demonstration that Zig has not achieved a comparable level of memory safety to Rust.
> 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.
This doesn't really have anything to do with my point that the CVE list does not provide evidence to dismiss temporal memory safety as irrelevant; it's more of a general statement on writing correct software. But regardless, "Zig has nullability and bounds checks" and "Rust has an affine type system, statically-checked immutability and exclusivity, language-level resource management, and no undefined behavior" are not in the same league of program correctness. Rust wasn't designed after some ideal of memory safety at the expense of clarity and correctness: the lifetime and type system came from a goal of reducing logic bugs in complex concurrent programs, and the fact that it is powerful enough to achieve memory safety without garbage collection was a happy accident. The emperical results that Rust programs have fewer memory-safety vulnerabilities demonstrate that Rust's static approach to software correctness is successful, and not just for the specific problem of memory safety, because Rust's tooling for achieving program correctness is generalizable to arbitrary application invariants. This lines up with my own experience; software I write using Rust is far easier to get right, more reliable, and easier to successfully maintain and refactor than anything else I've done.
Certainly Zig has its strong points as well -- explicitness can reduce complexity and compile times, but it also has downsides of pushing complexity into application code (thus making it harder to review and introducing more opportunities to create mistakes). A proper comparison of the two approaches is worthwhile, but just as "Rust is more memory safe" is an overly reductive generalization of the langauges' approach to software correctness, "there's a rather small difference between Rust and Zig" simply isn't true.
> There is a very clear sharp line between them in that Rust has no undefined behavior outside of an unsafe block.
Yes, but that's an intrinsic language feature whose value needs to be justified somehow. If you justify it by saying it prevents dangerous vulnerabilities, we're back to my point.
> This matters because the effects of undefined behavior -- particularly memory-corrupting undefined behavior -- are unbounded...
While I appreciate this explanation (and I've seen it many times), I hope you understand that it's more speculative and subjective than an empirical finding. At the end of the day, to measure the danger of a problem, we need to see what the actual vulnerabilities/exploits are and how common they are. Clearly, not all undefined behaviours are equally exploitable. That's why we see differences in weakness severity among different kinds of UB.
> emperical evidence from the last 10 years clearly indicates both that it is nigh impossible to write large C/C++ applications without both spatial and temporal memory safety vulnerabilities
Right, and that same empirical evidence shows that spatial violations are the more dangerous ones, and that's exactly why Zig prevents them.
> but the comparision between Deno and Bun in the article
What article? It seems that Bun has had one CVE. If you're talking about undefined behaviour you're, again, making an unjustified extrapolation from it to security. Some undefined behaviour leads to easily exploitable vulnerabilities, some does not.
It's true that in the presence of UB, the compiler could hypothetically do anything, but to get a dangerous vulnerability it has to actually do something that's exploitable, and when we look at vulnerabilities caused by UB, we see that some kinds are more dangerous than others because of that.
BTW, this touches on something that is sometimes misunderstood about UB. UB is defined with respect to a language specification, i.e. in the presence of UB, the language specification does not assign a program a meaning, but the compiler certainly does, because machine code has no UB. The program with the UB needs to compile to an exploitable binary for a vulnerability to exist.
> and that's where the sharp line is
I agree it's a sharp intrinsic line, just as saying that Zig avoids macros is a sharp line, but the impact of that line is anything but sharp. To draw the practical conclusion from it you don't follow the findings, but ignore them!
> This doesn't really have anything to do with my point that the CVE list does not provide evidence to dismiss temporal memory safety as irrelevant
I wasn't dismissing it as irrelevant. I was saying that if Rust's value is in eliminating dangerous vulnerabilities, then Zig has that value, too, and the difference between them isn't large on that particular front.
> are not in the same league of program correctness
Software correctness is something I've been dealing with and writing about for many years, especially formal verification (https://pron.github.io), and I can tell you that you're downright wrong on that. That "more sound guarantees is always the most effective form of improving correctness" is something we know (at least since the nineties) not to be generally true, which is also why the field is looking more and more into unsound methods. For example, Rust and Zig are more likely to effectively write correct programs than ATS, even though ATS is "in a different league" from both of them when it comes to sound guarantees.
We know that sound guarantees can help, but that their cost matters a lot. We also know that reviews and tests and dynamic verification are very effective, sometimes more than sound guarantees.
Rust proponents are free to speculate that, ultimately, Rust's approach leads to more correctness than Zig, and they can base that belief on some findings, and Zig proponents can do exactly the same in the opposite direction, also based on other findings, but both are speculations. People are free to choose which they are more inclined to believe, but the question isn't settled.
> This lines up with my own experience; software I write using Rust is far easier to get right, more reliable, and easier to successfully maintain and refactor than anything else I've done.
I'm not doubting that that's your experience. I'm saying we have no evidence that it's universal, likely to be universal etc. (and I know of some opposite experiences with Rust). Sometimes certain languages just click with certain people, but we can't extrapolate without more observation.
> "there's a rather small difference between Rust and Zig" simply isn't true.
The correctness difference between the two is unknown. It could be small or large and in either direction. The intrinsic differences are, of course, known, but don't really help reach an objective preference. My point was only that if we judge Rust by the vulnerabilities it soundly eliminates, then Zig is not far on that particular metric, and it's certainly much closer to Rust than to C.
Maybe we should be using ATS. Or more likely, maybe we should be using some novel language that doesn't exist yet that brings the benefits of ATS to a language with good tooling and good DX that you can use to build practical system software with - that is, a Rust for ATS instead of C/C++. I think we should be designing programming languages that help eliminate as many classes of bug as possible, and Rust is not the culmination of the line here.
One of the lessons of the past 50 years in software correctness is that sound guarantees are not always the most effective path to correctness. The problem is that proving something correct takes a lot of effort (and there are fundamental computational complexity reasons for that), while unsound methods are significantly cheaper and surprisingly effective in practice. A famous 1996 paper by Tony Hoare [1] expresses amazement at how software had become so reliable without proofs, something that in the 1970s was thought impossible. Since then, the field has moved to enthusiastically adopt more unsound methods.
And remember that a software system, unlike an abstract algorithm, is a physical system that cannot be proven correct, since the behaviour of the physical hardware cannot be proven. We're always dealing in probabilities, and so the question is: how do we get the most value (in terms of reducing the probability of costly bugs) for a unit of effort.
Since the 1970s, the size of software that can be proven correct in practice using deductive methods has only fallen compared to the average size of a program (i.e. the size of acceptably-reliable software we write has grown much more rapidly than the size of software we can prove correct using deductive methods). The largest programs ever proven correct using deductive methods are on the order of 10KLOC.
So the field of software correctness has long ago abandoned the position (held by some in the 70s) that proof is always the most effective way toward correctness.
[1]: https://gwern.net/doc/math/1996-hoare.pdf
> 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.
> But Zig does not eliminate them, but rather it might catch them at runtime
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.
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.
I think a lot of the absolutists around memory safety are just using it as a bludgeon to evangelize their preferred programming language. Otherwise, the position of "memory safety is the most important thing, but we should ignore other languages that provide stronger guarantees" is absurd.
[dead]