Rust is a great language but I think it has problems. Those problems come from the the time Rust was being developed by Mozilla and more problems were created after it became a community project. This post is a critique to Rust language to help you guys to improve it.
I started using it because I thought it would be a replacement for C because it has no garbage collection and zero-cost abstractions.
What made you quit?
What made me fed up was that I was getting SIGTRAP when I was trying to make a program that supports plugins. If it was SIGSEGV I would know that a statement is corrupting memory but SIGTRAP terminates the program and leaves me with no clue. No message is printed. I know exactly which statement causes the problem. I was trying to copy a struct into another struct. Copying primitives works fine. To be honest I couldn’t even setup gdb to show the source code, I know it is possible though. I don’t have to do any setup when I’m programming in C. I just run gdb and the source code is there.
FFI
Rust seriously does not support interfacing with other libraries. People write entire libraries just to call code from another C libraries. If I’m calling code using the C export interface, I know it is unsafe. No need for wraping. Furthermore, it is C code. Why do you guys depend on C? Call functions using the int instruction in assembly source code.
The language
The syntax has too many tokens. It makes programming unpleasant. A good example of a language with perfect shape is the Go language, very clean. struct fields end in coma, trait fields end in semicolon and statements end in semicolon too. Why not make everything a semicolon? What is the -> for before the return type? Why the semicolons after the identifiers in struct declarations? Rust does not support anonymous structs and they have to be always declared outside of the functions. But functions can be declared inside other functions, what an irony. Closures are something that I never needed. Entirely superfluous. Tuples are completely unnecessary. They are like anonymous structs with anonymous fields. When declaring a new struct instance, the fact that the field name have to be always used is a pain to the programmer. It should be optional as in C.
Packages
There is a lack of interface standardization for packages. Something like RFCs (Request for Comments) and packages that provide just the interfaces for specific applications. For example one interface for each type of database (table, kv, document). The Go language provides a common interface for SQL databases. This makes cargo.io bloated with packages that do the very same thing with different interfaces, work is doubled and human time is wasted. When I visit it I simply have to spend hours to analyze which package does it better and which has the better interface for my program.
There is a lack of modularization. Most libraries I used in Rust depend on many other libraries. It is a design failure. Libraries should have no or very few dependencies and the host program makes them interact.
Why people keep using names related to metals for the packages? Rust is a family of fungi. If people used names related to biology it would make more sense. Something like “microscope”, or “test tube”, or even “bacteria” or “lion”.
Build environment
No one talks about out of tree builds. It is essential for making backups of the development environment. It is even worse than it sounds. Each package builds its dependencies on the target directory so every time I make a backup of multiple projects, the dependencies get compressed not just once but multiple times, once per project. The solution is to clean each project one by one.
Cargo is just yet another package manager and the sources are centralized by default. Why crates.io by default and not github or any other website? Why not use the debian repository and make deb packages if it is not pushed in time to sid. Or maybe produce multiple packages in different formats if you don’t use debian. I can setup my /etc/apt/sources.list to point to tor://vwakviie2ienjx6t.onion/debian/. The fact that crates.io is the default makes Rust less resilient and vulnerable to censorship and surveillance.
The compiler
Too many warnings. It looks like running gcc with -Wall. That’s some flag that I would use after finishing the project. Things like unused variables, unused imports are just things that I don’t want to know when a program is under heavy development. The compiler outputs warning that do not affect the behaviour of the binary like braces around if expression, camel case for struct names and so on. Coding standard should be optional.
The compiler errors are cryptic and contains language not present in the book. For example:
error: the trait bound std::io::Read + 'static: std::marker::Sized
is not satisfied
This could be translated to "you are trying to use a trait instead of a struct. Traits do not have a size in memory."
Or this example:
error: the trait bound T: std::io::Read
is not satisfied [E0277]
The generic T does not declare the trait std::io::Read.
The terminal is bloated by note messages by default, no option to activate it if I really need more info.
The compiler embeds help messages with rustc --explain instead of putting them in man pages or maybe just copy pasting the error code on a web page.
The documentation
The documentation looks like a literature book. It’s one of those things that you read laying in bed before sleeping. It teaches the language like a person trying to learn it by trial and error and uses onomatopoeia like the author does not know what she is doing. She is just faking feelings and maybe the reader didn’t even understand the matter.
It presents trial and errors and shows the correct way at the end like telling a story. I just want to know the correct version. This causes TL;DR. It presents vague information about the stack, the heap, when memory is allocated and freed, what information a reference, a pointer, an identifier and an array carry. Where my data is stored anyway and how much space it is taking? It does not explain why it is possible to return structs and things wrapped in Result and Option. As far as I know it requires an optimization from LLVM to put the data on the caller’s stack frame instead of putting the data on its own stack frame.
Better information is missing for features unique to rust like ownership and lifetimes, specially lifetimes. It’s so terrible that I had to create a stackoverflow account just to make questions about it when I could just have googled it as usual.
The page about drop contains references to fireworks, bombs and explosions, things that I don’t want to think about when I’m concentrated. A technical book is not place for happiness symbolisms.
Good bye
I was using Rust mostly to make web apps. But now that virtualization is widely available, I can use C and the good old Apache with fcgi. I can now insulate the requests from every user and prevent it from modifying the operating system. I can use a memory management strategy like the one that the Ada (considered super safe) uses: always free the memory on the caller function. I will go back to C and I know that I will get SIGSEGV. It’s like the Socratic paradox says: I know that I create bugs. Rust has a great community. Anything you need you can count on me.
Good bye folks. Maybe I write my own language inspired in Rust.