166 comments

[ 2.5 ms ] story [ 109 ms ] thread
Rust is Pinky and Brain's attempts to take over the world.
Ways to figure out where the bug actually is when using systems built from different parts feels like an underexploited area.

Many things in software actually play this role, from obvious thing like unit tests through to using popular software (if it works for everyone else then it's probably your bug). If no one else uses your exact Chipset/OS/language/compiler/library (version) matrix then the bug could be anywhere.

I'm not sure it has an official academic name though. Modularity? Re-usability? Safety? Reliability? Predictability? Repeatability? Good ecosystem? There's a few things that overlap and combine.

This was interesting:

> At this point, while reflecting on that topic, I decided to look more into the origins of the drill/hole adage; that diversion led me to a lovely post critiquing the adage, saying it “doesn’t go far enough.” The heart of the argument there is that people don’t want holes either. [... ]

but then TFA didn't actually go there for Rust. After laying out a great example of how the purpose of a hole is ultimately about time (and possibly frustration), the author fails to reach a similar end-goal for Rust, despite hinting at it:

> But, thinking of the drill/hole adage, I stopped and asked myself: “Who wants safety? Is it an end in itself? If it is merely a means to an end, then to what end?”

What is the true end-goal? Saving lives/money/property by avoiding errors?

I find it kinda amusing that the New York Times lead reporter on cybersecurity has a book out literally called "This is How They Tell Me the World Ends" and we're on the worlds premier hacker forum pondering about the point of safety in software languages.
Have you read it? Is it good? Maybe submit a link to a review?
You seem to be trying to make the point that is should be completely obvious what the point of safety is.

And yet so much (not all, but a substantial part) of what that book is about has very little relationship to language safety. Rust will not protect you if there's a backdoor left in the system. Rust will not protect you if there's no password, or absurdly weak passwords. Rust will not protect you if your entire system design is predicated on a perimeter defense with no internal checks. Etc. etc.

Now, I'm not so stupid as to believe that we shouldn't do all we can, and that can include language safety. But by itself, that doesn't have a lot to do with the huge end goal laid out in the book, which might be summarized as: be able to build computational systems and networks that are extremely resistant to unintended access, utilization and modification in pursuance of personal, political or national goals".

> And yet so much (not all, but a substantial part) of what that book is about has very little relationship to language safety.

Yes, yes. I know that.

But we literally have a book floating around around THE END of the WORLD and us nerds can't justify even the first step around fixing these systems. It's like someone asking what good fire hydrants are since they won't help with battery fires.

I can’t believe people care about cybersecurity when climate change is a bigger threat to us all ad nauseam.
They don't need to be mutually exclusive. They operate on different time scales too (or can). And the nature of the solutions is fairly different in each case. Were someone actually able to hack into a power generation plant and destroy it, they might actually intersect in some way.
Meanwhile PL design (in particular memory safety) doesn’t impact cybersecurity? That seems to be the indirect implication (going by GP).
My point about PL design was that it may not be the most important issue with cybersecurity, and that even if it was, there are still many other important issues that it does not impact.
I had a similar thought; TFA:

> Can I just say “Rust developers spend less time debating about who is responsible when issues arise, and they spend less time figuring out how to get a performant solution into shape”?

The author sneaks in the assertion that issue attribution is the primary cost of issue resolution. I don't think this is true at all. What about actually writing & testing the patch?

If Rust has a technical approach to solving issues, then Go has a social approach. The latter is so darn simple that an intermediate Gopher can grok a codebase and contribute patches relatively quickly. Go is easy to hack; it's C with garbage collection and concurrency primitives (and an excellent ecosystem). That's why it was made!

I think Rust's primary value proposition is expressiveness. People enjoy writing Rust, because they can represent complex ideas with few LOC. Safety is a distant second. It's a language for enthusiasts, not products.

If you want language where safety is truly #1, well, Ada is going on half a century of usage in safety-critical systems including aerospace.

No, Go is "simple" but big Go codebases are not going to be simple. It will actually be simpler to get onboard on a larger Rust codebase, because Rust offers a higher variety of tools to define modularity boundaries.
Go has interfaces and namespaced packages. Not everyone uses them effectively. Codebases can always be overcomplicated by careless abstractions, even in the simplest language.

> Rust offers a higher variety of tools to define modularity boundaries.

"Higher variety" is among the last things I want when trying to understand a big new codebase.

> No, Go is "simple" but big Go codebases are not going to be simple.

Can you expand on this? I actually lean towards the same belief but wants to hear your reasons.

Can any gophers suggest one or more exemplars of simple big codebases for us to test our beliefs on?

> I think Rust's primary value proposition is expressiveness. People enjoy writing Rust, because they can represent complex ideas with few LOC. Safety is a distant second. It's a language for enthusiasts, not products.

What nonsense. Companies across the board are adopting Rust not because it has some hype behind it, but because it solves real problems, like memory safety and performance.

Go and Rust are from the same generation of programming languages. Yet one is building mass-adopted software like Kubernetes and Hashistack and Prometheus/OpenMetrics, while the other is pretty firmly in hype & thinkpiece phase.

I can't imagine a serious blog post in 2022 questioning the purpose of Go because it is evident in the large amount of enterprise software being written in it.

> Go and Rust are from the same generation of programming languages.

Go 1.0 was released in 2012 and the language has barely gained any highly impactful features since then (generics aside, which are quite new still). Rust 1.0 was not out before 2015 and the 2018 edition already introduced huge changes, with more in the pipeline even today. It hardly seems sensible to describe them as being in the "same generation".

Fortran: 1957

C: 1972

Go first (real) commit = 2008

Rust first (real) commit = 2010

Versioning schemes are incomparable. The two langs are from the same generation, period. To suggest otherwise requires mental gymnastics.

Go is a language for people that think being able to learn a programming language in a couple of hours makes it good. C-like syntax is not an inherently good thing, it's just familiar. Thus Go is good for people who don't like to learn and/or find learning difficult.

Simple constructs such as sum types do not exist in Go. How do you express that a value is either type A or type B in Golang? Go, in its infinite simplicity, does not allow for that, instead it allows you to express that a value can be type A or type B, type A and type B, or neither! Simple right!

And then errors! Go takes the simple approach with regards to incorrect code in that it just does not care if your code handles all possible error states or not! Simple, just don't give a shit!

If your career is in software and your decision making process for a programming language is "what can I learn in an hour?" then your decision making abilities are questionable.

You can represent sum types with type assertions on interfaces.

Frankly, outside of subjective error handling preferences, I don't see much value in sum types. They encourage building towers of type abstractions and obscure what is happening on the wire.

> obscure what is happening on the wire

They obscure nothing, sum types in rust have 0 overhead. You cannot in go faith argue that Go gives a more accurate representation of what occurs "on the wire" than Rust.

> If your career is in software and your decision making process for a programming language is "what can I learn in an hour?" then your decision making abilities are questionable.

I posit Rust has a poor return on investment. If you're going to spend time learning a new language then make it a language that completely changes how you think about programming: something like Clojure, Scheme or Haskell. Even if you never create a single system using these languages you will be a better programmer for having learned them. I'm not so sure the same can be said for Rust.

It's not about learning either. It's about what tool generates the best output.
Interestingly, what the adage left out, is the qualities. People don't just want a hole, without qualification. They want a hole that's reliably uniform (smooth bore, sharp edge), quick and easy to produce, and cost effective.

If Rust can avoid more errors with nearly the same performance profile (and control) offered by C, it's an improvement. The Hole purpose is to be a better low level language.

Also, there are people that want a hole and there are those, that are selling hole making to others. The latter would indeed want to buy the drill.

A restaurant customer doesn't care what knife the chef used. But chefs still choose to get different specialized knifes for different tasks.

Is anyone writing a Python interpreter in Rust? Or an OpenSSL fork? Cert parsing libraries at least? I know there is a project to rewrite coreutils into Rust, seems that would also be a good demo. I don’t think the kernel drivers thing has landed yet, but it is also an interesting project.
There's a JIT framework in Rust: https://github.com/bytecodealliance/wasmtime

There's a library for doing full X.509 certificate parsing and verification: https://briansmith.org/rustdoc/webpki/

There's definitely some attempts at doing pure-Rust SSL, but I suspect a lot of them are also doing some sketchy things with crypto that shouldn't be trusted (getting constant-time stuff implemented properly is really challenging, and probably requires large amounts of assembly to guarantee correctness).

While not Rust, there are definitely Python implementations in safe languages, namely Python itself, Java and .NET.
This is (to me) a very odd article. It creates some straw man definitions and points out that Rust doesn't hold up to them, and then gives a more accurate definition and complains that it isn't expansive enough. It concludes by pointing out that unsafe code is unsafe.

Speaking personally, Rust offers a rather nice featureful syntax (and libraries), and saves me the trouble of worrying about certain kinds of very typical mistakes.

I may want a hole, but a cordless drill with a comfortable hand grip is very likely my tool of choice. Especially thinking back to my father's corded underpowered temperamental drill with the easy to lose chuck key...

My dad always taped the chuck key to the drill's cord. Those were the days...
I was surprised to see that it was written by a Rust implementation insider. The first half is very meandering. Please just get to the point and leave footnotes and asterisks for things like “safe”. (Just my preference.)
Moreover, at some point the rubber meets the road and some "unsafe" code almost certainly must exist at that point. The goal should not be to have zero lines of unsafe code, but to have so few that it is possible to review and understand them and to understand why, though they are "unsafe", they yield safe behavior. Rust does do this!
> It concludes by pointing out that unsafe code is unsafe.

It spent an awful lot of time on that without making very good points.

About one paragraph of text could have pointed that reducing the surface area of unsafe code is therefore a good thing, which leads to "rewrite it in rust" which gets you more safe code.

There also seemed to be a little bit of conflation of safe code with bug-free code which just isn't possible. Arguing English semantics of words which are being used to describe very specific compiler behavior is going to be a GIGO argument.

Surely the value proposition of Rust is fewer security vulnerabilities than an equivalent C program.
And no garbage collector pauses or tuning.
Pauses happens when using Rc types with a cascade deletion of deeply nested data structures, and if Drop are incorrectly written, even a possible stack overflow might occur.
> Pauses happens when using Rc types with a cascade deletion of deeply nested data structures

True, but this is inherent to deterministic deallocation. Rust is getting local allocator support to make it easier to manage these tradeoffs. (Local allocators are commonly used already in C/C++.)

Only the call is deterministic, not how long it takes to return.

Local allocators are also a thing in many languages with automatic memory management.

Well, if you just wanted no garbage collector, you could use C.
This article is focusses on the safety features of Rust the language but this is not something that many developers (or me at least) considered when adopting yet another language. For me I was looking todo computer graphics with something that wasn't c++ but had similar performance characteristics and could compile to WASM.

Rust had the best language features for this and the most momentum behind it with things like wgpu and bevy. Fighting with the borrow checker and unsafe Rust is not something I do all day or every day, it is just something you live with.

From the title, I was sure this was going to be an article about typed holes.
The value proposition of Rust is that you can Rewrite Stuff in it and it's going to generally run faster, with fewer bugs, taking up less RAM and generating less heat in your processor. The rewriting part is the whole point - that's where all the fun is! I'm not sure why so many devs complain about being told to RIIR. Who doesn't want to be using state of the art tools when coding and developing their stuff? Software is eating the world anyway, so why can't Rust eat software?
I don't want to get paid to write code. I want to get paid to solve problems. My least favorite type of problem to solve is "how do I explain ABC solution in Language 123". I hate it even more when ABC solution is working per any metric the business cares about.
I think greenfield projects in Rust make a lot of sense. However, for some existing projects, the math just doesn't check out.

I worked on Google Earth for a few years, and the core was in C++. With ASan and modern C++, memory safety bugs rarely slipped into production... perhaps once every 3-4 months, and this was a million line codebase with 20 engineers working on it.

When you consider the cost of a memory safety bug (some users get odd behavior), how rare they happen (because of our good test coverage), and that everything's sandboxed in WASM anyway, there's just not much cost to this kind of memory unsafety bug... and certainly not as much cost as a full rewrite.

RIIR makes sense for projects whose memory unsafety causes catastrophic failure. And even then, in some of those cases it makes more sense to use Java or Javascript, which don't expose unsafe operations.

RIIR makes sense if someone's doing something with extreme performance requirements, and they're okay with a tiny risk of memory unsafety (from unsafe code).

All just my opinion though, I'm sure there are many other great opinions out there.

> and that everything's sandboxed in WASM anyway, there's just not much cost to this kind of memory unsafety bug...

Presumably, without the potential for memory-safety bugs, there'd be no need for anything like a WASM sandbox, no?

If so, then can't the costs of the WASM sandbox (overhead, potential exploits in the JS/WASM runtime, etc.) be tallied under the column of "costs of memory-safety bugs"?

In about the same sense that e.g. the costs associated with running a Web Application Firewall in front of a Wordpress instance, can be blamed on how vulnerable/exploitable Wordpress+PHP are as a stack.

If you avoid introducing an attack-surface in the first place, then you don't need to spend effort on guarding it.

An interesting thought, but are you suggesting we could run arbitrary Rust code, unsandboxed, in users' browsers?
Miscommunication, I think.

In the context of a web browser, the browser JS execution-context is itself already a sandbox, so running WASM there isn't necessarily doing any sandboxing per se (although it can); it's more just serving as the current state-of-the-art way to host arbitrary native code in the browser. (Too bad about PPAPI.) You'd still be using WASM here whether there was any sandboxing benefit or not.

I was instead more thinking about the Google Earth "native" desktop + mobile apps. Those are the environments I presumed you meant when you said that Google Earth is "sandboxed by WASM." Those deploy environments are where adding an intentional sandbox layer would get you some additional safety, over just having the user run a "raw" native C++ executable on their device.

Thanks for the clarification, yep I meant the web client.

We didn't rewrite iOS/Android either, any memory unsafety bugs just cause odd behavior on that user's device, and wouldn't e.g. give an attacker root access to our servers. The costs of the occasional memory unsafety bug didn't seem to approach the cost of a rewrite.

I should say, rewriting servers (especially public-facing ones) in a memory-safe language like Rust or Java is a much more reasonable proposition, but for client code, it's a slightly different story.

If you want to eliminate memory-safety bugs you cannot use unsafe Rust. Restricting yourself to safe Rust also has a performance cost.
If anything, having such a large code base makes good coding practices even more, not less relevant. It goes without saying that rewrites on something that large - whether to Rust or to some other safety solution, such as C++ with Core Guidelines support - should be targeted to pick the most valuable and lowest hanging fruit first. But the advantage of Rust goes far beyond mere safety, and this is where your comparison with Javascript or even Java might miss the point a little bit. Google Earth itself is a bit like a video game; it doesn't strike me as something where either performance requirements or long-term maintainability are that irrelevant.
That sounds nice on paper. We all like good coding practices. We all like Rust's benefits, not just the memory safety ones. My argument is a cost/benefit analysis; those nice benefits aren't worth the massive cost of rewriting the whole thing in Rust.

In an actual business, one has to justify a project's existence, by showing growth, new features, new users. Imagine stopping that while we rewrite a million line codebase. Now imagine a project which doesn't bring in revenue, and just delivers social good, while having out-of-touch executives looking at our resources and headcount like hungry vultures.

Rewriting in Rust would have cost us years, and would have killed Google Earth.

> rewriting the whole thing

It's not something that has to be done wholesale, obviously. Language interop between Rust and C++ is constantly improving, with one goal being to make rewrites happen gradually while keeping the same interface wrt. outside C++ components.

Alas, doing it gradually doesn't make the cost/benefit any better. It might slightly reduce the short-term risk of the product dying, but it would also increase the medium-term cost of the rewrite.

The boundary between C++ and Rust code is often a lot trickier than one might think, because one has to reconcile conflicts between C++ paradigms and Rust paradigms... when one considers all of the temporary code that reconciles those conflicts, we see that the cost just went up.

And then moving that boundary is tricky to do in a healthy way, especially when using proper A/B testing practices which require us to have both the old and the new code alive in the same binary.

Rewriting often sounds like the solution to things, but in practice it's a very risky and costly thing to do. See also: https://www.joelonsoftware.com/2000/04/06/things-you-should-...

A hybrid solution involving C++ and Rust would make your operational costs soar. No sane person with a budget they're being measured against would ever advocate for that. This gets to the whole problem I have with Rust - I don't see its value proposition. If I have an existing C++ project it makes no economic sense to migrate to Rust. If I have a greenfield project then what is Rust bringing me that Go isn't? Keeping in mind it's far easier to build a team comprised of competent Go developers than it is to build one comprised of competent Rust developers. It seems to me Rust fills very niche cases.

What am I missing?

Nothing really, Rust's killer application are domains where using a language with automatic memory management and support for value types isn't an option, trying to use it elsewhere, while possible is sacrificing productivity.
I really don't agree with this. I feel like we have to get pretty heavyweight in terms of data structure complexity before a GC is paying off enough that I'm glad I'm not in Rust productivity-wise.

That's across Java, Go, C#, Python. Maybe there's a GC language I should be using where all this feels easier, but if so I don't know what it is.

We have to agree to disagree then.

Having to create borrow checker friendly data structures doesn't bring anything to the table when writing GUI applications (including design tooling), distributed applications (Akka, Orleans, Erlang style, RDMS SP), CLI tooling, compiler tooling....

In what concerns languages with automatic memory management and support for value types, my list is somehow different, D, Nim, C#, F#, Swift, Go, Linear Haskell, Ocaml with Effects, Eiffel, Common Lisp.

And I leave Herb's talk regarding those issues with RC types,

"CppCon 2016: Herb Sutter “Leak-Freedom in C++... By Default.”

https://youtu.be/JfmTagWcqoE

We certainly do disagree on this.

Even the first chunk of Herb's talk, before you get to reference counting - illustrates why you might feel more comfortable in another language compared to C++, as once again C++ has the wrong defaults. Rust's defaults are better.

Nullable shouldn't be the default. It's really hard to undo this bad decision, it's not one of the easy ones where I think C++ realistically could (but still won't) just fix it, but it's still a mistake. By getting this wrong C++ adds an unnecessary burden.

Since Rust doesn't get this wrong that burden isn't present. I am never worrying that the Box<Thing> in a Rust structure might not be there, by definition it's a Thing in a Box, if it might not be there that would be written Option<Box<Thing>> and the compiler would let me know if I ever forgot to account for the None case.

And it keeps happening. Later Herb wants an array of known-at-runtime size on the heap, so, he makes one with unique_ptr but of course by default C++ doesn't remember how big this is, so he needs to make sure he tracks it separately, more anxiety. Rust can Vec::into_boxed_slice() and the resulting slice automatically remembers how big it is, even though you've given up the vector's ability to grow or shrink. The machine representation ends up the same if you do it right in both languages, but C++ gives the programmer another thing to worry about.

Except that still doesn't make Rust better than the alternatives with automatic memory management outside kernels, drivers and domains where Ada/Spark is being used nowadays.

Even Google isn't comfortable into pushing Rust into app developers for their OSes, despite the amount of adoption at kernel and driver.

So when Android comes out with Rust Compose, Fuchsia does Rustter, or Native Cloud folks migrate in mass to Rust, then I might eat my hat.

Naturally you might refer to Rust/WinRT, whose tooling is a joke versus C++/WinRT, let alone using .NET alongside Blend and VS.

Doable sure, then again there are people that also insist into using COM from C, regardless of how sane that might look like in practice.

So unless Rust reaches a state where ownership is transparent to app developers and distributed computing stacks, we will keep on disagreeing.

My assertion is that Rust gets enough of this other stuff right that unlike C++ it doesn't start out more painful than languages I've used with GC. I can only speak for my own experience writing software in these languages and so that doesn't allow for questions like whether Rust programmers are rare or expensive which might influence whether you make a .NET thing or a Rust thing.

When things get more complicated sure, Rust can mean you spend too much time figuring out how lifetimes should best work compared to a GC environment. But even a fancy GC doesn't promise to release unused resources promptly, so for non-memory resources you can end up needing to care about lifetimes anyway, and the GC languages do not prioritise this problem.

FWIW the phrase you probably wanted is "en masse" from the French meaning "as a body" not in mass.

You keep missing the point why I use automatic memory management when describing languages like D and Swift instead of GC.

Exactly to make the point that those languages offer the same deterministic tooling and not mix with how Java does it.

I haven't written any Swift, or D but as I understand it Swift just chooses to do reference counting everywhere. Maybe it at least factors out the places where this is a waste of everybody's time? I can't tell.

I don't see that as any kind of upside over Rust. It sounds like one of those "my first Rust project" codebases full of Arc<Thing> when Box<Thing>, Thing or sometimes even just &Thing would have been appropriate.

In fact this then makes me realise you consider "it has reference counted smart pointers" to be "automatic memory management" but then you say Rust is suited for situations where that isn't possible, does that mean you didn't know Rust has reference counted smart pointers (two kinds even)? Or does it mean you consider all of Rust above core to be superfluous (Rc is in alloc) ? Either way this makes very little sense.

And so I went back and now I'm also puzzling what you think Value Types are and why you believe that's relevant. Is the problem that you bumped your head and now you think Rust is Java ?

This would have been more relevant had Rust existed 30-35 years ago when C++ was ascending to supremacy. As it is, C++ is being pushed further and further into niche use cases and Rust is competing with C++ in those ever-decreasing niche use cases. That was my point in the first place - Rust seems like it's too little, too late. Add Go to the mix and there's even less of a reason to use Rust. It feels like Rust is obsolete before it even got started.
> one has to reconcile conflicts between C++ paradigms and Rust paradigms...

The modern trend is closer to refactoring C++ code so that it's more Rust-like, not the other way around. The C++ Core Guidelines include plenty of indications on "paradigms" and overall design, so this is something C++ developers are being asked to do anyway. But unlike these, Rust is fully intended to ensure no unsafety in the safe subset.

This isn't true at all IME. Rust's paradigms are great a lot of the time, but the best C++ code does not necessarily look like Rust code in all situations.

There are a lot of patterns in modern C++ which the borrow checker rejects, for example the observer pattern and dependency injection (the pattern, not the frameworks), which are often the best tool for the situation.

Also, are you saying that the C++ Core Guidelines encourage us to make code more Rust-like? I would love to read up on that, if you have a source.

Thanks for the link.

I don't see any occurrences of "Rust" in this document...

Thanks! This article makes some nice recommendations, but they don't have much to do with Rust, these things have been in a lot of other mainstream languages for a long time. I'm not sure this supports zozbot's claim that the modern trend is to "refactor C++ code so that it's more Rust-like" very strongly.

I also assume they meant that that we should adhere to AxM in C++ (since that's the only thing new Rust brings), to make interop with Rust easier, but I could be interpreting incorrectly.

> But the advantage of Rust goes far beyond mere safety...

Could you say what they are?

For me, it's a pleasant syntax to work with. The code structures make a lot of sense to me. I like the approach of using Result return types instead of exceptions really works well (especially with crates like anyhow and thiserror to abstract away the messiness of how errors are created/propagated) (writing JVM code for my day job, I find myself often wishing for Rust features).
Available in Kotlin and Scala.
True, although they have to coexist with Java exceptions. Also, they target the JVM (I have a vague notion of there being JVM-to-native compilation projects, although some of what makes the JVM appealing would be difficult to impossible to do in native code).
Native code compilers have existed since about 2000 in commercial compilers, and there are JIT caches as well.
Depends what you are comparing it to, but often listed are features of a modern language & type system: expressive generics, pattern matching, sum & product types, iterator chaining, etc
Yes - after writing C++ for 30 years I know how to make my life easy with it. If I never touch the wonky and unsafe bits it just works.

But man, after trying to watch after a C++ project with other kinds of programmers on it I kind of wish it was built into the compiler. Rust is pretty much what I do by convention.

Also when a beginner asks me whether they should start learning C++, prepare for a long uncomfortable silence while I look for the right words.

Rewriting C++ code in Rust is probably not economical.

Rewriting C code in Rust is probably quite economical.

But you have a big advantage working with 20 C++ engineers for a giant company, right? Maybe Rust makes it easier for smaller teams with a normal budget to achieve the same results.
I would love that job. I have occasionally gotten to rewrite someone's old messy code into a new language and it was very satisfying.
I'm not sure to how many engineers this value proposition appeals. We write software to solve problems. We get excited on new and deeper problems. Besides, a sufficiently large piece of software has tons of tangled and non-generalizable business logic that god knows who would be interested in. I can't think of a single reason for me to want to write them.
> We get excited on new and deeper problems.

The value proposition of Rust is to make it easier to solve deeper problems by combining a state-of-the-art language (that will be designed to get out of the way as much as possible) with the best efficiency.

> tons of tangled and non-generalizable business logic

This can often be made more maintainable by using embedded DSLs. Rust includes language support for macros that makes it easier to design and use special-case custom languages.

> If you are interested in helping solve any of these problems, please reach out!

Coincidentally, we're working on these problems with Vale [0] by obviating the need for unsafe, while still having single ownership's performance benefits, by taking generational indices (a common Rust/C++ technique) and building them into the language itself, and by moving borrow checking to the region level instead of the object level [1].

Time will tell if it works out!

[0] https://vale.dev/

[1] https://verdagon.dev/blog/seamless-fearless-structured-concu...

Many PL folks are now looking into ways to generalize Rust's borrow checking approach. Even the Rust community is getting into this kind of stuff with the GhostCell proposal and its many variations. It remains to be seen how such extensions and generalizations might be adopted in a way that's reasonably intuitive and ergonomic.
There is only one language (as far as I know) in the following niche:

* compiles to native code with no GC or runtime overhead

* Facilities for high-level abstraction well beyond those offered by C

* Widely used in the mainstream.

That language is C++. If Rust becomes mainstream, it will be the second language in that set.

Thus, in my opinion, talking about the value proposition of Rust makes the most sense when comparing it to C++. I find it much easier to write and understand Rust than modern C++, and that’s what makes it valuable, for me.

For me Rust and C++ have similar complexity in terms of learning curve and the main difference is where you spend your time. Rust programs have a tendency to work on the first or second try provided you can get them to compile. In C++ it’s easier to rig something up that technically meets the portion of the language spec that the compiler enforces, but who knows if it actually does what you expect and the debug cycle is much longer. Debugging is generally more frustrating and time consuming than simply conceptually massaging your implementation strategy until it fits Rust’s model, at least for me.

Also Rust is pretty mainstream at this point.

Pretty much that. Safety gimmick aside, Rust is (mostly) what C++ would have been if designed with modern knowledge of programming languages theory and compiler practice in mind. It’s not like Rust brings that much novel things to the table, it is has its roots in ML and friends that have been around for decades. It’s just that we didn’t know how to make ML-type languages fast in the 80-ties. So C++ designers did the best they could given the time period and the circumstances.
So ignoring the main point of Rust, it's (mostly) what C++ would have been...

You could do this with basically any language advancement. Ignoring classes, C++ was (mostly) what C... Ignoring GC, Java was (mostly) what C++...

Also, a language is more than the sum of its parts. If it weren't, kitchen sink languages would be the best ones out there, because they have the most parts.

> Also, a language is more than the sum of its parts. If it weren't, kitchen sink languages would be the best ones out there, because they have the most parts.

I've been hugely interested in this recently, at least part of what you are describing is programming language affordances.

> So ignoring the main point of Rust, it's (mostly) what C++ would have been...

"And the sanitation"

"Oh, yeah, the sanitation, Reg. Remember what the city used to be like?"

Yeah. All right. I’ll grant you the aqueduct and the sanitation are two things that the Romans have done.
I think Go has done a lot in the last 10 years to facilitate a mindset shift in our industry to "less is more". For a long time, Go was (and probably still is) ridiculed for eschewing many of the features that programming language practitioners have dreamt up over the last several decades, but as more people have tried the language in earnest they have to grapple with the fact that there are some advantages to not having to grok an enormous feature matrix even if they disagree with Go's specific feature set. The conversation has advanced beyond the "if you don't like a feature just don't use it" justification for kitchen sink languages.
I don’t know if it’s Go that’s been that influence more or if it’s the generally increasing profile of functional programming languages (especially JavaScript!) which have always taken a more minimal approach to features.
Is go really used a lot?

I know some larger corporations use it but I don't hear much about it otherwise. The most obvious plus side I hear about is the small memory footprint and fast boot time which makes it good for functions-as-a-service.

It is also getting generics know which makes it sound like the simplicity was a lie or will be a lie.

Except the critiques for not including generics were valid and the designers finally had to admit they should be in the language. "Less is more" really just meant "omit anything newer than we are used to."
You're implying a contradiction (and a weirdly adversarial one) where none exist. "Less is more" never implied "we will never change anything" or "we got it exactly right with v1". Yes, Go launched without generics so the developers could figure out whether they were really necessary and how best to add them.

I'm sure many will say "well I could have told them they were necessary from the start", but the overwhelming majority of these people are just lucky--they picked a conclusion that happened to pan out. And we know this with certainty because most of these people make arguments for generics where they are neither necessary nor useful--they're merely familiar with languages with generics and they reach for them on first sight of a problem. These people also can't articulate the advantages of not having generics--namely the unreasonable productivity that accompanies everyone writing the same code absent personal flourishes. The very fact that these people consider it a no-brainer that generics were the way to go from the start betrays their error--generics are only just worth their costs, and the emphatically pro-generics camp can only rarely articulate those costs due to their inexperience with other kinds of programming.

My stance is adversarial because Go has wasted an enormous amount of people's time. Not having generics was pitched as a feature, and they spent a lot of effort bragging about how fast compiles were without mentioning that this was because their optimizer was pitiful rather than some great property of the language design. They ignored just about every major development in programming language research in decades and rereleased something they'd already built before, just laundered under Google brand this time to ensure popularity.

The value of generics is obvious if you ever write your own container. Go had pre-Java-1.4 level type safety for any container not specially blessed by the creators. Prior art on how to do them without significant compile time cost was already established by Java, not even some obscure academic language. Go was dumb from the start.

> Go was dumb from the start.

You betrayed your own credibility. As previously mentioned, those who can't articulate the tradeoffs associated with the generics question lack qualifications--they are amateurs, and their opinions aren't interesting to professionals. Consequently, for lack of interest, I'll leave you to your opinions.

Are there other languages with compile time GC prior to Rust? I thought that was a pretty novel feature. I recall an ML variant with region inference, but that was just an optimization I believe for it's runtime GC.

Edit: MLKit was the ML dialect I was thinking of - looked it up

Nothing that has hit the mainstream like Rust. To my knowledge, Rust's lifetimes take influence from a language called Cyclone.
Cyclone I believe (has been a while) used region based inference like MLKit I mentioned. I'm not sure off hand if Cyclone was influenced by MLKit or the other way around. Cool tech, but Rust took it to the next level by making it pure compile time.
What exactly do you mean by compile time GC? Various techniques like compiler-optimized GC have been around for a while. If you are looking for mainstream stuff, Apple’s automatic reference counting for Objective C comes to mind (has been shipping since around 2009)
I mean that Rust knows exactly when something will be deallocated at compile time due to its lifetime system (for things that are single ownership, Rc/Arc excluded). In contrast, ARC does compiler assisted increments/decrements if I recall, but still uses runtime ref count to know if something needs deallocation.
C++ programmers where selectively implementing borrow checkers at runtime decades ago (see library omnetpp as an example). Moving those borrow checkers to compile time with templating is possible (but people did not do it because the borrow checking could be disabled after testing and no overhead would be paid neither at runtime nor compile time). That Rust implements borrow checking as pillar of the language I think it is great.
Ah, I see. True, Rust has a more restricted model that allows it to track lifetimes more precisely. As far as I know, Clang will omit reference counting if it can be statically determined but of course it has fewer optimization opportunities here. In the end, the two approaches are not entirely dissimilar: ARC uses static analysis to detect dependencies and will fallback to dynamic RC n complex scenarios; while Rust enforces certain rules that only allow most basic dependencies and requires the user to mark these by using dedicated tools.
Pony has some references how they came to it before Rust. Easily doable with escape analysis. Just that pony added a proper GC protocol for it's threaded actors and proper concurrency safety by avoiding blocking IO.

More important is tracking the owner, which perl6 used.

Interesting, thx for the response. Pony is on my list of languages to do a deeper dive on at some point in the future. It has some interesting ideas I thought when I last glanced at it.
Could you elaborate on what Perl6 does? I thought it was just regular old GC.
> Safety gimmick aside

Safety is a gimmick?

To be fair C++ is backwards compatible with C. That meant there was a large amount of design space they couldn't explore. Rust not going there gave them the ability to do better.
That intent to be "backwards compatible with C" doesn't stretch so far as to say, provide any way to spell valid symbols from C.

Imagine you have some C that has (for whatever reason) named two important functions "class" and "fn" which are completely reasonable C symbol names. In C++ that word "class" is reserved, so you can't name symbols class, but, that is what the C symbol's name is so too bad? However in Rust, even though fn is a reserved word there's no problem referring to that symbol, you just have to spell it r#fn meaning "the symbol named fn" as distinct from the keyword fn.

C++ is no longer backwards compatible with modern C.
C++ compatibility has improved. E.g. I've noticed that C++20 has designated initializers for struct members, which were introduced in C99. So now if you're writing C that has to compile as C++, you can use C99 designated initializers, if you're OK with requiring C++20.
Like Ada in 1983, or Modula-3 in 1990's, but I digress.
Safety is what brings me to the table. I'm not a genius, I'm not a 10^Nx coder. I'm a guy who wants to make neat things. I've been doing this programming thing for a while and have had my forays into C and C++. I've spend a lot of time in python and go too. The thing I like about rust is that it gives me the level of control C and C++ do without all the mental overhead of remembering "is this for reading, writing, both? none of the above?" for each and every pointer and variable. It's written down in the type signature and then the compiler verifies that for me.

That saves me time and energy - time because I don't have to wait for my misunderstanding to manifest weeks or months later at runtime (in a worst case) and energy because my editor will fill show me signature information inline - I can just glance up a few lines if I need to remind myself of what the constraints of a variable are.

I know for a fact that I don't strictly need this - I am capable of writing C that preserves those contracts, at least for smallish projects. It just takes much more time and effort. And in big projects even the "gods" have trouble with getting it right every time.

In fact, I've been willing to tackle much more difficult problems professionally that I would have shied away from (outside a research setting anyway) without the guarantees rust tooling provides.

The whole "safety is a gimmick" angle always brings to mind a bunch of 9-fingered carpenters sitting around trying to convince their boss not to buy saw-stop because you just gotta be careful using the tablesaw.

If you're capable of writing C that gets things right, even if in just smallish projects, chances are good you could crank out bullet-proof C++98.
The initial C++ designers produced a language which was still very understandable, and in which you could easily write bullet-proof programs.

In C++98 (the first ISO standard version of C++) you can fairly easily organize a program such that any low-level activities are confined to classes that are almost impervious to misuse by the rest of the application, so there will be no memory misuse or leaks, or out of bounds arithmetic.

If Rust takes off, there will be widespread use of its unsafe parts by programmers who are under pressure to deliver something and take the obvious route of telling the machine where to put what bits, exactly like what C++ programmers have been doing.

But tools like cargo geiger will tell you exactly where the unsafe parts are so you can progressively remove them. Also safety is usually terser in Rust, so programmer laziness usually leads to safe code.
Rust already is mainstream. It's being adopted at a very impressive rate and is running in production in innumerable places, serving billions of users.
Add:

* A build system

* A package manager with powerful features

* A toolchain manager for getting different version of compiler etc

* Code generation in the language

* Build scripts in the language

* A test framework

And when I write "a test framework" or "a package manager", it's not just that it has one, but that it has one.

On the mainstream question, since I told friends and colleagues I'm learning Rust, I get a lot of statements like "I think I should learn that too, it looks like its going to take off". That is a strong signal that it has already taken off. Like once regular investors have heard of some stock (or bitcoin).

I have many colleagues who have foresworn C++ but are liking Rust (myself included).

(comment deleted)
It's already happened:

* Discord replaced Go with Rust[0]

* Microsoft's VS Code uses ripgrep for searching through code which is coded in Rust.

* npm is using Rust

* Cloudflare (I believe for their serverless platform)

* Figma (unsure how)

* And I'm sure countless more, hell one of my former employers is using it for mission critical work in place of C++

As you can see Rust is used by some pretty massive services, even if you don't use them, millions of people do. In fact VS Code is the most surprising to me I had no idea it was using it all along. I also believe Atom was looking into using Rust to improve performance for Atom but I'm not sure if it was just native code in place of JS / HTML.

I would argue Rust has entered the mainstream, it will be slow to be far more common, but it is getting there. I will not be surprised if we see it all snowball once there is a full feature web framework like Django or Rails but for Rust with all the batteries included. Go took a little while before it became as big as it did, and some would naively argue Go isn't mainstream, while they deploy code using docker to their kubernetes cluster (for those who missed it both of those tools are coded in Go) or what have you.

[0]: https://discord.com/blog/why-discord-is-switching-from-go-to...

I’m impressed with the adoption of both Rust and Go. Seven years ago I wouldn’t have been surprised if Rust had just become a language for PL enthusiasts and Mozillians, and that Go had just become a language for worse-is-better enthusiasts and Googlers. :)
I work at a 100% Rust shop, so I’m well aware that it’s being used for real stuff. I agree with you, but it still has a long way to go before it’s as mainstream as C++ and has a similarly mature ecosystem.
I think you make that point better than the author.

The author talks about drills and holes, but to me, the conversation is more analogous to cordless drills versus regular electric drills - they both can do the same thing, but have different characteristics about the process of drilling the holes.

People make good money with renting out drills, so I'm not so sure about that analogy.
(comment deleted)
I thought of this classic drill article: http://www.team.net/mjb/hawg.html

Not sure that is the Unix philosophy but definitely the attitude of many 90s C programmers. But also we want power and safety at the same time. A smart matter drill, if you will, that will dissolve when it hits flesh. Rust currently ushers a lot of thought about safety into the coding process, while with C you can start dangerously and then fix later with Valgrind/Purify etc. fun but bad results for OpenSSL or sudo or parsers in general.

I think Rust’s hole purpose is to be an ergonomic language that supports modern practices and generates very fast executables. Safety is a nice thing to have, but that’s just an icing on the cake for folks who need it. For me at least, a proper type system, reasonable ownership model (slices and co), modular programming are worth much more than “safety”.
One small point I disagree with is characterizing using iteration to avoid bounds checks as "wrestling with your environment". At least for most developers, iterating instead of writing for loops by hand is the more natural approach, and I really like that Rust makes the way people WANT to write code the fastest path. Contrast with C# or Javascript where using iterators has performance overhead. So you have to ask yourself (in some domains) if the iterator is worth the overhead. In Rust you just use the iterator any time you can!

However I can see how people coming from C might consider the for loop the more natural approach.

I saw a benchmark that indicated that the iterator approach was actually even faster than the loop.
C# JIT can remove it, specially if PGO is enabled.
Speaking by example:

If you have one team of 10 people write a browser engine in C++ and another team of 10 people write the same browser engine in safe Rust (or as much safe rust as you can get away with), over a 5 year timespan you'll discover fewer UAF bugs in the Rust-written engine than the C++ one.

This is the value prop for any company deciding to use Rust. Obviously every language comes with tradeoffs, but this is concretely what people mean when they throw around the word "safety".

The author is also totally correct in pointing out how easy it is to include unsafe Rust in your code by linking unsafe crates. I think this should definitely be an area of discussion and awareness-raising on the part of developers.

> I think this should definitely be an area of discussion and awareness-raising on the part of developers.

It is. There is an unofficial `cargo geiger` tool that will alert you to these issues.

> If you have one team of 10 people write a browser engine in C++ and another team of 10 people write the same browser engine in safe Rust

Has it ever been shown that it’s possible to write a full browser engine in Rust? I believe for C++ it has been proven multiple times. If I am not mistaken, Servo hasn’t been finished in 10 years.

> Servo hasn’t been finished in 10 years.

Mozilla laid off all their servo developers in 2020

> Has it ever been shown that it’s possible to write a full browser engine in Rust?

Why wouldn't it be possible?

> Mozilla laid off all their servo developers in 2020

Yeah, I know, that’s sad.

> Why wouldn't it be possible?

I don’t know if it’s possible in reality or not, but if I have to, I can imagine some reasons (I’m making them up): maybe it takes too long to write proper safe Rust, or maybe developers get stuck bikeshedding over use of language features, or maybe the language’s learning curve is too steep, or maybe compilation is too long for fast dev iterations, or maybe developers who like Rust don’t like large codebases, or maybe Rust does not provide any tangible benefits over already existing code, or any combination of reasons.

Of course, you can write any program in any general-purpose language, just not everything is practical to be ever made. Like, I doubt people will make a full browser engine in Python, although it’s possible in theory.

> I can imagine some reasons (I’m making them up): ...

All your listed reasons apply equally (or even more strongly) to C++.

My point is, these reasons obviously didn’t hinder a possibility of making a full browser engine in C++ multiple independent times. But for Rust — they might be too big of an obstacle to make one. (Original discussion was about comparing quality of browser engines written in C++ and in Rust)
Keep in mind Rust wasn't even 1.0 until 2015, so servo was being developed in tandem with that, from 2015 to 2020 they integrated stylo from servo to firefox, and a few other components if memory serves.

So no, I guess they didn't bring an entire re-write to market in that time, but I don't think you can attribute any of those failings to language choice.

The advantage is actually pretty simple and I think this article overcomplicates it.

The Rust community considers safety violations to be the language's fault not the implementer’s fault. In C++ if you violate the language spec then you’re and idiot who just blew their foot off. In Rust the people responsible for the project take it upon themselves to make sure that nobody blows their foot off. If you happen to cause UB in safe code, the community says “oops yeah we messed up how do we fix that”. This is a huge difference and the article alludes to it but I don't think the author states it clearly enough.

Rust’s “hole problem” is that it forces developers to write safe code (conform to the language spec) up front which ultimately saves time and money. Developers are the audience and they want the best tools. Users want a hole (often as a means to an end, sure) and don’t care how it gets there; developers who make holes all day want the hole in the wall and not in their foot as frequently as possible.

This is it right here, a similar analogy this brought up was car manufacturers of old making an excuse that fatalities were the idiot drivers fault and not because of the inherent lack of safety features of the vehicle. It's too damn easy to make the wrong assumption in C & C++ and spend a painful amount of time debugging.

In my experience the added safety guarantees have made me more comfortable in "going faster" and back to vehicular terms the choice is still there to not fasten the seatbelt and go `unsafe`.

(comment deleted)
For the record, the author is the lead of the Rust compiler team.
Which we all appreciate. It doesn't mean the essay didn't turn out less articulate than it could be. It’s fair to critique writing regardless of the author’s credentials. The “hole” analogy is interesting but doesn't really serve to land a clear and coherent point as used by the author in my opinion.
That's well and good for safe Rust, but unsafe Rust is hard as hell to audit because nobody _really_ knows what the rules are. We're kind of still figuring out how to write unsafe Rust safely. Have a look at the "too many linked lists" book, which turns out to have had a fundamental error in it for years.

I think miri is a part of the answer to this, but it is not perfect. At the end of the day, you need unsafe at some level to do anything useful, and we need more explicit rules about how to do it properly.

It should be at least no harder than modern C, where any undefined behavior is a license for the optimizer to outright ignore the code you actually wrote. The main practical difficulty stems from the fact that Safe Rust rules are fully in effect even in an unsafe block, so you need to assess where references can be used instead of general pointers etc.
> The end value provided by Rust to its developers (and thus to their customers and employers) is less time arguing linguistic minutia and less time wrestling with a managed language environment, and more time focused on what actually matters to each of those developers (be it business logic, or family time).

Hm, interesting that this boils down to a wholly unsupported claim.

Part of it isn't even coherent to me. In my experience arguing linguistic minutia has nothing to do with programming languages (or any specific domain) and everything to do with personalities and social interactions.

As for spending less time wrestling with the language environment, I suppose that very well may be true. But it may very well not be true. Here it's an assertion without anything backing it up. It certainly seems possible to me that another safe language (e.g., Javascript) may win in this area.

The purpose of Rust is to provide a home for programmers who want to nurture a professional reputation for rigor but don't want to work in a boomer language
Smh why are y'all so salty I'm just speaking facts. I'm not even saying it's a bad thing
Modula-2, Ada and Object Pascal are quite nice boomer languages.
This is nonsense. In this context, safety is a term whose meaning is implied by Rust's design, i.e. it refers to code that's not unsafe.

This doesn't translate to much of anything in the world outside of Rust, and it boggles my mind that so many HN comments use it as a mere buzz word, thus devaluing it.

> People don’t want to buy a quarter-inch drill, they want a quarter-inch hole.

Never heard that one before, will remember! Any more such phrases?