Hacker News new | ask | show | jobs
by bangaladore 263 days ago
One of, in my opinion, the largest problem with Rust is that they sought to solve two problems:

1. Memory / thread safety

2. They didn't like C/C++

And often times it feels like there is more focus on problem two than problem one.

Quite a bit of idiomatic and safe (yes that does exist) C++ doesn't "translate" well to Rust without large amounts of rearchitecting. I'd focus more on converting C/C++ to languages nearing the safety of Rust but without it being such a huge shift. Like converting C++ to C#.

8 comments

To be honest I don't buy it. The biggest problem with translating programs to Rust, IMO anyway, isn't actually dealing with the chasm between mentalities regarding programming language design. I don't disagree that Rust intentionally goes a different way in many regards; obviously it focuses on composition over inheritance, and takes more inspiration from ML. But still, that isn't really the problem. It really does come down to the fact that appeasing the borrow checker is hard. It only accepts valid, well-formed programs according to its rules, but it rejects a ton of completely safe things in the process. It's a tradeoff.

Literally just not being able to easily and efficiently express interior mutability completely changes how you design both code and APIs. Unsurprisingly, since they evolved in parallel, C++ is pretty well-suited for old-school widget toolkits like Qt, but Rust is not. It's not just a matter of having to retool things for composition... The entire view and data model just doesn't work very well. Instead with Rust you wind up seeing the vast majority of toolkits go for immediate mode or functional reactive flow designs that look like React.

I'm not Rust expert but this is basically my opinion on what's really going on. I don't think it's a hatred of C/C++, especially since I think C especially translates to Rust perfectly well ignoring the borrow checker. Rust found one way to do safety and it does reject some valid code and make some patterns awkward or necessarily inefficient... There are others but it is clearly an area of open research.

> Literally just not being able to easily and efficiently express interior mutability completely changes how you design both code and APIs.

The issue is that fundamentally interior mutability is hard to reason about. It requires a lot more temporal reasoning to make sense of and ensure the safety of. Leaning into the type system Rust has does make interior mutability harder when you have "temporally based" safety arguments. It's a lot easier to reason about correctness in the model Rust uses.

Have you looked at the godot-rust bindings? They've gone very far to make the Godot object system work well going between C++ Godot code and Rust. I would love to see that model adapted to Gtk.

Unfortunately, I don't think that's avoidable. This is equivalent to lamenting not being able to use Haskell-style pure FP, nor object inheritance. There are C++ (and C) design patterns that will just not work in rust, or won't work in an ergonomic way. The solution is to solve the problem in a different way.

I will add a #3 to your list: Make an all-around nice language I think playing up rust as the memory-safe language underplays its value.

I don't think #2 is at all fair. I'm certainly of two minds about Rust and its ergonomics. But #2 seems to assume that C is some kind of default and canonical programming model, and to the extent that I like rust, its because they made different and internally consistent design choices.
C/C++ is the "default" language they are/were trying to replace with Rust. So I think it's fair to point out that Rust made design decisions explicitly contrary to design decisions of C/C++ style languages even though Rust is meant to replace it. That's going to (and does cause) problems.
> design decisions explicitly contrary to design decisions of C/C++ style languages even though Rust is meant to replace it

Yes, but that doesn't have to do with whether they "like" C++ or not. What they "liked" is a programming model that could possibly be theoretically proven safe by any sort of tractable static analysis, and that inevitably means making decisions contrary to C/C++. Achieving their design goals was more important than adhering to C++'s mistakes for sentimental reasons.

You are confusing problem 1 (memory / thread safety) with problem 2 (being distinct from C/C++). I'm not here to argue about changes made that are necessary to solve problem 1, but I'm also not here to pretend that all the differences Rust has compared to a C-style language like C/C++/C# is largely due to supporting memory / thread safety.
You continue vaguely asserting "differences" and then retreating when challenged. So please be specific: what differences?
But C is the default and canonical programming model.

It is the native language of every major operating system.

It is the language most closely tied to mainstream ISA assembly, and—symbiotically—which mainstream archs have tried to optimize for.

It's one of few languages that are completely public, in the sense that it is not de jure or de facto owned by a single market participant.

And it is the only language that both has standardized ABIs (per platform) but API and ABI compatibility implemented in a huge number of other languages.

There is no extern "Rust" {} in C++. There is no with Convention => Swift in Ada.

There is extern "C" and with Convention => C exactly because because C is the de facto standard that everything has to interface with.

For historical reasons. Which are very good reasons, but IMO we shouldn't just be forced to deal with the first somewhat okay solution we come up with for now until the end of time.

C is a fine language, but there are so many glaring and obvious mistakes.

At the time that Rist was created, C/C++ and Java were pretty much the only industry standard languages.
No, even by 2010, Javascript, PHP, and Python would have all already surpassed C and C++ by number of professional programmers in industry.
None of those are systems languages.
The parent's claim wasn't about systems languages.
It was about C/C++ and Rust, both of which are systems languages.
> They didn't like C/C++

Riiiight. You do realize they made syntax similar to C/C++ on purpose to ease Mozilla's C/C++ programmers into it.

It's not that they didn't like it; it's that C/C++ is about as disinterested in memory/thread safety as you can get. It's been what, ten years since Rust became 1.0? And the safety needle of C++ hasn't budged a femtometer.

> Quite a bit of idiomatic and safe (yes that does exist) C++

Sure, so does legible Brainfuck. However, it's extremely challenging to write it. It usually takes years and years of effort, chasing down obscure bugs.

> Like converting C++ to C#.

If you can take GC pause and not wince, sure, go for it. Not everyone can take that luxury.

> And the safety needle of C++ hasn't budged a femtometer.

That's not fair. C++ 26 gets from the uninitialized primitives by default being a massive footgun to only slightly worse than using Rust's unsafe core::mem::uninitialized function - which was deprecated in 2019.

Now, sure, in a good language this mistake shouldn't even compile, so C++ moved from "Reprehensibly awful, do not use" to "Very bad". But that's more than a femtometer.

C++ is much more safe than C and has numerous safety contracts that are impossible to represent in C. Its always weird when C and C++ are thrown together.

Barne has talked about it, but one of the primary reasons he created C++ was to address safety issues in C. And he's talked about this since the early 90s.

Like access modifiers and private by default. Something we take for granted now, but something which is impossible in C.

Or std::vector. Unlike array in C, it won't blow up if you add too much stuff to it. Again, obvious, but at the time, revolutionary.

Or exceptions! We take them for granted to!

No more forgetting to check errno! No, if you don't catch an exception your program terminates, so you have to handle errors.

Or, the biggest one of all: RAII and ownership. Might sound familiar to rust devs!

Point is, C++ is not C. That's why C++ exists. Its not safe, but it's much, much safer.

> C++ is much more safe than C

The issue Mozilla faced wasn't that it wasn't safer than C. It's that it was not safe enough for their needs. A chainsaw is safer than a saw blade; you still don't want to trim your beard with it.

And the C++ working group, to this day, hasn't even moved one inch to accommodate those needs. As another commenter noted, they added a feature for C++26 that Rust abandoned circa 2019.

They couldn't multithread the components like compositor and renderer as much as they would have liked, even with all the caveats.

> The issue Mozilla faced wasn't that it wasn't safer than C. It's that it was not safe enough for their needs.

I would agree with this for most use cases. My main qualm is lumping together C and C++.

It's like lumping together Rust and JS, because they're both memory safe. But Rust is WAY more safe. JS is, overall, an extremely footgunny language.

In my view, the jump from C to C++ is about the same as the jump from Rust to JS, potentially even bigger.

> Quite a bit of idiomatic and safe (yes that does exist) C++ doesn't "translate" well to Rust without large amounts of rearchitecting.

How? If you're writing modern safe-ish (still very unsafe though) C++, then you're going to be avoiding shared mutability and using lots of smart pointers which translate straightforwardly to Rust.

C++ and C# share a letter only. They operate in entirely different domains. You can certainly try to write PLC logic or a an IMU Sensor in C#, but that's probably not going to be a fun task.
C++ is used in many non-low-level domains simply because of performance, due to the many kinds of zero-runtime-overhead abstractions it offers. There are e.g. popular game engines written in C++. LLVM is written in C++. Some DBMSes are written in C++. Etc.

C# overlaps C++ in all these “performance-sensitive high-level code” domains.

Given the topic of the thread is DARPA it's unlikely they're going to benefit from the type of overlap C++ and C# have in game engines or DBMSes.
I'm very familiar with both. My day job in defense is bare metal systems with C & C++ and often integrating them with C#-based test infrastructure.

Is C# perfect for every task, no. But it's probably suitable for most of the tasks that DARPA is targeting to support. The reality is that low-level languages were used in the past because generally our computers were less efficient, and the higher-level languages didn't exist. Most things today written in C++ would probably be written in a higher-level language if designed today.

Infact, I know of a specific case where a vendor is currently in hot water because a GUI tool running on a standard windows machine is not memory safe when in this case some agencies think it should be. This is probably similar to the vast majority of C++ code DARPA is concerned with.

Examples?
My best example of a "real" and not more artificial example (like XYZ data structure) is Game development / game engines & UI.

For reference: https://news.ycombinator.com/item?id=40172033

A bit surprised that you didn’t mention Bevy in your post. Have you worked with it?
Not my post, but I've heard the same concerns with Bevy as with the others. And the actual blog post linked by that post does mention Bevy many times.

Infact Bevy might be a perfect example of my gripe(s) with Rust. Completely throwing a standard object system out the window in-favor of ECS which still hasn't caught on in even the most used game engines like Unity hurts adoption and usability.

I thought Unity and Unreal were transiting to ECS? I was under the impression at least that Bevy was adopting what the industry was moving towards, not exploring virgin territory.
I'd very much consider ECS virgin territory. DOTS (ECS) in Unity has been out for 5+ years with little to no real adoption. I'm unaware of any pretty much any use of ECS in Unreal (I think what exists is mostly focused on internal graphics / animation, not gameplay).
Doubly linked lists. Any cyclic data structure.
While I think this is Rust's biggest flaw, this doesn't stem from any particular hatred of C/C++. This is related to memory safety, as it is very difficult to reason about memory lifetimes of object graphs with cycles.
There are doubly-linked list libraries in Rust. They are safe and well-designed. It's rare for a project to actually need a doubly-linked list. When you need it, you should use those instead of reimplementing your own.
Both of those are a direct consequence of Rust's memory model, not a result of animus against C++.
That's not at all a "we don't like C++" problem. That's "the chosen borrow-checking model makes cyclic structures hard, you have to do Rc/Arc and some manual management, or use unsafe and raw pointers". (Frankly, the latter is easier.)
Ref counting doesn’t work for cyclic data structures
Sure it does. Make the backreferences weak, or use a library that provides cycle detection (or even full-on tracing GC if you really want).
That changes the semantics. It won’t work for a graph for example.
It doesn't fully handle the memory management, but it handles having shared references. You can use weak references or manually break the links when you want to free something. Or you can use unsafe raw pointers, which frankly seem simpler. Either way you're going to wrap it in a data structure that encapsulates all the details.
It works well. One easy trick is to have one reference count for the whole graph.
Rc has downgrade and the Weak type explicitly for this purpose.
The easiest way to implement these is with Weak references in one of the directions. This requires some checking and/or locks, but the fact it is not trivial to do is kinda the point: the integrity of a cyclic data structure depends on managing multiple pointers in multiple structs simultaneously, and with that comes concurrency dragons.
Syntax is different any many places for no apparent reason
> They didn't like C/C++

What?

> Quite a bit of idiomatic and safe (yes that does exist) C++

Reminds me of the “yes I’m vegan, yes I eat meat, we exist” meme.

C++ is an unsafe language, but there is lots and lots of safe C++ code. Most C++ code is safe, that's why every other line isn't a segfault. Safety, as a whole, is about catching edge cases.