Rust is a disappointment
I used to call myself a Rust hater, but really I was doing it just to compensate for the perceivable fanboyism e.g. Rust tops on stackoverflow surveys as most-loved language. There are many reasons to hate C++, and I hate C++ too. Lots of people were waiting for a better programming language, but got Rust instead.
There are several core problems with Rust:
- Its compilation is slow. I mean SLOW. Slower than C++. I know over years Rust became several times faster, but objectively we need it to be two orders of magnitude faster, not just two times.
- It’s complex. Just as complex as C++. But C++ had legacy and Rust had not. The complexity of forcing your way through the jungle of
Arc<Mutex<Box<T>>>on every single step directly impacts the quality of the logic being implemented i.e. you can’t see the forest for the trees. Once again, C++ has the same problem, so what’s the point of the language switch in the end? - 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.
- 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.
C++ actually sucks
There is no doubt about it. Undefined behavior (UB) is a fundamental aspec of the language, you don’t simply encounter UB — the whole language is built on UB. You do array indexing and you immediately encounter UB because the language just does not check out of bound access. I want to emphasize that lots of UB-s are not even justified by performance matters — it’s an outright sloppy design of C carried over and amplified in C++. I can go all day long about how C++ sucks:
- implicit type conversions, implicit copies, implicit constructors, implicit object slicing, and pretty much everything implicit;
- function overloading (implicit), particulary considering its omnipresence in STL;
- non-uniform error handling with exceptions as afterthought;
- still #include-ing text files 40 years after C and One Definition Rule barely checked by compilers;
- unsound combination of paradigms (good luck overriding a generic function in descendant classes);
- SFINAE nuisance as a core mechanism of generic programming;
- T, T&, T*, std::optional
, std::unique_ptr to describe similar things, each broken in its own way. Put a const cherry on top of it.
So C++ is complex, unsafe, and it’s compiler is slow. How does the Rust (not) fix those issues?
1. Slow compilation
It’s not a temporary problem — it’s by design. Here one of the designers explains why the Rust development team sacrificed the compilation speed every time:
https://pingcap.medium.com/the-rust-compilation-model-calamity-1a8ce781cf6c
Rust FAQ explains that there are many efforts to optimize it, like better frontend, MIR, and so on. But MIR effort was started at 2015 and it still fails to significantly quicken the compilation (although it speeds up compiler checks).
Unfortunately, it’s impossible to make Rust compile fast. The problem is inherent to all similar generics-heavy languages, like Haskell. Arguably, Rust is closer to Haskell than it is to C++. You can also say it’s close to a template-heavy C++ — and template-heavy C++ code exhibits the same problem of slow compilation.
When you do for i in 0..limit {} — you don’t just iterate, you create a range, you create an iterator, you iterate over it — all of it monomorphized to your concrete types and have to be optimized individually (non-optimized Rust code is insanely slow, it’s mostly unusable even for debugging).
Put a non-optional borrow-checker on top of it — and there you have your insanely slow compiler. And you WILL recompile a lot, because borrow checker is relentless.
2. Complexity
You just cannot avoid it. 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.
As I’ve already mentioned, this makes it very hard to write high-level logic in Rust. That’s why many of early Rust adopters actually revert to Node.js and Go for less performance-sensitive services — high complexity combined with slow compilation makes it impractical to write anything complex in sole Rust.
3. Memory safety
There are two uncompromising things in the Rust fundament: performance and memory safety. I have to argue that Rust designers went wa-a-ay overboard with memory safety. You know the containers are actually implemented with unsafe functions, because there is just no perfect correctness possible in the Turing machine model — you have to build safe programs from carefully arranged unsafe building blocks. Node.js and Go are considered practically safe language. Rust sacrificed sanity and practicality for memory safety — and gets none of them at the end of the day, it’s still not 100% memory safe.
Now speaking about practicality — lots of use cases just don’t need perfect memory safety. 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. If a pacemaker stops — 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:
https://blog.cloudflare.com/18-november-2025-outage/
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 — that’s why I’m telling the language designers went overboard. They sacrificied core practical quality for an abstract principle of memory safety. Just like Haskell designers sacrificed practicality for purity — that’s why I reiterate on parallels between Rust and Haskell.
4. Mutable shared state
It’s possible, but employing mutable shared state in Rust just makes no sense. You lose most of advantages and are left with all the deficiencies of Rust. Pretty much all of the successful Rust projects are employing shared read-only state, one way data flow, acyclic data structures: rustc compiler, mdbook and pulldown-cmark Markdown tools, Actix and Axum for stateless handlers, append-only blockchains, single-threaded WASM. The model is, once again, very similar to Haskell, which also excels in parsers, stateless handler, mostly-non-interactive CLI tools, and was employed in blockchains.
Early prototypes of Rust actually had Software Transactional Memory (STM) as an option for safe concurrency, however, STM has performance penalties and it requires simple but significant runtime support.
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. Borrow checker, ownership? Just useless, you cannot analyze ownership in a cyclic graph without GC-like algorithm.
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. 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.
Particulary, GUI is a mutable shared state. Hence we don’t see any big GUI projects in Rust. Zed IDE is still beta for so many years — I can almost feel the pain of the developers hacking their way through the borrow checker jungle just to realize their logic is bug-ridden, and they are yet to implement dozens of other features.
Big databases, scalable stateful services, operating systems, at least significant Linux modules? Yet to be seen.
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”.