Below post has started from me thinking about Rust on a weekend, and then expanded a bit. I was merely trying to understand whether C/C++ will die eventually and be replaced with something like Rust.
First of all, Rust is great, good performance, interesting language, more accessible than C.
However, thinking more about it - forces developer to start from clean slate.
There is no interop with C++. There is with C, meaning that you can wrap C++ in C calls, make a dynamic library and only then call it from Rust. Wrapping is not always a good idea, as C is unsafe and C++ is safe, plus you will have to translate some rich C++ data structures into C, meaning performance overhead. Also this prevents overall program compiler optimisation, meaning again performance loss. Also you will have to wrap C interface from Rust, again another performance loss.
System programming close to metal and OS is primarily done in C, so Rust is a very weird citizen there. Like Linux and Windows is all C, and according to various sources there is no vision to use Rust.
The promised safety is really arguable. Usually you will hear arguments that Rust is safer than C++. But that’s just not true for Modern C++. It could be true when comparing Rust to the state of C++ maybe 20 years ago.
New successful languages like TypeScript, Scala, Kotlin all have one thing is n common - they are built on heritage and are completely comfortable in their area. I mean for example TypeScript is actually JavaScript on steroids. You can take js file, change extension, and that will be a valid TypeScript program. It’s not ideal, but it will work. Apparently you can also use any JavaScript library from TypeScript and vice versa. You can mix and match in one program. This is big.
Scala is another example, as it builds on JVM, can use any native Java library, and can be compiled to use from classic Java as well! Same with Kotlin. And the wast amount of platforms JVM runs on.
Python is… well, still good. Most of Python libraries are actually written in C++ with python wrapping on top. Python is old and well developed. It even runs on JVM.
Golang is just golang, it does not claim to be a replacement for anything, bit fits well into the area of writing small simple utilities for command line where others would be too heavy. Some do write more complicated code, for instance Docker is done in Go, however it is not common. You would not write anything performance critical in Go either, mostly due to unpredictable garbage collection issues. And it’s not powerful enough to scale to really complex code. Remember that Docker is essentially an orchestrator gluing together different parts of OS to make it more accessible to mortals. It does not actually run when container runs.
C# is a weird beast. It builds on top of Java principles, but doesn’t run on JVM. It’s really way ahead of Java in terms of features and productivity, but used to only compile for Windows. Today cross platform support is great, but it may be too late for the party. It may end up like Windows Phone, it’s hard to tell. I hope not. Btw Windows Phone was way more superior than iOS and Android, but that didn’t matter at the end. It was just really late to the party.
Where does Rust leave us? I’m really confused, but it seems nowhere. Yes ecosystem is growing and there is just a lot of good stuff. But always almost enough, not completely enough. Sure if you are building software that is a utility or web server it’s ok to use, but not something really deep, no way to reuse rock solid code that worked for decades already. You’ll have to create some weird workarounds or write stuff that existed for decades from scratch. Scratch that.
Rust is not supported on as many platforms as C/C++ is. Meaning embedded and IoT is not fully accessible.
Tooling is just not there. There’s no cool IDEs like Visual Studio (which btw works perfect for Linux programming) or CLion or Eclipse. We have some half baked support in IDEA, Vs code and some others. But no really cool tooling C++ has grown to.
Do I hate Rust? Oh no, not at all. I think it’s a beautiful language. Very clear, with no legacy like C++.
Is it superior to C++? No, I don’t think so. Everything Rust does C++ does, if you use more or less recent C++ version. Even 10 year old C++ will do. But, the problem with C++ is novice programmers - the language is just so rich, it’s much easier to escape out of the sage box and do something stupid. But that’s just language evolution, eventually Rust will be there too as history shows.
Would I choose Rust for my next project? It depends. If I need to interface with OS or use third party C/C++ libraries than no. I would probably use it for command line utils or self sufficient cross platform network utilities. But then why won’t I just stick with C++ if I already use it? So far only as a learning exercise.
Well, I think I’ll stick with C++, but I’m open for criticism.
P.S. Originally published on my blog.
Top comments (10)
So I'm assuming you're not super familiar with Rust yet, and I don't mean too be critical, but I think a lot of this is kind of wrong. I work with C++, Golang, and Java frequently, these are the primary languages used at my job. I also maintain a popular Rust project, and have even used it a bit at work. I work with C++ as both a system language and embedded language(FreeRTOS, mbed). I will say C++ has gotten a lot safer when the STL is available to you, but in no way would I claim C++ is safe. C++ does not have anything analogous to Rust's ownership system outside of smart pointers which is half of it, C++ also does not have anything like Rust's Send/Sync traits which provide safety from data races. C++ has smart pointers, these aren't available without the STL, and while Rust doesn't have smart pointers without it's STL it still provides safety unless your explicitly forego. C++ is still plagued with use-after-free, that are often "hidden" now with modern idioms like lambdas. C++ retrofitted the safety features of Rust into itself, and they're far from perfect and certainly not fool proof, meanwhile Rust was built with these features the driving principal. Also most of them are STL features in C++ while many of them are literally just features of the Rust compiler.
There is a lot of talk about using Rust in the kernel space. Linus has spoken a lot about allowing Rust in kernel space, and it's moving forward but it'll take time for it to actually happen, but it's already been decided on. So it would seem very much like Linux is betting that Rust will continue to become a larger player in this space, and Microsoft research seems very interested in this subject also. C++ in kernel space pretty much loses all of it's safety features, Rust does not.
Rust never had any intention of replacing C++ or C. I think the lines were drawn by people looking in, because it's well known that C++ and C are not safe, and while C++ has made strides it's still not perfect and the safety features feel and very much are an after thought. Golang was also just meant to be a systems language, and I'd say it's more analogous to Java. Neither language is trying to eat anyone else's cake. It just so happens that Rust falls more in line with the problem space that C++ and C fit into, and Golang falls more in line with things like Java and even things like Nodejs and Ruby for web backends.
Also have you dealt with C++ templates? I mean Rust has the conciseness of Java in it's type parameters, but maintains the benefits of templates in C++, it does codegen to monomorphically create a template version of each function/type rather than the weird type erasure and implicit casting that Java does. It's just much easier to read and deal with, and the preprocessors of Rust as so much nicer.
Now I don't want to sound like I'm totally trashing C++, I actually really like C++ it was one of my first languages. I just find Rust to be better in a lot of ways. Embedded support might not be that great, but really Rust has excellent support for common microcontrollers, in fact it's theoretically got the exact same compatibility as the clang compiler because they both us LLVM. Really the only reason I tend to choose C++ these days is because I'm in a way forced to because of requirements, eg. I have to create an integration with embedded engineers who exclusively work in C++. I think that's a totally fine reason to make a technical decision, but to me there are very few drawbacks to Rust over C++ and a lot to gain. Rust might eventually have growing pains similar to C++, but as far as it's safety guarantees those are very well baked into the language and you'll never run into old projects trying to refactor major portions of code to try to accommodate these features because they've always been there. By the time Rust is old and dusty what do you think C++ will look like? Surely a new language will come along and I'll be writing a blog post about how it doesn't make sense and I'll continue using Rust because it's now go a massive STL with retrofitted solutions that work just fine.
I'm already aware that people will respond to this with insults about how I don't know C++ because I've only written for a decade and not 30 years so I can't possibly understand it enough to critique it. And I ask those people to reflect on the irony of that before posting a response, because that's also a great reason why Rust may be a nicer language.
As far as the problems with C++ safety please refer to this blog post which I think does a great job: alexgaynor.net/2019/apr/21/modern-...
Most of these things are not possible in Rust without unsafe, and while you might say, hey you can't get those optimizations (like avoiding a increment on a reference count) in Rust, you completely avoid the fact that the compiler 9/10 is going to optimize these things away anyhow.
Well no, I'm not a Rust expert but surely have experience with Rust. And I don't dislike it, quite the opposite! I think Linux is in "wait and see" game with Rust, considering to allow writing new mom critical code. It's not there yet though and I can't imagine it will be for at least 5 years. It just doesn't have enough support for variety of platforms C does. Unless you abandon majority of them like Neovim did, it might work. I wouldn't personally even try to do that.
Rust is new and seems shiny and simpler but as you mentioned yourself a lot of it already shows the age. Necessity to wrote unsafe code and battling with borrows checker is far from perfect experience. C++ allows you to have a borrows checker mechanism, custom garbage collector and whatever else you need, it's a matter of agreeing on style. Sure you can write unsafe code and screw up big bit so you can with Rust as well. ABI between C and Rust is just not there and is so painful it's not worth it. Mixing two is a bad idea.
I disagree quite a bit. The default for C++ is unsafe, the default for Rust is safe where you explicitly define something as being unsafe. You can argue that as a semantic difference, but I truly think it changes the way people actually write and think about code. C++ lacks any kind of synonymous solution to the Send/Sync traits (that I'm aware of) which avoid a multitude of threading issues. I agree that C++ has implemented many of the features of Rust, it doesn't feel fully there yet, but I'm consistently impressed with the feature set of C++ every time that I come back to it. As someone who spends a good amount of time doing system programming in Rust I will tell you the FFI between C and Rust is absolutely serviceable and dare I say even pretty damn good. I'm really curious what your exact criticisms of it are. The compatibility between Rust and C++ is a bit more painful. However dealing with the C from Rust isn't really that difficult or confusing, nor is vice versa. In fact you can generate complete wrappings to C libraries with the bindgen tool. Mixing C and Rust works fairly well in my experience, and using Rust code from C is a lot nicer than comparatively using a C++ library from C. In fact once again you can use bindgen to do all the work for you and have it generate the C and C++ header files so you can easily write a Rust library that can be used from C or C++, the same is certainly not true for C++.
Honestly Rust's generics vs C++ templates is enough to convince me these days to opt for Rust in many cases. That said it seems like pointing out that Rust will someday age and be filled with quirks and rough edges is a strange argument. It's like saying my current car is old and doesn't start in the cold, and I shouldn't buy a new car because it'll someday be old and not start in the cold. It's kind of a bad argument to say not to embrace new technology because new technology is destined to be old eventually too. That seems like a bit of a fallacy.
Nonetheless I think your article still does a great job outlining how modern C++ can compare to Rust, and how it has made the effort to stay up to date. I don't think C++ is going anywhere soon, but I do think Rust will continue to grow in this space for good reason.
Coming from a security background, I can tell you that there is a provision for writing secure code in every programming language. It's the same argument people use to make for PHP in 2000s that PHP is bad. No Sir, PHP is not bad, It's just that whatever you are writing using PHP is bad.
I think a programming language should solve Engineering problems not academic problems. Rust will a hobby language for a long time. If you wanna create a todo app for your college project you can go with rust but if you wanna create a production ready CRM application, forget about using Rust.
World is running on C++,Java,C# right now. Because there are people who can develop secure code.
That's objectively false. Rust is what Amazon is using Rust for 2 major hypervisors. They use it for Nitro which is EC2's main hypervisor now, and firecracker which is the hypervisor that backs all of AWS Lambda workloads. These are basically the backbone of their 2 most critical compute services. These aren't academic or hobby projects. You're comparing apples to oranges, no one is writing CRMs in C++ and Rust wouldn't be a good choice either. Plus CRMs are just outright bad examples of what a system language is useful for, because a CRM is just pure business logic, you're better suited that gives you high level representations of business logic (Java, C#). I know several companies using Rust for embedded on production robotics systems now (hint, I'm one of them). The world is running about 700 languages right now, the world is running COBOL that's not necessarily a strong endorsement for the use of COBOL.
Like you said there is a "provision for writing secure code in every programming language", and the reality is that doesn't really start or end at language semantics or idioms. A decent C++ developer who is also proficient in Rust should have a pretty good idea what's going on in either language with a similar understanding. Having a more pedantic compiler only serves as a benefit. Don't take my word for it go look at what the industry is doing. They're writing critical pieces of system software in Rust at many large companies, they're writing firmware, control systems, and databases in Rust. I'd urge you to do some more research.
Also nitpicks about Docker. I'm a core contributor to a container runtime actually. Docker is written in Go and is in fact what is called the "high level runtime", so it does very few OS interactions and uses a "low level runtime" for actual container creation. Docker basically just provides a standard interface (CRI) which handles pulling images, extracting the filesystem, and converts inputs into a standard format for the low level runtime which and communicated with the low lever runtime per the OCI spec. Docker's default runtime, and by far the most popular runtime is runc, and runc is also written primarily in Go. It was honestly probably a bad choice, but it's there and it works. Runc handles things like namespace creation, pivot_root which changes the root filesystem of a process, cgroups configuration, etc. Problem is with Go, it actually is completely unable to do certain system calls mostly pertaining to process namespacing. This means that Go actually has a small C program which it's shipped with that it invokes to handle this. This means runc has to spawn an entire process just to do a number of syscalls that Go cannot perform. Red Hat has an OSS project called crun which is a C runtime that is much faster, but it does have a history of having some memory issues.
So Golang is absolutely doing much of the low level work for dealing with constructing containers, apart from I believe 2-3 syscalls which had to be forked out into a process written in C. Lots of complicated, and even surprisingly low level code has been written in Go. Lots of large projects have been written on Go. Kubernetes is all Go, and it's a rather large and complicated project. I'd argue that C++ isn't incredibly scalable either, because you still need some concept of how memory is being handled and the compiler has no solid guarantees still, and you're kind of just expected not to do anything stupid which is a bad general rule when you're talking about humans.
For Rust C++ interop take a look at cxx.
All the features of rust are also in C++? I didn't know that C++ provided an accurate borrow checker. I didn't know that C++ had a clear boundary between code that can cause UB and safe code, while still allowing safe code to be efficient. I've seen lots of attempts at a borrow checker in C++, but I doubt Microsoft and the Linux community would take a serious look at Rust if there was feature parity.
The main niche for c# is in enterprise IT shops that are Microsoft centered. That's a lot, so it isnt going away. It's also used to make windows gui apps. Probably easiest way to get something out quick for that.
"Go didn't clamed to replace anything", nop it was originally intended to replace C/C++ at Google , devs said no thank you.
"
'Btw Windows Phone was way more superior than iOS and Android"
No it wasn't . It was late buggy and useless.
Seems like we have the same opinion. As someone who has been programming for just more then a year in mostly cpp. I don't think rust is bad but I don't see any point to switch currently.