Why Rust is not my favourite programming language

Rust is a programming language I’ve argued a lot about. I’ve argued against it, to be precise. And although I tried my best to lay out my arguments as clearly as possible, it seems most people I’ve talked to didn’t understand where I was coming from, whether due to my own fault or theirs.

A few days ago, whilst taking a shower, I realised that just arguing with strangers on Twitter isn’t a really good or effective way of communicating criticism, so I decided to write this blog post/essay, to allow me to express my views in a calmer and better researched manner.

Before I share my opinions though, I have to get one thing out of my way: they are indeed only my personal beliefs. What I’m going to talk about here is not universal truth, but rather the thoughts of a 16 year old Hungarian teenager who likes to program in his free time. Although I might sometimes say things as if they were facts, I do it because it’s just simpler grammar-wise. So, please do not misinterpret the contents of this post. I’m not an evangelist for anything.

The good things

I don’t want to start by throwing insults at the language right away. So I’ll first list some of the good things about Rust.

For one, it’s a language that was properly designed, which is absolutely a rarity these days. Unlike C++, for example, Rust’s creators (I presume) sat down, at some point, and discussed what they wanted the language to be like. This lead to an experience that feels continuous and consistent. Every element of the language seems to know its place and purpose, and there’s minimal duplication, at least as far as I could tell through my experiments with it.

For example, I’ll compare it to the opposite of that, C++. In C++, there are at least two ways to access the contents an std::vector:

There are also two ways to get the length of a string. In general, C++ offers at least two ways to do anything, without there being any practical difference between the options. Although this might not seem like a problem, making all those micro-decisions all day can get tiring pretty quickly. It also bloats coding style guides, which developers then have to remember. It’s all a huge mess, to put it bluntly.

Speaking of style guides, Rust having an official style guide is a nice thing too. I can hop on lib.rs1, randomly open the sources of a library that I’ve never heard of, and they’ll use the familiar style. It makes reading other projects' sources much easier, as I don’t have to readjust my eyes for every project.

It’s also got a really cute mascot.


I do have to note though, that these pros aren’t exactly unique to Rust. It shares it with other recent languages, such as Go2.

The bad things

Let’s not forget why I started writing this post, though. I wanted to talk about why I don’t like Rust. And there are plenty of reasons for that. Let’s get the simpler ones out of the way first. We’ll move onto the juicier ones later.

Compile times

I don’t think there’s much to explain about this. rustc is slow, and so is cargo. Even worse than C++, actually, which is quite an achievement.

But I’m gonna demonstrate it. Let’s take a look at the following example projects: LeftWM3, a tiling window manager written in Rust, and i3, which is written in C. For i3, I used the latest development snapshot at the time of writing. All times where measured with the Unix time utility, in my case the GNU implementation. The tests were performed on an ASUS VivoBook with an Intel Pentium Gold processor and 12G of RAM.

Building LeftWM took 3 minutes and 35 seconds. Part of that was all the dependencies, but the fact is, you have to compile your dependencies with your project, at least as far as I know, because there is no other way to link to them.

With i3, setting up the build directory took about 1.5 seconds, and the rest of the compilation using Ninja was around 11.3 seconds. This admittedly doesn’t include the time to build dependencies, because it was actually possible to install them separately, from binaries. By the way, by line count, i3 is about 2.7 times larger than LeftWM (38,269 for i3 and 14,094).

I will admit that this is not a very scientific benchmark; I compared two randomly selected (although in purpose similar) projects. However, from my experience, most projects in both languages seem to be similar to this. Keep in mind that this wasn’t meant to assess the raw performance of compilers, but rather what trying to build a project written in these languages feels like.

If you want better set-up, proper benchmarks, you should search the web instead.

Type safety over speed

This is a thing I often have issues with, yet others claim it’s not an issue. Simply put, Rust always prefers safety over speed, even when it could save a lot of time.

For example, I was testing speed of memory allocation in Rust and C. If we allocate memory for, I don’t know, a byte array, we probably want to initialise the buffer with zeros. Doing this (in Rust with any vector or array type, in C with calloc), the performance is roughly the same, with C beating Rust by only a few percent. But, if you are allocating for something that you’ll initialise yourself immediately after, you might not want the system to automatically zero the buffer, as it would simply be a waste of CPU cycles. It might not sound like this saves a lot of time, but it can absolutely do so. For perspective, if you do it enough times the difference can be 0.001s vs 50s. In C, this is easy (just use malloc instead of calloc), but in Rust, you really have to fight the language for it, and it’s heavily discouraged.

A similar issue is array accesses and boundary checks, although that issue is much easier to avoid by writing idiomatic code.

The juicy part

Up until now, I only talked about minor annoyances. They wouldn’t be dealbreakers, unlike the ones in this section. As promised, some of them are larger issues that can’t be fixed without a total revamp of the language4. Some aren’t unfixable, but still big issues.

The paternalistic compiler

This is one of the biggest issues I have with the language. I want my compiler to do as told, and not complain unless I throw them something incomprehensible. It should assume I know what I’m doing, unless told otherwise, and not complain about things it doesn’t understand.

Famously, it’s extremely hard to make a mutable doubly linked list in Rust5, because the borrow checker refuses to acknowledge the fact that the same value will never be mutated through multiple references at once, because the project implementing them doesn’t even use multi-threading.

By the way, in C, this is what a doubly-linked-list looks like:

struct DoubleList {
	struct DoubleList *next, *prev;
	TYPE value;
};

You could use a macro or a parametric header to make this generic, but I won’t bother for this example.

In Rust though, all examples are extremely messy. Just take a look at this StackOverflow question. It’s a fucking mess.


Similar issues came up all the time while I was using the language. For some reason, the compiler keeps throwing errors at code that would be perfectly safe (if it compiled). This ended with me spending three hours on a simple 60-line file that was meant to implement a very simple protocol.

It’s extremely annoying to be honest, although I might live in a bubble, as manual memory management was never an issue for me6.

Panicking everywhere

In idiomatic Rust, code encountering unrecoverable errors uses the panic macro to, well, panic. This is completely sensible, the problem is that not everyone agrees on what counts as unrecoverable. For example, by default, the standard library functions that perform allocation panic on failure, and so do many third-party libraries. This is fine for most programs, but can be a huge reliability issue for others (e.g. servers). Again in C, these errors are extremely easy to handle:

int *arr = calloc(1000, sizeof(*arr));
if (arr == NULL) {
	// Allocation failed
	exit(EXIT_FAILURE);
}

In Rust, you have to perform much more complicated rituals to achieve the same, if you can at all. With most third-party libraries, there’s no way to do it. In fact, most people recommended the previous thread’s OP to just drop the standard library (I’m pretty sure that’s what no_std does) and do it all by themselves. Which is, you know, inconvenient.

However, Rust again shares this issue with a lot of modern languages, which simply weren’t developed in an age where allocations failing was an everyday occurrence.

Un-bootstrappable

This isn’t an issue with the language per se, but instead with the toolchain, but I thought it was still worth mentioning. The toolchain is huge, and de facto impossible to build on a laptop (which happens to be the only “desktop computer” I have). Certain compilers for C, on the other hand (tcc and pcc, for example) can be compiled in mere seconds.

There isn’t much to expand on this section. It’s huge and slow to build. When I mentioned this, people told me to rent a server from AWS, and compile it there. That’s kind of ridiculous, isn’t it?

(No, that actually happened. I can’t find the Twitter thread anymore (and I’m not 100% sure it was on Twitter), but I can clearly remember it happening. No offence to the person that said this, but not everyone has the means for that.)

NPM-like developer culture

This bugs me more than it probably should. The thing is, most Rust programs rely on a myriad of small libraries. Whilst Rust’s bigger standard library prevents the left-pad incident from happening, it still gets a little weird sometimes. For example, there is a package crate solely for lazy-initialised globals. That just seems off.

I’ll admit that a little more disciplined approach to dependencies helps with this issue, but it still exists.

In conclusion

Rust is not, at the moment, my favourite programming language, simply because it’s not a good match for some of the issues I commonly have. Even though I spent a lot of words on telling you why it’s bad, I have to say it has its pros.

I didn’t write this post/essay because I perceive Rust to be extraordinarily harmful (I would have definitely wrote about C++ first if that was the case), but because I got tired of some of the voices in the language’s community. I don’t know if they’re serious, or if it’s just a meme, but the constant “everyone and their mother should program exclusively in Rust” has became very annoying.

Liking the language is fine, and I might change my views about it. But I believe that it’s not good for everything, and C still has its place.

It’s possible I might have got some things wrong in this post. If so, please contact me using the methods listed on my contact page (link in the sidebar).

(Proofread by Don Graham. Thanks!)


  1. I’m aware that it’s not the official site. However, it’s absolutely superior to the official site, so I’ll link to it instead. ↩︎

  2. It even has a similarly cute and marketable mascot! ↩︎

  3. Built with this release↩︎

  4. Which arguably would create a separate language, only sharing the name with today’s Rust. It would also be something most Rust programmers would hate. ↩︎

  5. Well, without unsafe that is. But with unsafe, Rust basically becomes an extremely fancy C dialect so it doesn’t count. ↩︎

  6. I started coding with C, though, so in return all other approaches feel unnatural, or at least take some time to get used to. ↩︎