Live data from Hacker News

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

verdagon.dev

71–80 of 226 posts

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

#71
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

This is the nice thing about TypeScript—you can type want you want. As you iterate you can either ramp or down your type checking. This is outside the realm of memory management, of course.

And new to JS/TS land is the separation of pure data structures from resources. Something a sibling comment or brought up.

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

#72
post #8
post #7

Earlier quoted context omitted.

Ideally we would have -fsafe and [[unsafe]], but it will take years for something like that.

Presuming syntax for “unsafe” that gracefully degrades in non-aware compilers, why couldn’t a particular compiler start doing it right now, starting with a very trivial safety checker than can be iteratively improved upon once the framework is in place?

I feel like D has gone this route of incrementally adding features (like borrow checking) to the language that, in principle, improve safety.

I wonder if anyone here has more experience to know how well it has worked?

One massive advantage of Rust is that they started with borrow checking from the beginning. I think one thing that often gets understated in these discussions is how much it matters to have your entire ecosystem using a set of safe abstractions. This is a major drag for C++, and I suspect that even if the language went a route like D they'd still have gaping safety holes in practical, everyday usage.

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

#73
post #22

Earlier quoted context omitted.

So no need for LLVM and GCC, Great news! Where can we download it?

Assuming you are serious, there is https://github.com/bytecodealliance/wasmtime/tree/main/crane... which is written in Rust and is targeted to become the default debug backend in rustc. LLVM has accumulated a lot of optimizations contributed by various groups and people over more than a decade. It's hard to catch up to that by virtue of resource limits.

Is there a reason to replace LLVM? Are there still memory bugs that are popping up and causing issues?

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

#74

> 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?

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

#75
post #63

Methods such as these for C and C++ are interesting, and needed, but only solve a part of the problem. As others have noted before, they do little good because they're opt-in. I think there's a bit of nuance to that which needs to be explored though, as I think it's less a problem that the extra checks are opt in, and more a problem of how we use and categorize libraries. As long as we encourage dynamic and static li…

If you were starting a new project you could put lints in place to make these things enforced. But at some point you have all these lints and customizations in place, and you can't use old or 3rd party C++ code any more because of them, so you begin to ask, why not just use a new language where this stuff isn't pasted together with glue and bailing wire?

My point is really not about the code you write yourself, but the code you need to include in your project. Rare is the professional programmer that always gets to finish their project using only code they wrote themselves, and for many projects that's highly inadvisable (don't roll your own crypt unless you have a very good reason).

So, given that at times we will have to use external libraries, and given that even very safe languages often have escape hatches meaning you can't be sure the code of one language has more constraints than another, it would be great to have other indicators than the language it was written in that indicated what safety checks it uses.

If next year you're writing a new program in a language that hasn't even been invented as of now, and is viewed as safer than every language out today, what does that actually get you if one of your constraints is that you need to include and use openssl or one of a few forks for compatibility reasons? Wouldn't you rather be able to look at the available options and see that come opt into specific safety constraints, and have been good about not them circumventing them, and do so extremely easily? Network effects and existing known projects seem to have an inordinate amount of staying power, so we might as well deal with that as a fact.

The world is a messy place, but the more information we have the better our chances of making order out of it, even if temporarily.

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

#76

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…

I would never tell you that you are wrong to have cyclic data structures. But there are reasonable workarounds like using handles into an array to do it, which of course re-creates some of the same problems as pointers, but not the worst ones, and is often a positive for performance on modern hardware due to improved data locality.

Or you can use reference counted types and take a small performance hit.

Or use unsafe and git gud.

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

#77

> 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?

Without directly answering your question, it's worth noting that there are also additional optimizations made available by Rust that are not easily accessible in C/C++ (mostly around stronger guarantees the Rust compiler is able to make about aliasing).

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

#78

> 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?

The question is far too broad, and contextual. You're never going to get an answer to that question.

Sometimes, the rules add more optimization potential. (like how restrict technically exists in C but is on every (okay almost every) reference in Rust) Sometimes, the rules let you be more confident that a trickier and faster design will be maintainable over time, so even if it is possible without these rules, you may not be able to do that in practice. (Stylo)

Sometimes, they may result in slower things. Maybe while you could use Rust's type system to help you with a design, it's too tough for you, or simply not worth the effort, so you make a copy instead of using a reference. Maybe the compiler isn't fantastic at compiling away an abstraction, and you end up with slower code than you otherwise would.

And that's before you get into complexities like "I see Rc> all the time in Rust code" "that doesn't make sense, I never see that pattern in code".

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

#79

> 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?

There can be no answer. Research is ongoing, smart people are actively trying to make optimizer better, so even if I gave a 100% correct answer now (which would be pages long), a new commit 1 minute latter will change the rules. Sometimes someone discovers what we thought was safe isn't safe in some obscure case and so we are forced to no longer apply some optimization. sometimes optimization is a compromise and we decide that the using a couple extra CPU cycles is worth it because of some other gain (a CPU cycle is often impossible to measure in the real world as things like caches tend to dominate benchmarks, so you can make this comprise many times when suddenly the total adds up to something you can measure.).

The short answer for those who don't want details: it is unlikely you can measure a difference in real world code assuming good clean code with the right algorithm.

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

#80

Earlier quoted context omitted.

Assuming you are serious, there is https://github.com/bytecodealliance/wasmtime/tree/main/crane... which is written in Rust and is targeted to become the default debug backend in rustc. LLVM has accumulated a lot of optimizations contributed by various groups and people over more than a decade. It's hard to catch up to that by virtue of resource limits.

Is there a reason to replace LLVM? Are there still memory bugs that are popping up and causing issues?

https://github.com/bytecodealliance/wasmtime/blob/main/crane...
Post reply on HN