Skip to content

Instantly share code, notes, and snippets.

@cynthia2006
Last active May 26, 2026 09:07
Show Gist options
  • Select an option

  • Save cynthia2006/584f518161cfcba9a745afd94c903304 to your computer and use it in GitHub Desktop.

Select an option

Save cynthia2006/584f518161cfcba9a745afd94c903304 to your computer and use it in GitHub Desktop.

Criticism of Rust

Rust is all about grand narratives—fearless concurrency, memory safety, zero-cost abstractions, and all that jazz. But does it hold up altogether or crumble under its own weight of deceptive marketing?

Myth of Zero-Cost Abstractions

There's nothing such as zero-cost abstractions. Any abstraction, no matter how transparent, brings both a performance and cognitive penalty. It applies not only to Rust, but also to carcinogens like C++.

Cognitive penalty is especially applicable to bindings that dramatically change the original paradigm of the underlying library without (properly) documenting it; in that case, source code must be read to ascertain correct behaviour. This needless effort makes abstractions not zero-cost, but sometimes more cost than if you had just used the library without the binding.

Hostility towards unsafe

I've seen Rustaceans act with hostility towards unsafe code. And, I understand that often there's no need for unsafety, but in certain cases it has been shown in the past that sometimes performance is indeed achieved through unsafety. And not just that, sometimes unsafety is a necessity, such as when dealing with FFI (Foreign Function Interface), which is foundation of bindings.

A case of out-pointers: A vector is normally initialised, however certain APIs require user pass a slice, and a certain function/method writes into that slice usually upto its length (see example). Initialisation thus becomes an unnecessary overhead, as the slice will be written to anyway. Here, we manually extend the vector’s length assuming the region is initialised. This is particularly useful for FFI code, but here’s a simple demonstration.

fn uninit_vec<T>(n: usize) -> Vec<T> {
    let mut v = Vec::with_capacity(n);
    unsafe { v.set_len(n); }
    v
}

fn write_into(s: &mut [u8]) {
    for (i, s) in s.iter_mut().enumerate() {
        *s = (i % 256) as u8;
    }
}

let mut v: Vec<u8> = uninit_vec(10);
write_into(&mut v); // Borrow as slice
assert_eq!(v, vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);

Bindings exist because not all code has been rewritten in Rust, much to dismay of the Rust community. Many take safety for granted without considering the circumstances where the unsafe code used to implement the safe interface may non-deterministically malfunction, which is the case with a lot binding libraries out there. Debugging this requires to scrutinize the source code as mentioned before, which is just wasted labour as the direct library could have been used if Rust had better FFI ergonomics.

"Infallibility" of Ownership

People hailing to a background in low-level languages (e.g. C or FORTRAN) find Rust rather hard to understand at first, because in those languages the norm is to manually manage memory or resources (sockets, files, etc). Even in languages like Go, resource allocation and deallocation is manual. However, Rust is based off of RAII (inspired from C++) and ownership (similar to unique_ptr<T>); i.e. a resource has a single owner, and it can be mutably borrowed once, and immutably borrowed an infinite number of times, if not mutably borrowed.

Ownership model, unfortunately, isn't silver bullet for all problems regarding memory safety. There exist valid cases, when a reference is semantically immutable, but it requires mutability for bookkeeping; e.g. Rc<T> or Arc<T>—smart pointers for a heap-allocated reference-counted object; former one for single-threaded and latter for multi-threaded scenarios, using a mutable Cell<T> for counting references. There’s also RefCell<T> for enforcing ownership rules during runtime.

Debunking Fearless Concurrency

What rustaceans call concurrency is actually parallelism (see concurrency is not parallelism). And, parallelism is no child's play. Spawning a pool of threads to perform a computation sounds cool. More thread means performance, right? Not really. Rather as the number of threads increase past the number of logical processors (CPUs), scheduling starts to become clumsier, and rapid context-switches would rather hurt performance. The topic of parallelism is complicated (e.g. mutexes, semaphores, conditional variables, atomic variables) and requires careful design. It demands experimentation, profiling and thorough optimisations. An algorithm designed for a sequential scenario, might turn out to be suboptimal in a parallel scenario. Trust no library which markets itself as a plug-and-play parallelism solution; it’s just to good to be true. Getting trained in a rayon bootcamp isn't going to get you past making toy programs.

Async & Pin<P>

Similar to many languages (e.g. Python), Rust has adopted a model of explicit cooperative multitasking. Rust's futures are a hybrid version of Python's coroutines and futures, but ultimately represent a deferred computation whose result will be available “in the future.” Python's coroutines are generators in disguise; because they enable bidirectional communication with the eventloop. A coroutine suspends execution at an await-point, and is resumed when the awaitable resolves. Generators are a state machine in a nutshell.

While this is no problem for Python—because all data is either reference-counted or garbage collected—it poses a problem for Rust. The state machine (a struct) contains something akin to a status field signalling what point it’s at executing the task. This status field references all the relevant fields necessary to carry the execution forward once the execution resumes; as it turns out, this can’t be accomplished without raw-pointers because self-referential structures weren’t accounted for during Rust’s design.

The harbingers of fearless concurrency conveniently consider raw pointers to be the “necessary evil” here. Not to mention raw pointers are the very culprit behind memory safety bugs, something the Rust marketing team claimed it obsoletes. If a self-referential structure is moved, its raw pointers becoming dangling. Where's your safety now?

To aid this problem, sages who jotted down the holy scriptures of the Rustonomicon came up with a brilliantly stupid idea: introducing a new type Pin<P>, instead of just implementing move constructors1. Pin<P> is often misunderstood, because it’s highly elusive. Essentially, it's just a wrapper over a smart-pointer (Rc<T> and Box<T>) or a reference (&T or &mut T), enforcing that a mutable reference to a pinned value can't obtained safely. That is, types which don’t implement Unpin can’t be be moved out of this container safely. However, who's stopping a Tom, Dick or Harry vibe coder use a type like Pin<Box<RefCell<T>>> and invalidate this guarantee safely? Pin<Box<T>> prevents accessing a mutable reference to RefCell<T>, but since RefCell<T>'s entire point is enabling interior mutability, a mutable reference to T could be obtained safely; i.e. legally do a crime.

Sure, you don't directly implement Future<T> all the time, but who's there to guarantee that underlying foundations aren’t free of these bugs? The module documentation of std::pin sound like ramblings of the severely deranged. Have a read if you want to. You were warned.

Sloth Compile Times

Rustaceans, for all their omniscience, came to the conclusion that dynamic linking is inferior to static linking. Hence, all Rust projects must be compiled along with all its dependencies, all the time.

Lacking a stable ABI, it's impossible to link a Rust library (.rlib) compiled with one version of rustc with another. Lords of the Rustceans might have all powerful machines, whirring and buzzing, constantly compiling Rust code, but we, the mortals, don't have such luxuries, and waste billions of clock cycles compiling the same code, that could just have been compiled once.

Politics

The Rust community doesn't teach people to consider tradeoffs, and forces a singular authoritative opinion. The whole community thrives on meaningless politics2—always, right from the start. And, god forbid you make a remotely politically incorrect opinion, the entire community would cannibalise you!

Their appeasement policies towards non-binary people is apparent. I personally don’t hate anyone from the LGBTQ community, but hate it when a certain group is pandered for vote bank politics—an artefact of late-stage capitalism. Through bringing in contemporary attitudes of “woke culture” within the tech-sphere, it seeks to live through controversies and debates. In 2021, the entire committee resigned for not being able to enforce the community code of conduct. Besides, the anecdotal accounts of people (including me and Arija A.), who were erstwhile members of the community, have noted a prevailing toxic atmosphere.

Pro-AI Attitudes

Although, this is just a speculation and not a solid evidence, newer Rust projects tend to (sometimes heavily) rely on LLM assistance, particularly Claude Code. Interestingly enough, on December 2nd 2025 Anthropic acquired Bun and orchestrated a heavy rewrite (using “agentic coding” or whatever) from existing Zig code to Rust. The PR submitted to the Bun repository, sported a difference of around 1M lines, which is impossible for any human subject to review. As for the reason behind this rewrite, Anthropic was forced to do so because the Zig has a strict anti-LLM policy3, not because of the “better safety guarantees” excuse. Rust Foundation on the other hand has no such policy. The quality of the Claude Code AI slop is matter of debate, and through accepting the lowest common denominator, the trust of Bun users is severely undermined, a sort of technological fraud. And, the very need for LLM-assistance stems due to the language being so mentally taxing—a problem that C++ prominently suffers from—that having a mental map of all the features and their underlying semantics and pitfalls, and mastering it all becomes a virtually impossible task anyone aside from the language designers themselves. Cross-checking what a machine spat out as a result to ensure it’s idiomatic code becomes a task in itself, and carelessness in this regard will only result in suboptimal code, or worse yet, error-prone code making the architectural basis brittle. This desperate desire to outperform existing battle-tested handwritten C/C++ code is what I suspect to be some undercurrent within the Rust community to herald its decade-old agenda of “Rewrite in Rust”.


Checkout this blog by Arija A. (https://web.archive.org/web/20260201083739/https://blog.ari.lt/b/rust-bad-ii/). She has done a great job of pin-pointing exactly where the deficits of Rust lie. Fuck Rust. Peace.

Footnotes

  1. All moves in Rust are bitwise copies; i.e. a plain and simple memcpy.

  2. https://x.com/rustlang/status/1267519582505512960

  3. https://simonwillison.net/2026/Apr/30/zig-anti-ai/

@matthewyang204
Copy link
Copy Markdown

This is a very fair point. As can be seen in things like DOOM, yes, performance is achieved through extreme unsafety. I do also think the ABI is a problem. Something made for Rust 1.7x.x may not work in 1.8x.x and vice versa. I also do hate the politics around Rust. There truly is a problem when the entire community thrives on criticising and bringing down others with opinions only slightly different (aka the complete opposite of freedom of opinion & speech).

@cynthia2006
Copy link
Copy Markdown
Author

@matthewyang204 I know, right? The Rust community is full of SJWs who've nothing better to do than virtue-signal everyone. They've taken a clear trans-appeasement policy.

@matthewyang204
Copy link
Copy Markdown

@cynthia2006 Exactly. I use Rust myself quite a bit, but it's definitely not the non-enforced "Idiomatic Rust" and I definitely do not agree with how the community treat their own members, let alone other people like me who write code in C, C++, plenty of other unsafe languages, and also interpreted languages like Python.

@cynthia2006
Copy link
Copy Markdown
Author

@matthewyang204 The Actix drama exposes how toxic the community really is. My experience with Rust has been mixed so far; found out that — atleast in my case — writing equivalent C code lead to more comprehensible and less verbose code.

@cynthia2006
Copy link
Copy Markdown
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment