4 ms·
> This proposal and Rust's guarantees are different. A little different, but only in the sense of being, for the moment, less ambitious (than Rust) about the c
by duneroadrunner 8y ago
> This proposal and Rust's guarantees are different.
A little different, but only in the sense of being, for the moment, less ambitious (than Rust) about the completeness of the checker's implementation. But I think it substantially demonstrates a straightforward path to achieving the same level of memory safety in C++ as Rust.
> For example:
> > We do not attempt to address all aliasing cases
It seems to me that a main principle behind the design of the Rust language was to eliminate the aliasing issue, by imposing the "mutable references are exclusive" restriction, as a prerequisite to addressing the memory safety issue. And there was an implication (and sometimes more than that) that as long as C++ can't address the aliasing issue it can't address the memory safety issue (like Rust can).
I think the key thing that the lifetime checker demonstrates is that this premise is not (quite) right. You don't need to completely eliminate the aliasing issue to achieve (efficient) memory safety, you just need to address it "enough". And that can be done for C++.
Now, whether the complete elimination of the aliasing issue is, apart from the memory safety implications, a virtue that's worth the (flexibility) cost of the "mutable references are exclusive" restriction, is as far as I'm aware, still a matter of opinion. (Given the existence of the RefCell wrapper in Rust, and the ease (if not elegance) of implementing an "anti-RefCell" wrapper in C++, I'm guessing it's mostly a wash.)
> > or make concurrency safety guarantees. Programmers are still responsible for eliminating race conditions.
Data races are a separate issue, but relative to the (single-threaded) memory safety issue, I think there'd be less controversy that it can be addressed in C++ in vaguely similar fashion to Rust. [1]
But both in the case of Rust and the C++ lifetime checker, I don't think that the cost of the imposed (compile-time) restrictions in terms of code/algorithmic flexibility is being adequately acknowledged. For example, say you have a list (or whatever container) of references to (pre-)existing objects. In both cases, the restrictions require that all the objects must (be known to) outlive the list container even if there is a reference to them in the list for only a short time [2]. Imo this is an impractical restriction. In C++, you could use run-time checked pointers[3][4] to alleviate the restriction without sacrificing memory safety [5]. It's not immediately obvious to me that Rust couldn't have such a run-time checked reference as well. But others would be more qualified to make that assessment.
[1] shameless plug: https://github.com/duneroadrunner/SaferCPlusPlus#multithreading https://github.com/duneroadrunner/SaferCPlusPlus#multithread...
[2] https://github.com/duneroadrunner/misc/blob/master/201/8/Jul/implications%20of%20the%20lifetime%20checker%20restrictions.md#snippet-4 https://github.com/duneroadrunner/misc/blob/master/201/8/Jul...
[3] https://github.com/duneroadrunner/SaferCPlusPlus#registered-pointers https://github.com/duneroadrunner/SaferCPlusPlus#registered-...
[4] https://github.com/duneroadrunner/SaferCPlusPlus#norad-pointers https://github.com/duneroadrunner/SaferCPlusPlus#norad-point...
[5] https://github.com/duneroadrunner/misc/blob/master/201/8/Jul/implications1.cpp#L92 https://github.com/duneroadrunner/misc/blob/master/201/8/Jul...
- steveklabnik 8y ago> I think it substantially demonstrates a straightforward path to achieving the same level of memory safety in C++ as Rust. What path is that? It's not clear to me how this is possible without breaking backwards compatibility. This statement is directly at odds with > You don't need to completely eliminate the aliasing issue to achieve (efficient) memory safety, you just need to address it "enough" Safe Rust isn't "enough" safe, it is 100% (proofs pending, of course) safe. A "safe enough" system is not equivalent. Maybe if you mean that the existence of Unsafe Rust means that it's "enough", well fair. I still think it's substantially different; this proposal doesn't even get to being 100% safe. That said, as I said above, I very much welcome any sort of incremental improvement here.
- deleted 8y ago[deleted]
- duneroadrunner 8y ago> It's not clear to me how this is possible without breaking backwards compatibility. What do you mean? Presumably most existing sizable codebases will not satisfy the requirements of the (eventual completed) lifetime checker, even if the code is actually safe. > > You don't need to completely eliminate the aliasing issue to achieve (efficient) memory safety, you just need to address it "enough" > Safe Rust isn't "enough" safe, it is 100% (proofs pending, of course) safe. A "safe enough" system is not equivalent. I'm asserting (perhaps mistakenly) that you don't need to address the aliasing issue as completely as (Safe) Rust does in order to achieve the same memory safety that (Safe) Rust does. Or maybe "completely" is not exactly the right word. I'm saying that the universal imposition of the "mutable references are exclusive" restriction is not a necessary prerequisite to (fully) achieving the same type of ("zero overhead") memory safety that (Safe) Rust does. I'm not that familiar with Rust, but for example, if you have a reference to an element in a dynamic container, like a vector, (Safe) Rust ensures that that element is not prematurely deallocated by ensuring that there is no simultaneously existing mutable reference to the container. I.e. the container is immutable while an (immutable) reference to one of its elements exists. Right? (I mean, assuming you didn't "split" it first.) And if the reference to the element is a mutable reference, then the container cannot be referenced at all, right? From a memory safety perspective, this is overkill. The container does not have to be immutable (or inaccessible) while a reference to an element exists, only its structure needs to be immutable. The C++ lifetime checker imposes this lesser restriction. And for simple objects that do not have dynamic structure (or any indirect references), then the "mutable references are exclusive" restriction provides no memory safety benefit at all, right? As I said, even this lesser restriction will presumably break most existing C++ codebases, and you could (I think legitimately) argue that that makes this new "Safe" C++ a substantially different language than traditional C++. But the fact that the restrictions are much less severe than Rust's means that a lot fewer code modifications will be required than if a Rust-style universal "mutable references are exclusive" restriction had been adopted. Am I making sense here? Maybe I'm mistaken and these "lesser" restrictions are somehow inadequate, but I don't see it.