Live data from Hacker News

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

verdagon.dev

81–90 of 226 posts

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

#81
post #14

Earlier quoted context omitted.

I don't write Rust. But here is what you said and what the author said don't conflict with each other, and it has been on my mind for a while. People who write similar code, or work on things for decades usually don't really think through what "sketch out some code" looks like. They spend most of their time on refactoring things that has clear use-cases, but not well-defined API boundaries within the component, or be…

I really love parts of rust and kinda hate other parts. but this is what really ruins it for me. I want to play. I want to knock something together and work with it and see what kind of shape it is. rust demands that I cross every last t before I can run it at all. which is great if you already have a crystal notion of what you are building

> rust demands that I cross every last t before I can run it at all. which is great if you already have a crystal notion of what you are building

Maybe I'm a weirdo, but I don't find this to be the case for me.

When I'm knocking things together in Rust I use a ton of unwrap() and todo!() and panic!() so I can figure out what I'm really doing and what shape it needs to have.

And then when I have a design solidified, I can easily go in and finish the todo!() code, remove the panic!() and unwrap() and use proper error types, etc.

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

#82

Earlier quoted context omitted.

I really love parts of rust and kinda hate other parts. but this is what really ruins it for me. I want to play. I want to knock something together and work with it and see what kind of shape it is. rust demands that I cross every last t before I can run it at all. which is great if you already have a crystal notion of what you are building

> rust demands that I cross every last t before I can run it at all. It's worse than that IMO. Rust makes it very awkward/impractical to have cyclic data structures, which are necessary to write a lot of useful programs. The Rust fans will quickly jump in and tell you that if you need cycles, your program is wrong and you're just not a good enough programmer, but Maybe it's just that the Rust borrow checker is too li…

The basic model of Rust is to move use-after-free from a dynamic, runtime check to a static, compile-time check. But to keep the static checks from being Turing-complete, you need to prohibit arbitrary cycles while something like a tree (or other boundable recursion) is doable. So Rust not being able to check cyclic data structures isn't a "Rust currently can't do better" situation, it's a "Rust just can't do better" situation.

What Rust's intended solution for that is that you add in data structures that do the dynamic checking for you in those cases. But the Rust library doesn't provide anything here that's useful (RefCell is the closest alternative, and that's pretty close to a this-is-never-what-you-want datatype), which means your options are either to use integers, roll your own with unsafe, or try hard to rewrite your code to not use cycles (which is usually a euphemism for use integers anyways). The problem here, I think, is that there is a missing data structure helper that can sit in between integers and references, namely something akin to handles (with a corresponding allocator that allows concurrent creation/deletion of elements).

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

#83

> Borrow checking is incompatible with some useful patterns and optimizations (described later on), and its infectious constraints can have trouble coexisting with non-borrow-checked code. Not that this isn't true, but the rest of the article introduces a system with a superset of those limitations, gradually decreasing over time but never becoming a subset. In fact the pattern described in the article is a common pa…

I would really love a definitive answer on whether the borrow checker and rust’s rules do really limit optimizations and such. It seems like I see this opinion often and every time there are tons of people on both sides who seem sure they are correct. What are the limitations for optimization? Does unsafe rust really force those?

Difficult to answer.

However, what you can say is that the borrow-checker works like a straight-jacket for the programmer, making them less capable to focus on other things like performance issues, high-level data leaks (e.g. a map that is filled with values without removing them eventually), or high-level safety issues.

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

#84
post #83

Earlier quoted context omitted.

I would really love a definitive answer on whether the borrow checker and rust’s rules do really limit optimizations and such. It seems like I see this opinion often and every time there are tons of people on both sides who seem sure they are correct. What are the limitations for optimization? Does unsafe rust really force those?

Difficult to answer. However, what you can say is that the borrow-checker works like a straight-jacket for the programmer, making them less capable to focus on other things like performance issues, high-level data leaks (e.g. a map that is filled with values without removing them eventually), or high-level safety issues.

You can also say that the borrow checker works like a helpful editor, double checking your work, so that you can focus on the important details of performance issues, safety issues, and such, without needing to waste brain power on the low-level details.

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

#85

> Borrow checking is incompatible with some useful patterns and optimizations (described later on), and its infectious constraints can have trouble coexisting with non-borrow-checked code. Not that this isn't true, but the rest of the article introduces a system with a superset of those limitations, gradually decreasing over time but never becoming a subset. In fact the pattern described in the article is a common pa…

[deleted]

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

#86

Earlier quoted context omitted.

I agree these planes are important and deserve care. At the same time pretty much all suggestions on how to meaningfully improve the safety of those planes boil down to successor languages Cpp2, Carbon etc. or require some other complex manual rewrite of components of said plane. There is an argument to be made for having good out-of-the-box interoperability, however even in some of the most complex and important cod…

The second someone makes a successor language that seamlessly/directly interops with C++ _AND_ has the level of build/IDE tooling that C++/Rust have, I'm on board. The closest thing right now is Sean Baxter's "Circle" compiler in "Carbon" mode IMO: https://github.com/seanbaxter/circle/blob/master/new-circle/... Unfortunately, Circle is closed-source and there's no LSP or other tooling to make the authoring experience…

I also see Circle as the most promisor C++ wannabe, from all the contenders, and it being closed-source, once upon a time all major compilers were, so lets see.

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

#87

Earlier quoted context omitted.

> rust demands that I cross every last t before I can run it at all. It's worse than that IMO. Rust makes it very awkward/impractical to have cyclic data structures, which are necessary to write a lot of useful programs. The Rust fans will quickly jump in and tell you that if you need cycles, your program is wrong and you're just not a good enough programmer, but Maybe it's just that the Rust borrow checker is too li…

The basic model of Rust is to move use-after-free from a dynamic, runtime check to a static, compile-time check. But to keep the static checks from being Turing-complete, you need to prohibit arbitrary cycles while something like a tree (or other boundable recursion) is doable. So Rust not being able to check cyclic data structures isn't a "Rust currently can't do better" situation, it's a "Rust just can't do better"…

missing data structure helper -- didn't you already just name-check that though, since that's basically RefCell .. or if you're willing to roll the dice... UnsafeCell (aka "trust me I know what I'm doing")?

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

#88

> Borrow checking is incompatible with some useful patterns and optimizations (described later on), and its infectious constraints can have trouble coexisting with non-borrow-checked code. Not that this isn't true, but the rest of the article introduces a system with a superset of those limitations, gradually decreasing over time but never becoming a subset. In fact the pattern described in the article is a common pa…

> In fact the pattern described in the article is a common pattern in Rust and I make use of it all the time; the library for making use of it is `slotmap`.

Slotmap uses unsafe everywhere, it's a memory usage pattern not supported by the borrow checker. It's basically hand-implementing use-after-free and double-free checks, which is what the borrow checker is supposed to do. Is that really a common pattern in Rust?

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

#89

> Borrow checking is incompatible with some useful patterns and optimizations (described later on), and its infectious constraints can have trouble coexisting with non-borrow-checked code. Not that this isn't true, but the rest of the article introduces a system with a superset of those limitations, gradually decreasing over time but never becoming a subset. In fact the pattern described in the article is a common pa…

I would really love a definitive answer on whether the borrow checker and rust’s rules do really limit optimizations and such. It seems like I see this opinion often and every time there are tons of people on both sides who seem sure they are correct. What are the limitations for optimization? Does unsafe rust really force those?

I'd say it mostly applies to manual optimization, when we're restructuring our program.

If the situation calls for a B-tree, the borrow checker loves that. If the situation calls for some sort of intrusive or self-referential data structure (like in https://lwn.net/Articles/907876/), then you might have to retreat to a different data structure which could incur more bounds checking, hasher costs, or expansion costs.

It's probably not worth worrying about most the time, unless you're in a very performance-sensitive situation.

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

#90
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.

I agree these planes are important and deserve care. At the same time pretty much all suggestions on how to meaningfully improve the safety of those planes boil down to successor languages Cpp2, Carbon etc. or require some other complex manual rewrite of components of said plane. There is an argument to be made for having good out-of-the-box interoperability, however even in some of the most complex and important cod…

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.

Post reply on HN