Live data from Hacker News

Making C++ safe without borrow checking, reference counting, or tracing GC

verdagon.dev

191–200 of 226 posts

Re: Making C++ safe without borrow checking, reference counting, or tracing GC

#191
post #134
post #100

Earlier quoted context omitted.

Because something like slotmap has to use `unsafe` to get around the inadequacies of the borrow checker...

Author of slotmap here. There is absolutely no need for unsafe in slotmap. I chose to use unsafe (wrapped in a safe API) to reduce memory usage using intrusive linked freelists. If done using safe Rust this would involve `enum`s that would take up extra space.

Slotmap is one of my favorite crates, by the way. Thank you for putting it out there!

Re: Making C++ safe without borrow checking, reference counting, or tracing GC

#192
post #13

Earlier quoted context omitted.

To put matters into perspective, Rust reference implementations depend on C++ toolchains. Same applies to all major Ada, Java, .NET, Swift, Ocaml and Haskell implementations. And any GPGPU toolchain. Which kind of shows it isn't going anywhere and those planes have to be improved no matter what.

As an addendum, the same goes for many C toolchains. Anything requiring GCC 4.8 or later is depending on a C++ compiler. And projects like LLVM’s libc, Fuchsia’s Zircon kernel, the bareflank hypervisor, etc, demonstrate that C++ really can be used anywhere C is used. C++ is the new C in the sense that it’s the language everything else is built on and I expect it will be even more difficult to displace than C. For ins…

> C++ really can be used anywhere C is used.

Kind of what I have been preaching since 1993, as I adopted C++ into my toolbox, and had some fun on Usenet on C vs C++ flamewars.

It was with some vindication that I celebrated when all major C compilers eventually transitioned to C++.

Re: Making C++ safe without borrow checking, reference counting, or tracing GC

#193
post #90

Earlier quoted context omitted.

Rust in Firefox is a very tiny portion of it and now they are using some WASM sandbox tricks, because they aren't going to rewrite everything in Rust, given the effort. Chrome only now started to consider to allow adding Rust, and it is baby steps, not coming close to V8, graphics engine and such.

"very tiny portion" that's a gross misrepresentation. Rust sits at ~10% and C++ at ~27% https://4e6.github.io/firefox-lang-stats/ .

Since when is 10% big?

Re: Making C++ safe without borrow checking, reference counting, or tracing GC

#194
post #157

Earlier quoted context omitted.

> Obviously the standard library uses some "unsafe" as well, for instance. Most beautifully, MaybeUninit ::assume_init() -> T This unsafe Rust method says "I promise that I actually did initialize this MaybeUninit , so give me the T". In terms of the resulting program the machine is not going to do any work whatsoever, a MaybeUninit and a T are the same size, they're in the same place, your CPU doesn't care that this…

Exactly. People miss this all the time when they write off Rust for "needing unsafe to do real programming" or whatever uninformed criticism they're parroting (they've clearly never actually done this "real programming" in Rust). The whole point is to reduce the opportunity for unforced errors by marginalizing the cognitive load required for the programmer to ensure the program is correct. And a program with a few un…

> than a program that's littered with `void*` everywhere

Strawman argument. A properly written C++ program isn't littered with `void*` everywhere in the same way that a properly written Rust program isn't littered with `unsafe` everywhere. You build safe abstractions around the ugly low-level pointer handling, you just don't have a keyword for a clear delineation.

> People miss this all the time when they write off Rust for "needing unsafe to do real programming" or whatever uninformed criticism they're parroting

Hard-core Rust proponents also seem to miss this all the time. Because "you basically write the same unsafe code that you would write in C++ but you now have a keyword to mark it" just doesn't imply the same urgency for adopting the language than "you only need unsafe to implement a few primitives in the standard library" does, which always seems to be tacitly implied until called out, and then the critics are "misinformed."

Re: Making C++ safe without borrow checking, reference counting, or tracing GC

#195

Earlier quoted context omitted.

I think it’s generally accepted that writing code is nearly universally easier than reading code, in any language. That aside, getting a mechanical check on memory safety for the price of some extra language verbosity is obviously worth it IMO. By the same token, it is common to see criticisms of the complexity of templates in C++, but templates are the cornerstone of “Modern C++” and many libraries could not exist w…

> getting a mechanical check on memory safety for the price of some extra language verbosity is obviously worth it IMO But a GC'd language doesn't require the extra verbosity.

GC has little to do with it. The borrow checker as a developer tool has much more to do with preventing concurrency bugs and unexpected mutation than it does with memory management.

"As a developer tool" is doing some work in that sentence though. As a language implementation characteristic, the checker can help inform (or, more accurately, ensures that code is written in a way that informs) memory management decisions.

Re: Making C++ safe without borrow checking, reference counting, or tracing GC

#196

RIP all the modern languages that haven't made any improvements in memory management at all. There is so much low hanging fruit in programming language design and nobody is picking it up and instead everyone produces marginal improvements over existing languages.

> There is so much low hanging fruit in programming language design and nobody is picking it up (waves) Author here! I wrote this article about some improvements to C++, but I also made a whole programming language [0] using a lot of these weird techniques. So not quite nobody! Still, I can see why very few people do it. It's a massive undertaking. Even if one is fortunate enough to be able to spend the thousands of…

I saw how design dances around structs / methods / interfaces. What is so bad to have however limited form of OOP instead? Would look much cleaner from my point of view.

Re: Making C++ safe without borrow checking, reference counting, or tracing GC

#197
post #157

Earlier quoted context omitted.

Exactly. People miss this all the time when they write off Rust for "needing unsafe to do real programming" or whatever uninformed criticism they're parroting (they've clearly never actually done this "real programming" in Rust). The whole point is to reduce the opportunity for unforced errors by marginalizing the cognitive load required for the programmer to ensure the program is correct. And a program with a few un…

> than a program that's littered with `void*` everywhere Strawman argument. A properly written C++ program isn't littered with `void*` everywhere in the same way that a properly written Rust program isn't littered with `unsafe` everywhere. You build safe abstractions around the ugly low-level pointer handling, you just don't have a keyword for a clear delineation. > People miss this all the time when they write off R…

> You build safe abstractions around the ugly low-level pointer handling, you just don't have a keyword for a clear delineation.

The main difference is they are not really safe. It is trivial to accidentally invoke UB with incorrect use of "safe" abstractions in C++ like built-in containers or smart pointers. Keep a reference to a vector element, add a new item to the vector and it will sometimes blow up ;)

Re: Making C++ safe without borrow checking, reference counting, or tracing GC

#198
I want to note couple of things from POV of C++ gamedev to safety/compiler people. This is completely IMHO and opinion is not of my employer and yadda yadda disclaimer. Feel free to disagree. It is posted here to learn where I am wrong about things.

If you don't like our arrays that means we don't like your type system. Arrays is the only efficient way to access existing RAM and until hardware changes do not start your work with 'do not use arrays'. And do not write into array elements without dev explicit consent just for safety.

If you want to lock access to whole array to single reference it does not scale with current hardware that has lots of CPUs and accelerators. Start thinking about array slices as things that can check safety. Start thinking about temporal aspects of multiple code blocks accessing slices into same array(s).

If your type system is not allowing iteration in 'broken' project state it does not scale with projects that involve multiple people working at same time. Yes one has to put some mitigations to stop 'nasal demons' from running wild in practice to be able to work. Just drop the idea of blocking people from work until it is fixed.

Re: Making C++ safe without borrow checking, reference counting, or tracing GC

#199
post #157

Earlier quoted context omitted.

Exactly. People miss this all the time when they write off Rust for "needing unsafe to do real programming" or whatever uninformed criticism they're parroting (they've clearly never actually done this "real programming" in Rust). The whole point is to reduce the opportunity for unforced errors by marginalizing the cognitive load required for the programmer to ensure the program is correct. And a program with a few un…

> than a program that's littered with `void*` everywhere Strawman argument. A properly written C++ program isn't littered with `void*` everywhere in the same way that a properly written Rust program isn't littered with `unsafe` everywhere. You build safe abstractions around the ugly low-level pointer handling, you just don't have a keyword for a clear delineation. > People miss this all the time when they write off R…

Firstly the delineation clarity is much more valuable than you seem to appreciate. A day one beginner in Rust can see that this stuff is roped off - so they know if they should call a grown-up - and everything which isn't roped off is safe for them. This also benefits an experienced developer when you're not at your best. Lets not write unsafe Rust today, we can do that when the air conditioning works, the coffee machine is fixed and there aren't contractors using power tools in the office.

I also think you very seriously underestimate how much equivalently unsafe C++ you write, and overestimate how much actual unsafe Rust is needed. Philosophically WG21 (the C++ committee) didn't like safe abstractions, so it doesn't provide them. To the point where the C++ slice type std::span is exactly like the safety proposal where it was originally suggested, except with all the safety explicitly ripped out. "We like this safety feature, except for the safety, get rid of that". I am not even kidding.

Most Rust programmers don't need to write any unsafe Rust. They can rely on Rust's promises, about aliasing, races, memory safety, performance characteristics, and they have no responsibility for delivering those promises, it's all done for them so long as they write safe Rust.

The other crucial element is culture. Culturally Rust wants safe abstractions, that applies to the standard library of course, but it also applies to third party code, you can expect other Rust programmers to think your library is crap if it has a method which is actually not safe to call without certain pre-conditions but isn't labelled "unsafe" -- because that's exactly what "unsafe" is for so you're not fulfilling your social contract.

Re: Making C++ safe without borrow checking, reference counting, or tracing GC

#200

Earlier quoted context omitted.

> than a program that's littered with `void*` everywhere Strawman argument. A properly written C++ program isn't littered with `void*` everywhere in the same way that a properly written Rust program isn't littered with `unsafe` everywhere. You build safe abstractions around the ugly low-level pointer handling, you just don't have a keyword for a clear delineation. > People miss this all the time when they write off R…

> You build safe abstractions around the ugly low-level pointer handling, you just don't have a keyword for a clear delineation. The main difference is they are not really safe. It is trivial to accidentally invoke UB with incorrect use of "safe" abstractions in C++ like built-in containers or smart pointers. Keep a reference to a vector element, add a new item to the vector and it will sometimes blow up ;)

I disagree that it is "trivial," at least in the example you stated. This take-reference-then-mutate is exactly the kind of usage that the borrow checker prevents. You have to avoid it systematically in both languages.

The built-in containers are also not the best examples of "safe" abstractions. You can build safer abstractions, and you can employ safer usage patterns of built-in vectors, at non-zero but marginal costs.

The honest view on C++ is that there is no such thing as "safe" in absolute terms, but you have a lot of tools to mitigate the unsafe nature of the core language.

The honest view on Rust is that the idea of categorically excluding memory safety errors didn't quite pan out, but we're nonetheless left with an improvement over C++.

Post reply on HN