Live data from Hacker News

Rusty.hpp: A Borrow Checker and Memory Ownership System for C++20

github.com

121–130 of 174 posts

Re: Rusty.hpp: A Borrow Checker and Memory Ownership System for C++20

#121

Earlier quoted context omitted.

I'm pretty sure you could embed a language with lifetimes in a dsl built with c++ templates. You wouldn't want to use it beyond toy programs though.

Maybe, but nobody has demonstrated that it's actually possible. And even then, toys are fun, but still, at the end of the day, not good enough.

Of course, it would be completely impractical. Nobody has demonstrated it because they were interested in a practical solution.

Re: Rusty.hpp: A Borrow Checker and Memory Ownership System for C++20

#122
post #118
post #104

Earlier quoted context omitted.

Rust `Box` = C++ `std::unique_ptr`, both have the same ABI (just pointers) Rust `Arc` = C++ `std::shared_ptr` Rust `Rc` = C++ `std::shared_ptr` but using a simple integer instead of an atomic so it is not thread safe `Arc` and `Rc` do not allow you to mutate their contents directly so instead you should use "interior mutability" using something like a `Mutex` (thread-safe) or `RefCell` (not thread-safe), which have r…

You say: > Rust `Arc` = C++ `std::shared_ptr` GP says: > Rust requires shared pointers (Arc) to also explicitly implement some sort of Mutex-equivalent runtime safety check in order to mutate the data. Which is it? > An example of a big C++ codebase using something similar is Chromium ... Chromium's smart pointers are similar to their standard counterparts -- no mutexes for write access to pointed data. Also, tangent…

Both are true, Rust just has more restrictions. It’s not completely equivalent, but you can think of `Arc` as `std::shared_ptr` as in if you use `unsafe` or `const_cast` you can bypass mutability restrictions. Otherwise to mutate you need another abstraction doing `unsafe` things for you, such as `Mutex`.

I mentioned Chromium because they also differentiate between thread safe and non-thread safe shared pointers.

If anything, Rust shared pointers are more similar to C++ std pointers because in Chromium the reference count is inside the class, which is very handy because you can reconstruct a smart pointer from a raw pointer (like `this`), at the cost of needing `T` to extend `base::RefCounted`.

Re: Rusty.hpp: A Borrow Checker and Memory Ownership System for C++20

#123
post #77

Earlier quoted context omitted.

Although it's not as extensive as Rust's lifetime management, Nim manages to infer lifetimes without specific syntax, so is it really a syntax issue? As you say, though, C++ template magic definitely has its limits.

Nim has a garbage collector. That said, you're right on some level that it's truly semantics that matter, not syntax, but you need syntax to control the semantics.

Nim is stack allocated unless you specifically mark a type as a reference, and "does not use classical GC algorithms anymore but is based on destructors and move semantics": https://nim-lang.org/docs/destructors.html

Where Rust won't compile when a lifetime can't be determined, IIRC Nim's static analysis will make a copy (and tell you), so it's more as a performance optimisation than for correctness.

Regardless of the details and extent of the borrow checking, however, it shows that it's possible in principle to infer lifetimes without explicit annotation. So, perhaps C++ could support it.

As you say, it's the semantics of the syntax that matter. I'm not familiar with C++'s compiler internals though so it could be impractical.

Re: Rusty.hpp: A Borrow Checker and Memory Ownership System for C++20

#124

Earlier quoted context omitted.

Then I’m afraid I don’t know what your point is. Rust’s borrow-checker isn’t a replacement for shared/unique pointers in C++. It’s a replacement for raw pointers.

My point was that overhead is one common objection to C++'s shared/unique pointers - everything is a method call - but that could be mitigated by the compiler itself doing the type of raw-pointer lowering, when safe, that the get() method permits. From other replies in this thread is seems that Rust's borrow-checker addresses the high level issues of object ownership and thread safety - it's not just a replacement fo…

borrowck is a semantic check. So, it's not a replacement for some particular C++ feature per se, it's not a feature in the sense you mean at all, it's just that while C++ and Rust both have these same semantic rules in place, Rust checks them and C++ does not. When you as a programmer inevitably get something wrong and break the rules, in Rust your program won't compile, in C++ it just has some arbitrary misbehaviour, maybe you notice, maybe you don't, maybe it matters, maybe it seems benign... until 8:26 tomorrow morning when suddenly it blows up and makes your customer very angry.

In C++ the result of breaking semantic rules (not just those checked by the borrowck, most of the semantic rules in the language) is IFNDR - your program is Ill Formed, No Diagnostic Required - your entire program has no particular meaning, there is no explanation for what it does, shrug. In Rust it doesn't compile.

For people whose overriding mission is to get the code to compile, C++ is very attractive. Broken garbage? Meaningless nonsense? Not my problem it compiled so I went home. If you want to write software that works, that seems like you didn't do the hard part.

Re: Rusty.hpp: A Borrow Checker and Memory Ownership System for C++20

#125

Earlier quoted context omitted.

You can actually implement the C++ behavior, if you want: unsafe fn super_unwrap (x: Option ) -> T { match x { Some(val) => val, None => unreachable_unchecked!(), } } But defaults matter, and Rust certainly doesn’t make this kind of thing ergonomic (which is a correct decision on the Rust designers’ part).

Yeah, absolutely. My point is that Option itself doesn't give you this API and to make an unsafe version, you have to explicitly write it. Including UB in easy to misuse places is totally unnecessary and a footgun which really does cause issues in real code.

Yep, I agree completely. Just wanted to point out for completeness that rust can theoretically do the same thing as c++.

Re: Rusty.hpp: A Borrow Checker and Memory Ownership System for C++20

#126

Earlier quoted context omitted.

Then I’m afraid I don’t know what your point is. Rust’s borrow-checker isn’t a replacement for shared/unique pointers in C++. It’s a replacement for raw pointers.

My point was that overhead is one common objection to C++'s shared/unique pointers - everything is a method call - but that could be mitigated by the compiler itself doing the type of raw-pointer lowering, when safe, that the get() method permits. From other replies in this thread is seems that Rust's borrow-checker addresses the high level issues of object ownership and thread safety - it's not just a replacement fo…

The main overhead of using shared/unique ptr for everything where you could have used stack allocation is not the extra method call for get etc, it’s the extra heap allocation. Compilers can probably inline get, but they can’t change heap allocations to stack allocations in general.

Re: Rusty.hpp: A Borrow Checker and Memory Ownership System for C++20

#127
post #82

Earlier quoted context omitted.

The point is that Option in Rust doesn't have undefined behavior in any case, even if the values aren't known at compile time. Exhaustiveness is always checked at compile time, unlike C++ where operator* offers an escape hatch where nothing is checked in non-constexpr contexts. "Make everything constexpr" isn't a real solution to UB, in the same way that "make all functions pure" isn't a solution for managing side ef…

You can actually implement the C++ behavior, if you want: unsafe fn super_unwrap (x: Option ) -> T { match x { Some(val) => val, None => unreachable_unchecked!(), } } But defaults matter, and Rust certainly doesn’t make this kind of thing ergonomic (which is a correct decision on the Rust designers’ part).

You don't have to write this, it already exists as the (unsafe of course) method Option::unwrap_unchecked

Because all Rust's methods can be called as free functions, you can literally write Option::unwrap_unchecked for the same behaviour, or you can some_option.unwrap_unchecked() (in both cases you will need to be in unsafe context for this to be allowed and should write a SAFETY comment explaining why you're sure it's correct)

Re: Rusty.hpp: A Borrow Checker and Memory Ownership System for C++20

#128
post #122
post #118

Earlier quoted context omitted.

You say: > Rust `Arc` = C++ `std::shared_ptr` GP says: > Rust requires shared pointers (Arc) to also explicitly implement some sort of Mutex-equivalent runtime safety check in order to mutate the data. Which is it? > An example of a big C++ codebase using something similar is Chromium ... Chromium's smart pointers are similar to their standard counterparts -- no mutexes for write access to pointed data. Also, tangent…

Both are true, Rust just has more restrictions. It’s not completely equivalent, but you can think of `Arc ` as `std::shared_ptr ` as in if you use `unsafe` or `const_cast` you can bypass mutability restrictions. Otherwise to mutate you need another abstraction doing `unsafe` things for you, such as `Mutex`. I mentioned Chromium because they also differentiate between thread safe and non-thread safe shared pointers. I…

FWIW, in C++11, a class C can similarly cooperate to enable reconstructing a shared_ptr from a raw one by deriving from std::enable_shared_from_this.

Re: Rusty.hpp: A Borrow Checker and Memory Ownership System for C++20

#129
post #123

Earlier quoted context omitted.

Nim has a garbage collector. That said, you're right on some level that it's truly semantics that matter, not syntax, but you need syntax to control the semantics.

Nim is stack allocated unless you specifically mark a type as a reference, and "does not use classical GC algorithms anymore but is based on destructors and move semantics": https://nim-lang.org/docs/destructors.html Where Rust won't compile when a lifetime can't be determined, IIRC Nim's static analysis will make a copy (and tell you), so it's more as a performance optimisation than for correctness. Regardless of th…

> Where Rust won't compile when a lifetime can't be determined, IIRC Nim's static analysis will make a copy (and tell you), so it's more as a performance optimisation than for correctness.

Wait, how does that work? For example, take the following Rust function with insufficient lifetime specifiers:

    pub fn lt(x: &i32, y: &i32) -> &i32 {
        if x 
You're saying Nim will change one/all of those references to copies and will also emit warnings saying it did that?

Re: Rusty.hpp: A Borrow Checker and Memory Ownership System for C++20

#130

Earlier quoted context omitted.

You're describing what it would do in a sane world where WG21 cared about safety. In this world, as the document you've linked says: "The behavior is undefined if *this does not contain a value." The operators for such access are actually `noexcept` - the exception you're apparently relying on would be illegal.

Should’ve checked my own link instead of relying on memory — I might have some code to revisit on Monday. That’s insane, thanks for correcting me!

No problem, if I caused you to fix a bug before it happened that's great. Yes, I find that reading sources I'm about to cite is often eye-opening. Our memories are not as good as we think they are, and our condensed understanding of a complex situation may have ignored something which is now crucial.

Once in a while I go down a rabbit hole, but hey, it's not as though HN isn't a rabbit hole anyway.

Post reply on HN