Edit: apparently I am replying to the main Zig author? Language evangelism is by far the worst part of Rust and has likely stirred up more anti Rust sentiment than “converting” people to Rust. If you truly care for your language you should use whatever leverage you have to steer your community away from evangelism, not embrace it.
This comment would be a lot better if it engaged with the posted article, or really had any sort of insight beyond a single compile time metric. What do you want me to take away from your comment? Zig good and Rust bad?
> A brief note: 50 seconds is fine, actually!
50 seconds should actually not be considered fine.
Now we get all of this off-topic discussion about Zig. Which I guess is good for you Zig folk... But it's pretty off-putting for me.
whoisyc's comment is extremely on point. As the VP of community, I would really encourage thinking about what they said.
Having concrete proof that something can be done more efficiently is extremely important and, no, I haven't "demonstrated" anything, since my earlier comment would have had way less substance to it without the previous context.
The comment from Andrew is not just random compiler stats, but a datapoint showing a comparable example having dramatically different performance characteristics.
You can find in this very HN submission various comments that assume that Rust's compiler performance is impossible to improve because of reasons that actually are mostly (if not entirely) irrelevant. Case in point, see people talking about how Rust compilation must take longer because of the borrow checker (and other safety checks) and Steve pointing out that, no, actually that part of the compilation pipeline is very small.
> Now we get all of this off-topic discussion about Zig.
So no, I would argue the opposite: this discussion is very much on topic.
One major difference is the way each project considers compiler performance:
The Rust team has always cared to some degree about this. But, from my recollection of many RFCs, "how does this impact compiler performance" wasn't a first-class concern. And that also doesn't really speak to a lot of the features that were basically implemented before the RFC system existed. So while it's important, it's secondary to other things. And so while a bunch of hard-working people have put in a ton of work to improve performance, they also run up against these more fundamental limitations at the limit.
Andrew has pretty clearly made compiler performance a first-class concern, and that's affected language design decisions. Naturally this leads to a very performant compiler.
Do you have a list off the top of your head/do you know of a decent list? I've now read many "compiler slow" thoughtpieces by many people and I have yet to see someone point at a specific feature and say "this is just intrinsically harder".
I believe that it likely exists, but would be good to know what feature to get mad at! Half joking of course
You can't have a language with 100% of the possible runtime perf, 100% of the possible compile speed and 100% of the possible programmer ease-of-use.
At best you can abuse the law of diminishing returns aka the 80-20 rule, but that's not easy to balance and you run the risk of creating a language that's okay at everything, but without any strong selling points, like the stellar runtime performance Rust is known for.
So a better way to think about it is: Given Rust's numerous benefits, is having subpar compilation time really that big of a deal?
As someone who uses Rust as a daily driver at work at zed.dev (about 600K LoC of Rust), and Zig outside of work on roc-lang.org (which was about 300K LoC of Rust before we decided to rewrite it in Zig, in significant part because of Rust's compilation speed), yes - it is an absolutely huge deal.
I like a lot of things about Rust, but its build times are my biggest pain point.
Let's dig into this bit of that, to give you some more color:
> Split compiler/package manager — although it is normal for languages to have a package manager separate from the compiler, in Rust at least this results in both cargo and rustc having imperfect and redundant information about the overall compilation pipeline. As more parts of the pipeline are short-circuited for efficiency, more metadata needs to be transferred between instances of the compiler, mostly through the filesystem, which has overhead.
> Per-compilation-unit code-generation — rustc generates machine code each time it compiles a crate, but it doesn’t need to — with most Rust projects being statically linked, the machine code isn’t needed until the final link step. There may be efficiencies to be achieved by completely separating analysis and code generation.
Rust decided to go with the classic separate compilation model that languages like C use. Let's talk about that compared to Zig, since it was already brought up in this thread.
So imagine we have a project, A, and it depends on B. B is a huge library, 200,000 lines of code, but we only use one function from it in A, and that function is ten lines. Yes, this is probably a bad project management decision, but we're using extremes here to make a point.
Cargo will compile B first, and then A, and then link things together. That's the classic model. And it works. But it's slow: rust had to compile all 200,000 lines of code in B, even though we only are gonna need ten lines. We do all of this work, and then we throw it away at the end. A ton of wasted time and effort. This is often mitigated by the fact that you compile B once, and then compile A a lot, but this still puts a lot of pressure on the linker, and generics also makes this more complex, but I'm getting a bit astray of the main point here, so I'll leave that alone for now.
Zig, on the other hand, does not do this. It requires that you compile your whole program all at once. This means that they can drive the compilation process beginning from main, in other words, only compile the code that's actually reachable in your program. This means that in the equivalent situation, Zig only compiles those ten lines from B, and never bothers with the rest. That's just always going to be faster.
Of course, there are pros and cons to both of these decisions, Rust made the choice it did here for good reasons. But it does mean it's just going to be slower.
That's not what I said. I said it's unlikely that fast compilation cannot be achieved while using LLVM which, I would argue, is proven by the existence of a fast compiler that uses LLVM.
this is a terrible look for your whole community
All Zig code is built in a single compilation unit and everything is compiled from scratch every time you change something, including all dependencies and all the parts of the stdlib that you use in your project.
So you've been comparing Zig rebuilds that do all the work every time with Rust rebuilds that cache all dependencies.
Once incremental is fully released you will see instant rebuilds.
There is ino operator overloading like C, so A + B can only mean one thing.
You can't redeclare a variable, so foo can only map to one thing.
The list goes on.
Basically it was designed to compile faster, and that means many issues on Github have been getting rejected in order to keep it that way. It's full of compromises.
And it can be considerably faster if you use something like subsecond[0] (which does incremental linking and hotpatches the running binary). It's not quite as fast as Zig, but it's close.
However, if that 331ms build above is a clean (uncached) build then that's a lot faster than a clean build of my website which takes ~12s.
What I'm more interested to know is what the runtime performance tradeoff is like now; one really has to assume that it's slower than LLVM-generated code, otherwise that monumental achievement seems to have somehow been eclipsed in very short time, with much shorter compile times to boot.
Your first claim is unverifiable and the second one is just so, so wrong. Even big projects with very talented, well-paid C or C++ devs eventually end up with CVEs, ~80% of them memory-related. Humans are just not capable of 0% error rate in their code.
If Zig somehow got more popular than C/C++, we would still be stuck in the same CVE bog because of memory unsafety. No thank you.
Zig does a lot of things to prevent or detect memory safety related bugs. I personally haven't encountered a single one so far, while learning the language.
> ~80% of them memory-related.
I assume you're referencing the 70% that MS has published? I think they categorized null pointer exceptions as memory safety bugs as well among other things. Zig is strict about those, has error unions, and is strict and explicit around casting. It can also detect memory leaks and use after free among other things. It's a language that's very explicit about a lot of things, such as control flow, allocation strategies etc. And there's comptime, which is a very potent tool to guarantee all sorts of things that go well beyond memory safety.
I almost want to say that your comment presents a false dichotomy in terms of the safety concern, but I'm not an expert in either Rust or Zig. I think however it's a bit broad and unfair.
> Fil-C achieves this using a combination of concurrent garbage collection and invisible capabilities (each pointer in memory has a corresponding capability, not visible to the C address space)
With significant performance and memory overhead. That just isn't the same ballpark that Rust is playing in although hugely important if you want to bring forward performance insensitive C code into a more secure execution environment.
> Fil-C is currently 1.5x slower than normal C in good cases, and about 4x slower in the worst cases.
with room for optimization still. Compatibility has improved massively too, due to big changes to how it works. The early versions were kind of toys, but if Filip's claims about the current version hold up then this is starting to look like a very useful bit of kit. And he has the kind of background that means we should take this seriously. There's a LOT of use cases for taking stuff written in C and eliminating memory safety issues for only a 50% slowdown.
Until you guys write an actual formal specification, the compiler is the language.
The project is adopting Ferrocene for the spec.
Yes, the soundness hole itself is low impact and doesn't need to be prioritized but it undermines the binary "Zig is definitively not memory-safe, while safe Rust, is, by definition, memory-safe" argument that was made in response to me. Now you're dealing with qualitative / quantitative questions of practical impact, in which my original statement holds: "Zig is less memory safe than Rust, but more than C/C++. Neither Zig nor Rust is fundamentally memory safe."
You can of course declare that Safe Rust is by definition memory safe, but that doesn't make it any more true than declaring that Rust solves the halting problem or that it proves P=NP. RustBelt is proven sound. Rust by contrast, as being documented by Ferrocene, is currently fundamentally unsound (though you won't hit the soundness issues in practice).
- If a safe Rust program exhibits a memory safety problem, it is a bug in the Rust compiler that is to be fixed - If a Zig program exhibits a memory safety problem, it is a bug in the Zig program that needs to be fixed, not in the compiler
Wouldn't you agree?
> Ferrocene is intended to document the behavior of the current version of the rustc compiler, so it's just an effort to formalize "the compiler is the language".
I must admit I haven't read the specification, but I doubt they attempt to be "bug for bug" compatible in the sense that the spec enumerates memory safety bugs present in the Rust compiler. But am I then mistaken?
As to the Ferrocene specification, it explicitly states "Any difference between the FLS and the behavior of the Rust compiler is considered an error on our part and the FLS will be updated accordingly."
Proposals to fix the soundness hole in Rust either change the variance rules themselves, or require where clauses in certain places. Either of these changes would require corresponding changes to chapter 4 of the Ferrocene specification.
Right, this is from before it's adopted as the actual spec, because it was from outside the project, and so could not be.
Also, these goalposts are moving: it was "Rust doesn't have a spec" and now it's "I don't like the spec."
Fixing this soundness hole does not require a breaking change to the language. It is an implementation bug, not a problem with the language as specified. But even if it were, Rust's policies around soundness do allow for this, and the project has done it in the past.
If there is a proposed fix to the soundness hole that wouldn't reject some existing sound Rust code, please link to it; none of the proposed fixes I've seen do so. And yes, Rust's policies do allow for breaking changes in pursuit of soundness - likely some day many years from now safe Rust will indeed be sound and guaranteed to be memory safe.
I really don’t see how you can claim with a straight face that the two approaches are the same.
Look, I'm not saying the Zig and Rust approaches are the same. I explicitly stated that Rust is more memory safe than Zig (which is in turn more memory safe than C/C++).
This is because Rust has clearly delineated a "safe" subset of Rust which you have to explicitly opt out of that is mostly sound (and has a goal of eventually being entirely sound), has a culture of encouraging the use of the safe subset, and has taken a good approach to the interfacing of safe and unsafe code (i.e. if unsafe code is properly written and satisfies the exposed contract - despite the compiler being unable to verify this - then safe code can safely be linked with it).
All of this results in extremely low risk of memory corruption for Rust programs in practice (far lower than any other commonly used non-GC language with the sole exception of SPARK).
What you can't do though is reject the notion of memory safety being a sliding scale and draw a binary distinction between languages that are 100% perfectly memory safe and languages that are memory unsafe. Well you can, but Rust will fall on the side of memory unsafe for many years to come. Java (ignoring vendor-specific extensions) falls on the safe side though - the language semantics as specified are sound and it doesn't even have an unsafe subset.
That is the absolute best description of memory safety I’ve heard expressed.
But by implementation and spec definitely not.
Rust is a large and robust language meant for serious systems programming. The scope of problems Rust addresses is large, and Rust seeks to be deployed to very large scale software problems.
These two are not the same and do not merit an apples to apples comparison.
edit: I made some changes to my phrasing. I described Zig as a "toy" language, which wasn't the right wording.
These languages are at different stages of maturity, have different levels of complexity, and have different customers. They shouldn't be measured against each other so superficially.
(EDIT: The parent has since edited this comment to contain more than just "zig bad rust good", but I still think the combative-ness and insulting tone at the time I made this comment isn't cool.)
Respectfully, the parent only offers up a Zig compile time metric. That's it. That's the entire comment.
This HN post about Rust is now being dominated by a cheap shot Zig one liner humblebrag from the lead author of Zig.
I think this thread needs a little more nuance.
That's correct, but slinging cheap shots at each other is not how discussions on this site are supposed to be.
> I think this thread needs a little more nuance.
Yes, but your comment offers none.
Being frustrated by perceived bad behavior doesn't mean responding with more bad behavior is a good way to improve the discourse, if that's your goal here.