Rust has its issues and there are plenty of things to not like about Rust, but this article is giving me the impression that this person has not written much Rust. Unfortunately, many such cases with Rust criticism.
> Memory safety is not that sacred. In fact, for many applications malfunctioning is better than crashing — particulary in the embedded world where Rust wants to be present. You cannot get 99.999% reliability with Rust — it crashes all the time.
Yeah until that memory safety issue causes memory corruption in a completely different area of code and suddenly you're wasting time debugging difficult-to-diagnose crashes once they do start to surface.
There were multiple failures before that `unwrap()` and the argument can easily be made that this is no different than an unchecked exception or a release assertion.
> Sync/Send, Mutex and reference counting (Arc)? Unfortuantely, those lock or simply mess with CPU caches badly, so they are inefficient for multithreaded communication, at least an intensive one. They are safe, but inefficient. Which kinda destroys the first uncompromising thing in Rust — performance.
Doing this the "correct" way in other languages has similar impact? So I'm not sure why Rust forcing you to do the correct thing which causes perf issues is uniquely a Rust issue. Doing this the "just get it done" way in other languages will likely come back to bite you eventually even if it does unblock you temporarily.
There are plenty of times I did a `static mut` global in Rust just to get some shit done and oops, accidentally hit some UB as the project grew.
>Yeah until that memory safety issue causes memory corruption in a completely different area of code and suddenly you're wasting time debugging difficult-to-diagnose crashes once they do start to surface.
Some very solid argument here. However, as already implied in my article, you can get most of the guarantees without losing your sanity. Memory-safety-related problems are important, but they are not the sole source of bugs in applications — as developers of Zed found out.
>Doing this the "correct" way in other languages has similar impact? So I'm not sure why Rust forcing you to do the correct thing which causes perf issues is uniquely a Rust issue. Doing this the "just get it done" way in other languages will likely come back to bite you eventually even if it does unblock you temporarily.
It might be counterintuitive, but garbage collectors in multithreaded code can be very efficient. I mean you just spawn lots of objects with random references in between and then eventually GC untangles the mess — it's zero overhead until the GC cycle. Escape analysis and semantic-reach containers can reduce GC work a lot (so you don't have the classical JVM GC problems). More specialized things like RCU and general quescence-state reclamation can be totally pause-less.
> We actually had a recent Cloudflare outage caused by a crash on unwrap() function
Oh boy, this is going to be the new thing for Rust haters isn't it?
Yes, unwrapping an `Err` value causes a panic and that isn't surprising. Cloudflare had specific limits to prevent unbounded memory consumption, then a bad query returned a much larger dataset than expected which couldn't be allocated.
There are two conclusions: 1) If Cloudflare hadn't decided on a proper failure mode for this (i.e. a hardcoded fallback config), the end result would've been the same: a bunch of 500s, and 2) most programs wouldn't have behaved much differently in the case of a failed allocation.
>There are two conclusions: 1) If Cloudflare hadn't decided on a proper failure mode for this (i.e. a hardcoded fallback config), the end result would've been the same: a bunch of 500s, and 2) most programs wouldn't have behaved much differently in the case of a failed allocation.
So why do they need Rust then? What advantages does it provide? That was the main point of the article — we all wanted a better language, but got another crappy one instead.
The author says "Rust crashes all of the time" and then goes on to invoke the Cloudflare unwrap() as an example of that. Uhhhh... but that was clearly a programmer error, right? Ignoring the possibility of a Result being Err instead of Ok is not something the language is supposed to protect you against.
Yes, but in C++ we would simply not have asserted the result has_value instead of has_error and instead returned some implicit memory corruption. Or, I think that is the author's argument. (I don't subscribe to that point of view.)
There are programming languages/models/runtimes that crash and recover, there are models that gracefully degrade. Rust cannot recover. Neither can C++ in many cases e.g. when you have an exception in a destructor then it's a guaranteed `std::terminate`.
Do note that C did not have such a flaw built into language — C++ authors invented it and Rust inherited this flaw (the authors simply did not feel like it's a flaw). I mean specially designed embedded C code can survive total RAM erasure and still perform some meaningful work (with CPU registers and ROM intact). Or compare it to BEAM that can have processes crash all day long and still continue to work. "Memory safety at all cost" is not a practical requirement — it's theological.
> e.g. when you have an exception in a destructor then it's a guaranteed `std::terminate`.
You can throw in a destructor [1]. You just need to mark that destructor noexcept(false). You do get a guaranteed std::terminate if an exception escapes a destructor while unwinding is already underway, though.
> Do note that C did not have such a flaw built into language
assert() says hi?
> I mean specially designed embedded C code can survive total RAM erasure and still perform some meaningful work (with CPU registers and ROM intact).
Why doesn't a similar argument apply to "specially designed" Rust?
> Or compare it to BEAM that can have processes crash all day long and still continue to work.
Again, nothing stops you from writing Rust that does the same.
- Compile speed. Why do people care so much? Use debug for correctness and iterating your code. You're hardly going to change much between runs, and you'll get an incremental compile. Let rust-analyzer tell you if there are errors before you even try compiling. Let your CI do release optimization in its own time, who cares if CI is slow?
- The cloudflare bug was not caused by rust. Every language needs some way to say "hey this thing is invalid", and that's what happened when the list of AI tools got too long (or whatever their business issue was). Making the app panic was a design choice, not a language choice. Every language has a way to not handle errors.
- Things having unsafe {...} does not make them unreliable. On the contrary, if you run into a memory issue in a rust program, you know where to look for it. The problem in c++ was that the whole program was unsafe, and you then had no way to narrow it down. Memory safety errors are like type errors: a large class of errors that are worth checking for. If you're writing good c++, you have a linter that checks similar things anyway, and if you're disciplined, you've also upgraded warnings to errors. FWIW, I do think the marketing over-emphasizes memory management, because there are a lot of these hard learned lessons that are default in rust but optional in c++.
- Mutable shared state: make bad designs hard to write. Mutable shared state is another one of these eternal bug sources. Use channels and pass messages.
Honestly, it reads like a lot of critiques of Rust: people haven't spent enough time with it, and are not over the learning curve yet. Of course everything is cumbersome before you're used to it.
Yeah. Rust’s Option::None as like null in C++. Unwrapping an option is like checking if something is null and crashing. This "crash from an unwrap" is just a null pointer exception / segfault in any other language. The same bug would be trivial to write in any other language, and with more or less the exact same result. Its just - weirdly news because it was rust code. What?
> Honestly, it reads like a lot of critiques of Rust: people haven't spent enough time with it, and are not over the learning curve yet.
Exactly. I’ve spent years with rust and my complaints are very different. Well, I still wish it compiled faster but all the other stuff is noobie problems. As someone with more experience, my frustration points are things like how async blocks do compiler magic you can’t write yourself. I hate unnameable types. I think Pin is confusing and weird. And the syntax for interacting with raw pointers is unnecessarily inconvenient and ugly.
Yes, rust makes programs with a lot of shared mutable state awkward to write. So don’t program like that. In general, if you write code in language X as if it were a bad version of language Y, you're going to have a bad time. The right question here is if the "rust way" of thinking about your code results in a beautiful program. You can't answer that if you go in with too many preconceptions of how programs should be designed.
You really have to compare articles like this, which are just a bunch of hand waving around the author's biases, against articles with more concrete statements like the Android team finding a 1000x reduction in memory vulnerabilities compared to C/C++. Thanks for your opinion but I'm going to weigh the people who actually use the language more than you.
For my reality of developing for smaller projects than Android, I will absolutely weight Android team's opinion less than the opinion of smaller projects.
Trying to mimic FAANG engineering practices is a fools endeavour that ranges between naiveness at best and CV padding at worst.
> Personally my biggest complain from Rust is that I wish it was more readable. I've seen function signatures that seemed straight out of C++.
There is always a trade-off. You really cannot provide enough information for the compiler without the current signatures. There is a certain point where you cannot compress the information without losing some features.
Idk, it's a general rule of thumb that the more mutable shared state an algorithm has, the worse it scales. So if you're trying to scale something to be concurrent, mutable shared state is an antipattern.
It's lock contention that slows things down more than anything.
But it's really an 'it depends' situation.
The fastest algorithms will smartly divide up the shared data being operated on in a way that avoids contention. For example, if working on a matrix, then dividing that matrix into tiles that are concurrently processed.
> It's lock contention that slows things down more than anything.
It's all flavors of the same thing. Lock contention is slow because sharing mutable state between cores is slow. It's all ~MOESI.
> The fastest algorithms will smartly divide up the shared data being operated on in a way that avoids contention. For example, if working on a matrix, then dividing that matrix into tiles that are concurrently processed.
Yes. Aka shared nothing, or read-only shared state.
This is either performance art or rage bait. The opinions here are so wild. There are so many claims here that are wrong and just strange, it is hard to know where to start.
You cannot go along like “I’m writing a cold path high-level code, I don’t need performance, I don’t need to go deeper into lifetime handling, I just want to write a high level logic”. You will be forced into the low level nuances every time you write a single line of Rust. There is no garbage collector for Rust and will never be — you will have to semi-manually pack all your data into a tree of ownership. You have to be fluent in ownership, borrowing, traits to write just a few lines of code.
It's still quite rough around the edges, but Crystal is a fun choice for this type of thing. If you want a readable high level language and sane package manager that compiles to reasonably performant machine code, it's worth a look.
Zig... is surprisngly used a lot given how rough the state of the language is. It makes me think that if it ever reaches v1.0, it has a very good chance of being at least a "Kotlin", probably a "elixir"/"haskell", and a decent enough shot of "typescript".
> telling a victim “but the memory was not corrupted in the crash” is a weak consolation. We actually had a recent Cloudflare outage caused by a crash on unwrap() function. It’s probably the strongest point of my whining: Rust is memory safe and unreliable. The price of memory safety was reliability
This is incorrect in a way that honestly feels insulting. It's not the language's fault that you called the `crash()` function—every language has a way to terminate execution, and for good reason. Crashing isn't even necessarily incorrect behaviour; that's how you pass the error up to the infrastructure layer for handling. The problem here existed at a system design level, not a language level.
For the author to paraphrase this (bad) critique like this:
> You cannot get 99.999% reliability with Rust — it crashes all the time.
is outright dishonest and insulting to me as a reader.
Spending out something better isn’t easy. As an applications developer I want to ask “Why don’t you just use Java/C#?” and I’d go so far to say that the software reuse revolution behind Java was not OO or it’s particular approach to OO but rather the garbage collector.
That is, building applications out of premade parts is a struggle in C or C++ or rust because memory management is part of the API. C devs would be very concerned about having control of memory allocation and would like to have the choice of reusing a buffer from the application in the library or have the library allocate into an arena managed by the application, etc. It’s complicated enough that libraries can’t reasonably support every scenario application developers would like and ultimately tough because to free something the application has to know if the library is done with it or the library has to know if the application is done with it…. However, the garbage collector knows!. In the end there are a lot of libraries you can’t really write for C or if you can write them you have to write them assuming the application allocates or a certain way or you lose the benefit of being in control of allocation that C allegedly gives you.
On the flip side I think C is too high level in some cases, for instance you come to think the gymnastics involved in written embedded C or device drivers are normal but there are quite a few things that are a little bit cleaner in assembly language and I write things for AVR-8 that are rather small but it drives me nuts that C is moving the stack pointer around and following calling conventions that are not at all necessary for these particular programs.
I had friends who worked in the IBM Mainframe world where it is still common for applications to have bits written in assembly because of efficiency or to get finer control than you can get with COBOL. Part of the COBOL puzzle is that you have to be a Macro Assembler programmer to work on that stuff and you can’t just port it to GNU COBOL on Linux without also porting the assembly!
We’re still living in a multi-architecture world so the interesting idea of trying to make it easier to write assembly (imagine a super macro assembler with an integrated theorem prover) is a non-starter. Let x86 founder for a decade and if RISC-V makes no progress that picture could be different in a few years.
Node.js and Go are both memory safe, as are Python, Ruby, and Java. "Memory safe" is a term of art referring to susceptibility to memory corruption vulnerabilities in code written by an ordinary practitioner of the language. Almost invariably, attempts to show languages like Go and Python as memory-unsafe involve a programmer deliberately working to defeat the language. But you can do that in any language, including Rust.
There are essentially just two mainstream memory-unsafe languages: C and C++.
"Memory corruption vulnerabilities" != "concurrency bugs" or even data corruption. The last thread I was in about this, someone pointed to Go segfaults and said "see! memory corruption!" (obviously: no).
An easy response to claims like this: there's a huge tower of software written Go at this point, including the entire K8s ecosystem. Show me the memory corruption exploits.
The amount of Rust code using unsafe is a major issues for a language build around safety. And yes, the same argument can also be made about Go having a unsafe keyword.
The fact that there exist crates to detected the usage of unsafe in dependencies, shows that its a rather liberal used keyword. Geiger comes to mind.
Unsafe in a language like Go is very rare, mostly because people do not program at such low system level to get the max performance out of it.
Rust code with unsafe: 1.7M
Go code with unsafe: 400k
and for comparison, Go has about 2.3x the amount of repo's. So Rust has about a 10x more usage of the unsafe keyword.
I agree, and I personally wouldn't call golang memory safe for that reason. Thomas's semi-definition includes the word "vulnerability", which narrows the scope so much that golang fits under the bar, since the common data race that causes memory corruption hasn't been shown to be exploitable without being contrived.
My personal definition of memory safety for a language like golang would specify that you can't cause this sort of memory corruption without an explicit call to unsafe, but there's no real definition to fall back on.
The same thing happens any time a message board confronts a professional term of art. The same thing happened with "zero trust", where you'd have long wooly debates about what was meant by "trust", but really the term just meant not having a conventional perimeter network architecture. Sorry, but the term as used in industry, by the ISRG, and in government guidance refers specifically to vulnerabilities.
> People create lies to gain power and money. Which is kinda what I was supposed to do, but for random reasons I went rogue and chose sanity instead.
> I am anti-bullshit.
These "contrarian for the sake of being contrarian" vibes naturally flow into this Rust post. Rust has a ton of faults, but this is was a very shallow critique.
> "there is just no perfect correctness possible in the Turing machine model"
Grrr. Clueless people keep saying that. People have been verifying programs for over forty years now. Formal correctness in terms of not violating assertions is possible for most useful programs. As someone pointed out about the Microsoft Static Driver Verifier, if you're program is anywhere near undecidability, it has no business being in the kernel. This not a legit criticism.
Theorem prover ideas have an impact on Java, Rust and a lot of languages —- it really would be great to see something that accomplishes even more…. Would be nice if you could have a program that lives side by side with a correctness proof.
> Unfortunately, it’s impossible to make Rust compile fast. The problem is inherent to all similar generics-heavy languages, like Haskell.
I don't think this is correct, strictly speaking. Furthermore, I think this conflates two common causes of slow generic compilation:
- Type-checking them can take a lot of time
- Generics may be implemented in a way that generates a lot of code
Neither of those are required for generics-heavy languages (e.g., OCaml is generally considered to compile fast despite having a "complex" type system), and the presence of one doesn't necessarily require the other - a hypothetical "simple" generics system with heavy use of monomorphization can end up taking a long time to compile, and a "complex" generics system that erases types may take a while to type-check but could compile fast after that.
> Put a non-optional borrow-checker on top of it
From my understanding the borrow checker usually takes up a small fraction of the time needed to compile. There are cases where that's not true, but I think people tend to overestimate its impact on compile times.
> There are ways to implement unsafe programs that still don’t execute remote code or leak secret — they only corrupt user data and act sporadically.
Reliably implementing unsafe programs that don't have RCEs or leak secrets but still corrupt data and "act sporadically" seems like a very peculiar combination of requirements to me, if it's even possible. "Act sporadically" is also quite nebulous, and depending on the precise issue may in fact be an RCE or secret leak in hiding - after all, it's not that uncommon for exploits to start their life as someone noticing a crash.
> It’s probably the strongest point of my whining: Rust is memory safe and unreliable. The price of memory safety was reliability in addition to the developer’s sanity
I think that is actually one of the weakest points. I didn't see any support for a claim that memory safety necessarily requires trading off reliability, let alone that that is what Rust does.
> Step into the shared mutable state — and there a memory corruption is not an exception, it’s a rule. You have to handle the corruptions, you cannot simply crash.
What definition of "memory corruption" is being used here? I didn't think that's the kind of thing that you usually "handle"...
> Which kinda destroys the first uncompromising thing in Rust — performance.
I feel this misunderstands Rust's priorities. (Safe) Rust prioritizes safety over performance, and that has been a well-known tradeoff for basically its entire lifetime. If you want performance at the expense of safety, that is what `unsafe` is for.
> So, to reiterate, the second you step into the shared mutable state you lose every single advantage of Rust. Which is kinda rational considering that the main concept of Rust was to never employ a shared mutable state.
This misses another useful bit of Rust, which is the ability to contain unsafety to clearly-delimited sections of your codebase.
> T, T&, T*, std::optional, std::unique_ptr to describe similar things, each broken in its own way
How is `T` broken? How are the other things broken?
No matter what language you use, most of the code running between what you wrote and the hardware will be written in C. Your choice for the 1% on top is not very consequential. There is still a huge attack surface area no matter what.
> Its compilation is slow. I mean SLOW. Slower than C++.
No way. Maybe Rust 1.0, but it's steadily improved and it's definitely faster than C++ now.
> It’s complex. Just as complex as C++.
True, but the problem with C++'s complexity is that you have to memorise all of it or you'll accidentally invoke UB. It's so complex that is basically impossible.
Rust is complex but most of the time the compiler will tell you if you got it wrong. There are exceptions of course (lots of async footguns) but it's still night and day.
> Memory safety is not that sacred. In fact, for many applications malfunctioning is better than crashing
Not sure I really need to counter this...
> When handling lots of mutable shared state (GUI, DB, stateful services, OS/hardware), the performance of native Rust memory model is subpar, and non-native unsafes just leave you with slow compilation, high complexity, and no memory safety in the end — which makes Rust practically meaningless for heavy mutable state jobs.
Not totally clear what he's getting at here. Maybe the ergonomics of GUI style programming which are still being figured out? Hardly a deal breaker though is it? There are plenty of C/C++ GUI libraries with terrible ergonomics and the only one that is actually great (Qt) had to use a custom language extension for decades to achieve that.
> So, is the Rust bad or good? It’s neither. It’s a mediocre programming language with thousands of man-month put into its development
I would love to hear what he thinks a good programming language is, because I can easily pick more holes in any other language than he has.
He hates on C++ pretty much the same as he does on Rust. Your argument seems to be that Rust is better than C++, which is akin to trying to make the case that Cholera is better than Smallpox.
Language wars are boring and pointless, they all have areas of suckage. The right approach is to pick whichever one is the least worst for the job at hand.
> I would love to hear what he thinks a good programming language is
Also, not the OP, but I bet it is Python.
- No compile time.
- Not as complex as C++.
- Memory Safety, while they don't care about this apparently, but nice to have.
- Plenty of ergonomic GUI style programming, like PySide (Qt for python).
Of course, I know there are many downsides to python. Such as interpreted languages, especially ones that are duck typed are very slow to run... but that's not one of the OP's complaints.
The article complained that a Rust program can crash when you call `unwrap`—in fact, the author says that's their strongest critique. Python crashes when you call `sys.exit`, so it's no better.
Unfortunately I don't think their critique is really coherent—this is an absurd standard.
Unless I need close to 100% memory safety with no compromise in performance I'd rather write Zig, Odin or Go.
Zig and Odin are much more enjoyable to write and provide enough safety for a lot of applications, and Go gets you 90% of the performance of Rust without the complexity.
I think we’ve officially reached the inflection point where the Rust haters have become more annoying than the Rust evangelists. Maybe in a couple years we will finally be able to stop writing blog post about it.
So, is the Rust bad or good? It’s neither. It’s a mediocre programming language with thousands of man-month put into its development — this fact alone makes Rust a viable tool, just because you can pick it from the shelf and employ as-is. This blog was generated with Zola, written in Rust — I did not have to write a single line of Rust code to use it. And the Rust is a good fit for Zola SSG because of its non-interactive nature with one-way flow of immutable data. Just, please, don’t run around screaming “we should all switch our development to Rust because it’s the best programming language”.”
Man, I explained it in the first sentence of the article — it's not bad, it's much worse than it could have been. The main body of the article is not hate — it's plain facts. Everybody working on a significant Rust codebase agrees that Rust compilation takes eternity. Complexity? I know people that like complexity, they would say "that's a great language because of how hard it is to write a program in it!" — complexity would feel like a praise for them. Shared state? "Just don't use it, you are doing it wrong". That's is, where is the hatred?
> The main body of the article is not hate — it's plain facts. Everybody working on a significant Rust codebase agrees ...
Lol. Its not facts. Its a description of frustrating things you've experienced working with rust, dressed up as "deep truths about the language". You don't speak for the rust community. This article would be much more interesting if you just talked about your own experience without pretending your issues are universal.
Re: compilation time, in the 2024 state of rust survey 25% of rust developers said slow builds was a big problem. And thats a lot of people! But 19% of people said its not a problem at all for them. Its certainly not "everyone".
I suspect if you keep using rust, the things that annoy you about the language will change a lot over time. Some things will stop bothering you, and some things will start bothering you a lot more! (Like IMO Rc/Box/etc isn't a big deal. Once you learn to structure your code in a rusty way, you almost never need that stuff.)
I really like rust now. But I found learning rust to be incredibly painful. I get why you're struggling with it. But please don't confuse your struggle for universal truths about rust. You're only one person.
Can you give some examples? C/C++ devs seem to be very upset about rust content. Where all these annoying articles claiming we should rewrite everything in rust? They must be all over the place given how much C/C++ devs are upset. But I don't think I've read any?
There was that article from the android team about how rust improved their development workflow[1]. Is that what you're talking about? Was that article emotionally upsetting? Do you wish it wasn't written? What in particular is upsetting? Do you want people to stop writing technical articles to protect your feelings?
I haven’t seen a positive Rust article hit HN in over a year. Seems the zeitgeist has turned against it. All it took was the US government giving the thumbs up I guess.
On the other hand, lets face it: most of the time security in IT systems is the least priority. I mean after shipping fast, iterate fast, better performance, compatibility, architecture soundness (whatever it is), convenient tests, docs with UML diagram, well-designed interface — and somewhere in a distant drawer on the bottom you may find a note about security issues. It's often times people talk about importance of security after it destroyed the whole business.
We need more of the security. We probably don't need the Rust though.
security incident destroying a business is so rare and penalties for security breaches are non-existent and hence while everyone talks “security is important” it really isn’t all that important - in vast majority of the situations. I mean, fucking experian, the company whose sole purpose for existence is collecting and keeping data on everyone safe leaked everyone’s data and everyone was like “oh ok, thats cool, carry on…”
We really just need official/honest guidance on Rust for what works and what doesn't. The classic example is the dodging around cyclic datastructures.
Tl;DR Rust doesn't support any form of cyclic datastructure without indirection or unsafe. The indirection tooling is weak, and most real examples simply switch to unsafe rust. Unsafe rust is completely fine if you know what you are doing with memory, and is ok to use in these situations.
There are a few other gotchas that we just need to be clear about, some of these gotchas are limiting for developing higher level software and some are not e.g. String handling. If you are comfortable with unsafe, the rust toolchain is vastly superior to C/C++ development making it as close to an ideal replacement as we are likely to get.
A couple years ago I implemented a btree (technically order statistic tree) in a couple thousand lines of unsafe rust for a project. I wrote it more or less how I'd do it in C. Each internal node and leaf node was a separate heap allocation and internal nodes had an array of child pointers. It was surprisingly hard to program up. And complicated!
In my opinion, unsafe rust code is worse to use than C because rust is missing the arrow operator. And rust still requires strict aliasing to be followed even in unsafe code. This makes complex unsafe code very hard to implement correctly. Like, it’s easy for something to look right and work correctly but for MIR to still find subtle issues.
Eventually I rewrote my btree on top of Vecs. My node & leaf pointers are now array indices. The result? There is no longer any unsafe code. The code has become significantly simpler and it now runs ~10% faster than it did before, which is shocking to me. I guess bounds checks are cheaper than memory fragmentation on modern computers.
I have so many thoughts having done that. First, I think this is actually the right way to write rust. Yes, manually keeping track of which array slots are in use is inconvenient. But unsafe & pointers are also quite inconvenient in rust. Programming like this makes use after free bugs possible to write. But it’s still memory safe by rust’s definition. It’s impossible to get arbitrary heap corruption because there are no raw pointers. And the indexes are bounds checked.
I also don’t think the resulting code is any worse than the equivalent C++. Everyone talks about memory safety but IMO rust’s best features are enums, traits, cargo, match expressions and so on. Even when you do a run around the borrow checker, it’s these features which make me keep coming back to rust.
I agree better guidance would be nice, but so many words have been spilled on rust already. Would you find content talking about subtle stuff like this? Sometimes the only way to learn is by trying stuff out.
>Eventually I rewrote my btree on top of Vecs. My node & leaf pointers are now array indices. The result? There is no longer any unsafe code. The code has become significantly simpler and it now runs ~10% faster than it did before, which is shocking to me. I guess bounds checks are cheaper than memory fragmentation on modern computers.
Optimizations are very complex and potentially fragile in Rust, LLVM has to sort through tons of generated IR, so it might be just that native Rust structures are optimized better for compilation. Particulary, Rust is able to optimize out some bound checks.
Do note that binary trees are mostly an obsolete legacy today — they are way too cache-unfriendly. I mean you could have written similar code in C++ using std::vector or std::dequeue and get the bounds checking too.
>Everyone talks about memory safety but IMO rust’s best features are enums, traits, cargo, match expressions and so on
C++20 with concepts mostly reproduce the traits. C++17 with std::variants emulate enum/tagged union. Match is unmatched by C++, that's true.
Cargo is good for as long as there are few packages in there. Large projects already suffer from five versions of serde in one build and dependencies on FFI-connected libs that cargo itself cannot build. I mean look at the NPM nightmare — and they've mostly dodged FFI-s.
> Do note that binary trees are mostly an obsolete legacy today — they are way too cache-unfriendly. I mean you could have written similar code in C++ using std::vector or std::dequeue and get the bounds checking too.
As a sibling comment said, its a b-tree not a binary tree. B-trees are - as far as I know - the fastest data structure on modern computers for the class of problems they solve.
And yes, I think if I ever go back to C/C++ I'll try this approach out. It might also work great in GC languages like JS/TS/C#/Go because there's fewer pointers to keep track of.
> Cargo is good for as long as there are few packages in there. Large projects already suffer from five versions of serde in one build and dependencies on FFI-connected libs that cargo itself cannot build. I mean look at the NPM nightmare — and they've mostly dodged FFI-s.
I haven't run into the "five versions of serde" problem, but I can easily imagine it. I've lived NPM nightmares more times than I can count. But I'd still prefer that to all the problems you get from CMake, autotools and Makefiles. At this rate we're going to get self driving cars before we have a single sane build system for C.
> Do note that binary trees are mostly an obsolete legacy today — they are way too cache-unfriendly
BTree is not Binary Tree. It's B-Tree and is cache-friendly
> C++20 with concepts mostly reproduce the traits.
C++20 concepts are not the same as traits. Concepts are structural and awkward to use compared to Traits which are nominal. There are other important differences, too.
Zig currently sits in the hype cycle like Rust/Ruby/Lisp/etc once did here. Eventually something will come along and Zig will be in the hate cycle.
In reality none of these things need the religious wars that seem to go back and forth. It's just an incredibly unfortunate and annoying aspect of how programmer-centric communities tend to go.
>ORMs, OOP, Git, JavaScript bloat, Linux vs Windows
ORM and OOP whine is niche, agreed. Linux vs Windows is irrelevant because windows runs linux nowadays — I don't think I've read a single article about it.
Git? Okay, mostly circumvented by solutions that don't carry any implementation from the original Git, but have "git" in the product name.
Javascript bloat? I'm pretty sure that's still a hot topic. I don't remember it being solved, do you? Like if I open website and it greets me with a window suggesting to apply cookie policies for 300 (three hundred) trackers on the website — isn't it worth talking about?
"they only corrupt user data and act sporadically"
The author dismisses these defects, but try telling a financial institution that it's "only" corrupt user data when the books don't balance. Explain to an aerospace company that acting sporadically is just fine.
Rust has its issues and there are plenty of things to not like about Rust, but this article is giving me the impression that this person has not written much Rust. Unfortunately, many such cases with Rust criticism.
> Memory safety is not that sacred. In fact, for many applications malfunctioning is better than crashing — particulary in the embedded world where Rust wants to be present. You cannot get 99.999% reliability with Rust — it crashes all the time.
Yeah until that memory safety issue causes memory corruption in a completely different area of code and suddenly you're wasting time debugging difficult-to-diagnose crashes once they do start to surface.
> We actually had a recent Cloudflare outage caused by a crash on unwrap() function: https://blog.cloudflare.com/18-november-2025-outage/
There were multiple failures before that `unwrap()` and the argument can easily be made that this is no different than an unchecked exception or a release assertion.
> Sync/Send, Mutex and reference counting (Arc)? Unfortuantely, those lock or simply mess with CPU caches badly, so they are inefficient for multithreaded communication, at least an intensive one. They are safe, but inefficient. Which kinda destroys the first uncompromising thing in Rust — performance.
Doing this the "correct" way in other languages has similar impact? So I'm not sure why Rust forcing you to do the correct thing which causes perf issues is uniquely a Rust issue. Doing this the "just get it done" way in other languages will likely come back to bite you eventually even if it does unblock you temporarily.
There are plenty of times I did a `static mut` global in Rust just to get some shit done and oops, accidentally hit some UB as the project grew.
>Yeah until that memory safety issue causes memory corruption in a completely different area of code and suddenly you're wasting time debugging difficult-to-diagnose crashes once they do start to surface.
Some very solid argument here. However, as already implied in my article, you can get most of the guarantees without losing your sanity. Memory-safety-related problems are important, but they are not the sole source of bugs in applications — as developers of Zed found out.
>Doing this the "correct" way in other languages has similar impact? So I'm not sure why Rust forcing you to do the correct thing which causes perf issues is uniquely a Rust issue. Doing this the "just get it done" way in other languages will likely come back to bite you eventually even if it does unblock you temporarily.
It might be counterintuitive, but garbage collectors in multithreaded code can be very efficient. I mean you just spawn lots of objects with random references in between and then eventually GC untangles the mess — it's zero overhead until the GC cycle. Escape analysis and semantic-reach containers can reduce GC work a lot (so you don't have the classical JVM GC problems). More specialized things like RCU and general quescence-state reclamation can be totally pause-less.
> We actually had a recent Cloudflare outage caused by a crash on unwrap() function
Oh boy, this is going to be the new thing for Rust haters isn't it?
Yes, unwrapping an `Err` value causes a panic and that isn't surprising. Cloudflare had specific limits to prevent unbounded memory consumption, then a bad query returned a much larger dataset than expected which couldn't be allocated.
There are two conclusions: 1) If Cloudflare hadn't decided on a proper failure mode for this (i.e. a hardcoded fallback config), the end result would've been the same: a bunch of 500s, and 2) most programs wouldn't have behaved much differently in the case of a failed allocation.
>There are two conclusions: 1) If Cloudflare hadn't decided on a proper failure mode for this (i.e. a hardcoded fallback config), the end result would've been the same: a bunch of 500s, and 2) most programs wouldn't have behaved much differently in the case of a failed allocation.
So why do they need Rust then? What advantages does it provide? That was the main point of the article — we all wanted a better language, but got another crappy one instead.
The author says "Rust crashes all of the time" and then goes on to invoke the Cloudflare unwrap() as an example of that. Uhhhh... but that was clearly a programmer error, right? Ignoring the possibility of a Result being Err instead of Ok is not something the language is supposed to protect you against.
Yes, but in C++ we would simply not have asserted the result has_value instead of has_error and instead returned some implicit memory corruption. Or, I think that is the author's argument. (I don't subscribe to that point of view.)
There are programming languages/models/runtimes that crash and recover, there are models that gracefully degrade. Rust cannot recover. Neither can C++ in many cases e.g. when you have an exception in a destructor then it's a guaranteed `std::terminate`.
Do note that C did not have such a flaw built into language — C++ authors invented it and Rust inherited this flaw (the authors simply did not feel like it's a flaw). I mean specially designed embedded C code can survive total RAM erasure and still perform some meaningful work (with CPU registers and ROM intact). Or compare it to BEAM that can have processes crash all day long and still continue to work. "Memory safety at all cost" is not a practical requirement — it's theological.
> Rust cannot recover.
catch_unwind exists for a reason.
> e.g. when you have an exception in a destructor then it's a guaranteed `std::terminate`.
You can throw in a destructor [1]. You just need to mark that destructor noexcept(false). You do get a guaranteed std::terminate if an exception escapes a destructor while unwinding is already underway, though.
> Do note that C did not have such a flaw built into language
assert() says hi?
> I mean specially designed embedded C code can survive total RAM erasure and still perform some meaningful work (with CPU registers and ROM intact).
Why doesn't a similar argument apply to "specially designed" Rust?
> Or compare it to BEAM that can have processes crash all day long and still continue to work.
Again, nothing stops you from writing Rust that does the same.
[0]: https://doc.rust-lang.org/std/panic/fn.catch_unwind.html
[1]: https://cpp.godbolt.org/z/ao4cf3zrr
Nothing forces you to panic in Rust any more than anything forces you to call abort() in C.
is conceptually no different to: don't write either if you don't want to halt.I tend to disagree.
- Compile speed. Why do people care so much? Use debug for correctness and iterating your code. You're hardly going to change much between runs, and you'll get an incremental compile. Let rust-analyzer tell you if there are errors before you even try compiling. Let your CI do release optimization in its own time, who cares if CI is slow?
- The cloudflare bug was not caused by rust. Every language needs some way to say "hey this thing is invalid", and that's what happened when the list of AI tools got too long (or whatever their business issue was). Making the app panic was a design choice, not a language choice. Every language has a way to not handle errors.
- Things having unsafe {...} does not make them unreliable. On the contrary, if you run into a memory issue in a rust program, you know where to look for it. The problem in c++ was that the whole program was unsafe, and you then had no way to narrow it down. Memory safety errors are like type errors: a large class of errors that are worth checking for. If you're writing good c++, you have a linter that checks similar things anyway, and if you're disciplined, you've also upgraded warnings to errors. FWIW, I do think the marketing over-emphasizes memory management, because there are a lot of these hard learned lessons that are default in rust but optional in c++.
- Mutable shared state: make bad designs hard to write. Mutable shared state is another one of these eternal bug sources. Use channels and pass messages.
Honestly, it reads like a lot of critiques of Rust: people haven't spent enough time with it, and are not over the learning curve yet. Of course everything is cumbersome before you're used to it.
> The cloudflare bug was not caused by rust
Yeah. Rust’s Option::None as like null in C++. Unwrapping an option is like checking if something is null and crashing. This "crash from an unwrap" is just a null pointer exception / segfault in any other language. The same bug would be trivial to write in any other language, and with more or less the exact same result. Its just - weirdly news because it was rust code. What?
> Honestly, it reads like a lot of critiques of Rust: people haven't spent enough time with it, and are not over the learning curve yet.
Exactly. I’ve spent years with rust and my complaints are very different. Well, I still wish it compiled faster but all the other stuff is noobie problems. As someone with more experience, my frustration points are things like how async blocks do compiler magic you can’t write yourself. I hate unnameable types. I think Pin is confusing and weird. And the syntax for interacting with raw pointers is unnecessarily inconvenient and ugly.
Yes, rust makes programs with a lot of shared mutable state awkward to write. So don’t program like that. In general, if you write code in language X as if it were a bad version of language Y, you're going to have a bad time. The right question here is if the "rust way" of thinking about your code results in a beautiful program. You can't answer that if you go in with too many preconceptions of how programs should be designed.
You really have to compare articles like this, which are just a bunch of hand waving around the author's biases, against articles with more concrete statements like the Android team finding a 1000x reduction in memory vulnerabilities compared to C/C++. Thanks for your opinion but I'm going to weigh the people who actually use the language more than you.
The android team wasn't comparing like to like, though people seem to gotten the impression they were.
Hard disagree.
For my reality of developing for smaller projects than Android, I will absolutely weight Android team's opinion less than the opinion of smaller projects.
Trying to mimic FAANG engineering practices is a fools endeavour that ranges between naiveness at best and CV padding at worst.
The author would probably find joy in using Zig.
Personally my biggest complain from Rust is that I wish it was more readable. I've seen function signatures that seemed straight out of C++.
> Personally my biggest complain from Rust is that I wish it was more readable. I've seen function signatures that seemed straight out of C++.
There is always a trade-off. You really cannot provide enough information for the compiler without the current signatures. There is a certain point where you cannot compress the information without losing some features.
It's always an option to create type aliases, but there's a bit of "robbing Peter to pay Paul" happening when you do that.
You make the signature shorter but also take away the ability for the programmer to quickly understand what code is doing.
Mutable shared state is a feature, not a bug.
It's true that it's easier to write correct async code using immutable shared data or unshared data.
However, it's very hard if not impossible to do fast and low memory concurrent algorithms without mutable shared state.
Idk, it's a general rule of thumb that the more mutable shared state an algorithm has, the worse it scales. So if you're trying to scale something to be concurrent, mutable shared state is an antipattern.
It's lock contention that slows things down more than anything.
But it's really an 'it depends' situation.
The fastest algorithms will smartly divide up the shared data being operated on in a way that avoids contention. For example, if working on a matrix, then dividing that matrix into tiles that are concurrently processed.
> It's lock contention that slows things down more than anything.
It's all flavors of the same thing. Lock contention is slow because sharing mutable state between cores is slow. It's all ~MOESI.
> The fastest algorithms will smartly divide up the shared data being operated on in a way that avoids contention. For example, if working on a matrix, then dividing that matrix into tiles that are concurrently processed.
Yes. Aka shared nothing, or read-only shared state.
This is either performance art or rage bait. The opinions here are so wild. There are so many claims here that are wrong and just strange, it is hard to know where to start.
You cannot go along like “I’m writing a cold path high-level code, I don’t need performance, I don’t need to go deeper into lifetime handling, I just want to write a high level logic”. You will be forced into the low level nuances every time you write a single line of Rust. There is no garbage collector for Rust and will never be — you will have to semi-manually pack all your data into a tree of ownership. You have to be fluent in ownership, borrowing, traits to write just a few lines of code.
It's still quite rough around the edges, but Crystal is a fun choice for this type of thing. If you want a readable high level language and sane package manager that compiles to reasonably performant machine code, it's worth a look.
the issues with Crystal, nim, zig, is that they have zero changes to be bigger.
crtystal and nim, probably not.
Zig... is surprisngly used a lot given how rough the state of the language is. It makes me think that if it ever reaches v1.0, it has a very good chance of being at least a "Kotlin", probably a "elixir"/"haskell", and a decent enough shot of "typescript".
> You have to be fluent in ownership, borrowing, traits to write just a few lines of code.
> Rust sacrificed sanity and practicality for memory safety
skill issue
> telling a victim “but the memory was not corrupted in the crash” is a weak consolation. We actually had a recent Cloudflare outage caused by a crash on unwrap() function. It’s probably the strongest point of my whining: Rust is memory safe and unreliable. The price of memory safety was reliability
This is incorrect in a way that honestly feels insulting. It's not the language's fault that you called the `crash()` function—every language has a way to terminate execution, and for good reason. Crashing isn't even necessarily incorrect behaviour; that's how you pass the error up to the infrastructure layer for handling. The problem here existed at a system design level, not a language level.
For the author to paraphrase this (bad) critique like this:
> You cannot get 99.999% reliability with Rust — it crashes all the time.
is outright dishonest and insulting to me as a reader.
I was waiting for the part where author advocates for what they like but no it’s just a rant
Spending out something better isn’t easy. As an applications developer I want to ask “Why don’t you just use Java/C#?” and I’d go so far to say that the software reuse revolution behind Java was not OO or it’s particular approach to OO but rather the garbage collector.
That is, building applications out of premade parts is a struggle in C or C++ or rust because memory management is part of the API. C devs would be very concerned about having control of memory allocation and would like to have the choice of reusing a buffer from the application in the library or have the library allocate into an arena managed by the application, etc. It’s complicated enough that libraries can’t reasonably support every scenario application developers would like and ultimately tough because to free something the application has to know if the library is done with it or the library has to know if the application is done with it…. However, the garbage collector knows!. In the end there are a lot of libraries you can’t really write for C or if you can write them you have to write them assuming the application allocates or a certain way or you lose the benefit of being in control of allocation that C allegedly gives you.
On the flip side I think C is too high level in some cases, for instance you come to think the gymnastics involved in written embedded C or device drivers are normal but there are quite a few things that are a little bit cleaner in assembly language and I write things for AVR-8 that are rather small but it drives me nuts that C is moving the stack pointer around and following calling conventions that are not at all necessary for these particular programs.
I had friends who worked in the IBM Mainframe world where it is still common for applications to have bits written in assembly because of efficiency or to get finer control than you can get with COBOL. Part of the COBOL puzzle is that you have to be a Macro Assembler programmer to work on that stuff and you can’t just port it to GNU COBOL on Linux without also porting the assembly!
We’re still living in a multi-architecture world so the interesting idea of trying to make it easier to write assembly (imagine a super macro assembler with an integrated theorem prover) is a non-starter. Let x86 founder for a decade and if RISC-V makes no progress that picture could be different in a few years.
I can accept compilation being slow, slower than C++, but do large projects require >32GB memory, for example the case of LLVM, Chromium, or Envoy?
Had to buy a new laptop because of this.
> Node.js and Go are considered practically safe language
Node JS has had vulnerabilities in the past: https://www.cvedetails.com/cve/CVE-2021-22940/
Go is also not Memory safe: https://www.ralfj.de/blog/2025/07/24/memory-safety.html
Node.js and Go are both memory safe, as are Python, Ruby, and Java. "Memory safe" is a term of art referring to susceptibility to memory corruption vulnerabilities in code written by an ordinary practitioner of the language. Almost invariably, attempts to show languages like Go and Python as memory-unsafe involve a programmer deliberately working to defeat the language. But you can do that in any language, including Rust.
There are essentially just two mainstream memory-unsafe languages: C and C++.
Having run into memory issues in go but not (yet) in rust I would tend to disagree with this. It's really not hard or esoteric to run into it in go.
It's easy to cause memory corruption with Go while building a concurrent system, you don't need to learn anything about "defeating the language".
"Memory corruption vulnerabilities" != "concurrency bugs" or even data corruption. The last thread I was in about this, someone pointed to Go segfaults and said "see! memory corruption!" (obviously: no).
An easy response to claims like this: there's a huge tower of software written Go at this point, including the entire K8s ecosystem. Show me the memory corruption exploits.
The amount of Rust code using unsafe is a major issues for a language build around safety. And yes, the same argument can also be made about Go having a unsafe keyword.
The fact that there exist crates to detected the usage of unsafe in dependencies, shows that its a rather liberal used keyword. Geiger comes to mind.
Unsafe in a language like Go is very rare, mostly because people do not program at such low system level to get the max performance out of it.
Rust code with unsafe: 1.7M Go code with unsafe: 400k
and for comparison, Go has about 2.3x the amount of repo's. So Rust has about a 10x more usage of the unsafe keyword.
It's got really not much at all to do with `unsafe`.
I agree, and I personally wouldn't call golang memory safe for that reason. Thomas's semi-definition includes the word "vulnerability", which narrows the scope so much that golang fits under the bar, since the common data race that causes memory corruption hasn't been shown to be exploitable without being contrived.
My personal definition of memory safety for a language like golang would specify that you can't cause this sort of memory corruption without an explicit call to unsafe, but there's no real definition to fall back on.
The same thing happens any time a message board confronts a professional term of art. The same thing happened with "zero trust", where you'd have long wooly debates about what was meant by "trust", but really the term just meant not having a conventional perimeter network architecture. Sorry, but the term as used in industry, by the ISRG, and in government guidance refers specifically to vulnerabilities.
So, Ada?
The blogs about page is fun:
> People create lies to gain power and money. Which is kinda what I was supposed to do, but for random reasons I went rogue and chose sanity instead.
> I am anti-bullshit.
These "contrarian for the sake of being contrarian" vibes naturally flow into this Rust post. Rust has a ton of faults, but this is was a very shallow critique.
> "there is just no perfect correctness possible in the Turing machine model"
Grrr. Clueless people keep saying that. People have been verifying programs for over forty years now. Formal correctness in terms of not violating assertions is possible for most useful programs. As someone pointed out about the Microsoft Static Driver Verifier, if you're program is anywhere near undecidability, it has no business being in the kernel. This not a legit criticism.
Theorem prover ideas have an impact on Java, Rust and a lot of languages —- it really would be great to see something that accomplishes even more…. Would be nice if you could have a program that lives side by side with a correctness proof.
I was a Rust programmer, for 3 years. Did web backend, kernel programming, network security...
Then I discovered that C++ has a very cool feature that Rust doesn't have: jobs.
Now, I no longer search for Rust positions.
> Unfortunately, it’s impossible to make Rust compile fast. The problem is inherent to all similar generics-heavy languages, like Haskell.
I don't think this is correct, strictly speaking. Furthermore, I think this conflates two common causes of slow generic compilation:
- Type-checking them can take a lot of time
- Generics may be implemented in a way that generates a lot of code
Neither of those are required for generics-heavy languages (e.g., OCaml is generally considered to compile fast despite having a "complex" type system), and the presence of one doesn't necessarily require the other - a hypothetical "simple" generics system with heavy use of monomorphization can end up taking a long time to compile, and a "complex" generics system that erases types may take a while to type-check but could compile fast after that.
> Put a non-optional borrow-checker on top of it
From my understanding the borrow checker usually takes up a small fraction of the time needed to compile. There are cases where that's not true, but I think people tend to overestimate its impact on compile times.
> There are ways to implement unsafe programs that still don’t execute remote code or leak secret — they only corrupt user data and act sporadically.
Reliably implementing unsafe programs that don't have RCEs or leak secrets but still corrupt data and "act sporadically" seems like a very peculiar combination of requirements to me, if it's even possible. "Act sporadically" is also quite nebulous, and depending on the precise issue may in fact be an RCE or secret leak in hiding - after all, it's not that uncommon for exploits to start their life as someone noticing a crash.
> It’s probably the strongest point of my whining: Rust is memory safe and unreliable. The price of memory safety was reliability in addition to the developer’s sanity
I think that is actually one of the weakest points. I didn't see any support for a claim that memory safety necessarily requires trading off reliability, let alone that that is what Rust does.
> Step into the shared mutable state — and there a memory corruption is not an exception, it’s a rule. You have to handle the corruptions, you cannot simply crash.
What definition of "memory corruption" is being used here? I didn't think that's the kind of thing that you usually "handle"...
> Which kinda destroys the first uncompromising thing in Rust — performance.
I feel this misunderstands Rust's priorities. (Safe) Rust prioritizes safety over performance, and that has been a well-known tradeoff for basically its entire lifetime. If you want performance at the expense of safety, that is what `unsafe` is for.
> So, to reiterate, the second you step into the shared mutable state you lose every single advantage of Rust. Which is kinda rational considering that the main concept of Rust was to never employ a shared mutable state.
This misses another useful bit of Rust, which is the ability to contain unsafety to clearly-delimited sections of your codebase.
There's more I could say, but life calls...
> T, T&, T*, std::optional, std::unique_ptr to describe similar things, each broken in its own way
How is `T` broken? How are the other things broken?
No matter what language you use, most of the code running between what you wrote and the hardware will be written in C. Your choice for the 1% on top is not very consequential. There is still a huge attack surface area no matter what.
Totally wrong.
> Its compilation is slow. I mean SLOW. Slower than C++.
No way. Maybe Rust 1.0, but it's steadily improved and it's definitely faster than C++ now.
> It’s complex. Just as complex as C++.
True, but the problem with C++'s complexity is that you have to memorise all of it or you'll accidentally invoke UB. It's so complex that is basically impossible.
Rust is complex but most of the time the compiler will tell you if you got it wrong. There are exceptions of course (lots of async footguns) but it's still night and day.
> Memory safety is not that sacred. In fact, for many applications malfunctioning is better than crashing
Not sure I really need to counter this...
> When handling lots of mutable shared state (GUI, DB, stateful services, OS/hardware), the performance of native Rust memory model is subpar, and non-native unsafes just leave you with slow compilation, high complexity, and no memory safety in the end — which makes Rust practically meaningless for heavy mutable state jobs.
Not totally clear what he's getting at here. Maybe the ergonomics of GUI style programming which are still being figured out? Hardly a deal breaker though is it? There are plenty of C/C++ GUI libraries with terrible ergonomics and the only one that is actually great (Qt) had to use a custom language extension for decades to achieve that.
> So, is the Rust bad or good? It’s neither. It’s a mediocre programming language with thousands of man-month put into its development
I would love to hear what he thinks a good programming language is, because I can easily pick more holes in any other language than he has.
This anti-Rust zealotry is super tedious.
He hates on C++ pretty much the same as he does on Rust. Your argument seems to be that Rust is better than C++, which is akin to trying to make the case that Cholera is better than Smallpox.
Language wars are boring and pointless, they all have areas of suckage. The right approach is to pick whichever one is the least worst for the job at hand.
> I would love to hear what he thinks a good programming language is
not OP, but outside of extreme performance critical software I MUCH prefer Swift, C# or python.
C# is really good, but is Swift good enough as true general-purpose language for every platform and OS?
> I would love to hear what he thinks a good programming language is
Also, not the OP, but I bet it is Python.
- No compile time.
- Not as complex as C++.
- Memory Safety, while they don't care about this apparently, but nice to have.
- Plenty of ergonomic GUI style programming, like PySide (Qt for python).
Of course, I know there are many downsides to python. Such as interpreted languages, especially ones that are duck typed are very slow to run... but that's not one of the OP's complaints.
The article complained that a Rust program can crash when you call `unwrap`—in fact, the author says that's their strongest critique. Python crashes when you call `sys.exit`, so it's no better.
Unfortunately I don't think their critique is really coherent—this is an absurd standard.
Modern c# is very nice. And can be fast too
Use D.
> Memory safety is not that sacred. In fact, for many applications malfunctioning is better than crashing
Yeah, just another data leak, no biggie.
What's a bit of arbitrary code execution between friends?
I mean there's nothing better than Rust, just talk about what in Rust is annoying instead of saying that
Unless I need close to 100% memory safety with no compromise in performance I'd rather write Zig, Odin or Go.
Zig and Odin are much more enjoyable to write and provide enough safety for a lot of applications, and Go gets you 90% of the performance of Rust without the complexity.
I think we’ve officially reached the inflection point where the Rust haters have become more annoying than the Rust evangelists. Maybe in a couple years we will finally be able to stop writing blog post about it.
“Summary:
So, is the Rust bad or good? It’s neither. It’s a mediocre programming language with thousands of man-month put into its development — this fact alone makes Rust a viable tool, just because you can pick it from the shelf and employ as-is. This blog was generated with Zola, written in Rust — I did not have to write a single line of Rust code to use it. And the Rust is a good fit for Zola SSG because of its non-interactive nature with one-way flow of immutable data. Just, please, don’t run around screaming “we should all switch our development to Rust because it’s the best programming language”.”
Is this what makes someone a Rust hater?
Literally hates on Rust for the whole article except the final summary.
Man, I explained it in the first sentence of the article — it's not bad, it's much worse than it could have been. The main body of the article is not hate — it's plain facts. Everybody working on a significant Rust codebase agrees that Rust compilation takes eternity. Complexity? I know people that like complexity, they would say "that's a great language because of how hard it is to write a program in it!" — complexity would feel like a praise for them. Shared state? "Just don't use it, you are doing it wrong". That's is, where is the hatred?
> The main body of the article is not hate — it's plain facts. Everybody working on a significant Rust codebase agrees ...
Lol. Its not facts. Its a description of frustrating things you've experienced working with rust, dressed up as "deep truths about the language". You don't speak for the rust community. This article would be much more interesting if you just talked about your own experience without pretending your issues are universal.
Re: compilation time, in the 2024 state of rust survey 25% of rust developers said slow builds was a big problem. And thats a lot of people! But 19% of people said its not a problem at all for them. Its certainly not "everyone".
https://blog.rust-lang.org/2025/02/13/2024-State-Of-Rust-Sur...
I suspect if you keep using rust, the things that annoy you about the language will change a lot over time. Some things will stop bothering you, and some things will start bothering you a lot more! (Like IMO Rc/Box/etc isn't a big deal. Once you learn to structure your code in a rusty way, you almost never need that stuff.)
I really like rust now. But I found learning rust to be incredibly painful. I get why you're struggling with it. But please don't confuse your struggle for universal truths about rust. You're only one person.
Subjectiviy (eternity, complex, etc) is never factual. Your post has facts, it does, but it still sounds a lot like hate.
It seems pretty clear from the article as a whole.
Absolutely not. Rust lovers are still incessant as they’ve ever been. More Rust haters is a good thing.
Can you give some examples? C/C++ devs seem to be very upset about rust content. Where all these annoying articles claiming we should rewrite everything in rust? They must be all over the place given how much C/C++ devs are upset. But I don't think I've read any?
There was that article from the android team about how rust improved their development workflow[1]. Is that what you're talking about? Was that article emotionally upsetting? Do you wish it wasn't written? What in particular is upsetting? Do you want people to stop writing technical articles to protect your feelings?
[1] https://news.ycombinator.com/item?id=45918616
I haven’t seen a positive Rust article hit HN in over a year. Seems the zeitgeist has turned against it. All it took was the US government giving the thumbs up I guess.
On the other hand, lets face it: most of the time security in IT systems is the least priority. I mean after shipping fast, iterate fast, better performance, compatibility, architecture soundness (whatever it is), convenient tests, docs with UML diagram, well-designed interface — and somewhere in a distant drawer on the bottom you may find a note about security issues. It's often times people talk about importance of security after it destroyed the whole business.
We need more of the security. We probably don't need the Rust though.
security incident destroying a business is so rare and penalties for security breaches are non-existent and hence while everyone talks “security is important” it really isn’t all that important - in vast majority of the situations. I mean, fucking experian, the company whose sole purpose for existence is collecting and keeping data on everyone safe leaked everyone’s data and everyone was like “oh ok, thats cool, carry on…”
> Rust haters have become more annoying than the Rust evangelists
I disagree. There's a long road till that inflection point for me.
At least the Rust evangelist build shit.
People who get shit done are too busy to evangelize.
We really just need official/honest guidance on Rust for what works and what doesn't. The classic example is the dodging around cyclic datastructures.
Tl;DR Rust doesn't support any form of cyclic datastructure without indirection or unsafe. The indirection tooling is weak, and most real examples simply switch to unsafe rust. Unsafe rust is completely fine if you know what you are doing with memory, and is ok to use in these situations.
There are a few other gotchas that we just need to be clear about, some of these gotchas are limiting for developing higher level software and some are not e.g. String handling. If you are comfortable with unsafe, the rust toolchain is vastly superior to C/C++ development making it as close to an ideal replacement as we are likely to get.
A couple years ago I implemented a btree (technically order statistic tree) in a couple thousand lines of unsafe rust for a project. I wrote it more or less how I'd do it in C. Each internal node and leaf node was a separate heap allocation and internal nodes had an array of child pointers. It was surprisingly hard to program up. And complicated!
In my opinion, unsafe rust code is worse to use than C because rust is missing the arrow operator. And rust still requires strict aliasing to be followed even in unsafe code. This makes complex unsafe code very hard to implement correctly. Like, it’s easy for something to look right and work correctly but for MIR to still find subtle issues.
Eventually I rewrote my btree on top of Vecs. My node & leaf pointers are now array indices. The result? There is no longer any unsafe code. The code has become significantly simpler and it now runs ~10% faster than it did before, which is shocking to me. I guess bounds checks are cheaper than memory fragmentation on modern computers.
I have so many thoughts having done that. First, I think this is actually the right way to write rust. Yes, manually keeping track of which array slots are in use is inconvenient. But unsafe & pointers are also quite inconvenient in rust. Programming like this makes use after free bugs possible to write. But it’s still memory safe by rust’s definition. It’s impossible to get arbitrary heap corruption because there are no raw pointers. And the indexes are bounds checked.
I also don’t think the resulting code is any worse than the equivalent C++. Everyone talks about memory safety but IMO rust’s best features are enums, traits, cargo, match expressions and so on. Even when you do a run around the borrow checker, it’s these features which make me keep coming back to rust.
I agree better guidance would be nice, but so many words have been spilled on rust already. Would you find content talking about subtle stuff like this? Sometimes the only way to learn is by trying stuff out.
>Eventually I rewrote my btree on top of Vecs. My node & leaf pointers are now array indices. The result? There is no longer any unsafe code. The code has become significantly simpler and it now runs ~10% faster than it did before, which is shocking to me. I guess bounds checks are cheaper than memory fragmentation on modern computers.
Optimizations are very complex and potentially fragile in Rust, LLVM has to sort through tons of generated IR, so it might be just that native Rust structures are optimized better for compilation. Particulary, Rust is able to optimize out some bound checks.
Do note that binary trees are mostly an obsolete legacy today — they are way too cache-unfriendly. I mean you could have written similar code in C++ using std::vector or std::dequeue and get the bounds checking too.
>Everyone talks about memory safety but IMO rust’s best features are enums, traits, cargo, match expressions and so on
C++20 with concepts mostly reproduce the traits. C++17 with std::variants emulate enum/tagged union. Match is unmatched by C++, that's true.
Cargo is good for as long as there are few packages in there. Large projects already suffer from five versions of serde in one build and dependencies on FFI-connected libs that cargo itself cannot build. I mean look at the NPM nightmare — and they've mostly dodged FFI-s.
> Do note that binary trees are mostly an obsolete legacy today — they are way too cache-unfriendly. I mean you could have written similar code in C++ using std::vector or std::dequeue and get the bounds checking too.
As a sibling comment said, its a b-tree not a binary tree. B-trees are - as far as I know - the fastest data structure on modern computers for the class of problems they solve.
And yes, I think if I ever go back to C/C++ I'll try this approach out. It might also work great in GC languages like JS/TS/C#/Go because there's fewer pointers to keep track of.
> Cargo is good for as long as there are few packages in there. Large projects already suffer from five versions of serde in one build and dependencies on FFI-connected libs that cargo itself cannot build. I mean look at the NPM nightmare — and they've mostly dodged FFI-s.
I haven't run into the "five versions of serde" problem, but I can easily imagine it. I've lived NPM nightmares more times than I can count. But I'd still prefer that to all the problems you get from CMake, autotools and Makefiles. At this rate we're going to get self driving cars before we have a single sane build system for C.
> Do note that binary trees are mostly an obsolete legacy today — they are way too cache-unfriendly
BTree is not Binary Tree. It's B-Tree and is cache-friendly
> C++20 with concepts mostly reproduce the traits.
C++20 concepts are not the same as traits. Concepts are structural and awkward to use compared to Traits which are nominal. There are other important differences, too.
Not to worry, another tech thing will be along shortly to fill the hype/hate cycle with its own drivel.
Zig currently sits in the hype cycle like Rust/Ruby/Lisp/etc once did here. Eventually something will come along and Zig will be in the hate cycle.
In reality none of these things need the religious wars that seem to go back and forth. It's just an incredibly unfortunate and annoying aspect of how programmer-centric communities tend to go.
Unfortunately there are topics that should stop long ago but people still rave about those: ORMs, OOP, Git, JavaScript bloat, Linux vs Windows.
Somehow there are always fresh people who think someone cares or that somehow those are important discussions.
>ORMs, OOP, Git, JavaScript bloat, Linux vs Windows
ORM and OOP whine is niche, agreed. Linux vs Windows is irrelevant because windows runs linux nowadays — I don't think I've read a single article about it.
Git? Okay, mostly circumvented by solutions that don't carry any implementation from the original Git, but have "git" in the product name.
Javascript bloat? I'm pretty sure that's still a hot topic. I don't remember it being solved, do you? Like if I open website and it greets me with a window suggesting to apply cookie policies for 300 (three hundred) trackers on the website — isn't it worth talking about?
"they only corrupt user data and act sporadically"
The author dismisses these defects, but try telling a financial institution that it's "only" corrupt user data when the books don't balance. Explain to an aerospace company that acting sporadically is just fine.
That was quite literally the author's point.