3 ms·
> 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 sat
by 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.
- steveklabnik 8y ago> 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. You need to address the aliasing, or address the mutability. They're two sides of the same coin. > only its structure I am not 100% sure what distinction you're making here, sorry. What's "the container" vs "its structure"? > From a memory safety perspective, this is overkill. Yes, in general, Rust takes a soundness-based approach. If you can't prove that it's safe, then it's not safe. This takes the other path, which is totally valid, mind you! But that means it will allow cases that are not safe. > 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? That's not right. You can have a data race to a plain old integer.
- duneroadrunner 8y ago> That's not right. You can have a data race to a plain old integer. Sure, if your language allows unprotected access to any object from any thread. Which, I guess traditional C++ essentially does, but presumably a "Safe" C++ would eventually have an "asynchronous sharing" checker that would require any shared objects to be appropriately "protected". > > only its structure > I am not 100% sure what distinction you're making here, sorry. What's "the container" vs "its structure"? For example: std::vector<int> vec1 {1, 2}; { const auto& cref1 = vec1.at(0); auto& ref2 = vec1.at(1); ref2 = 3; auto& ref1 = vec1.at(0); std::cout << cref1; ref1 = 4; // co-existing const and non-const references are permitted and memory safe here std::cout << vec1.size(); vec1.at(0) = 5; vec1.clear(); // <---- Rejected by the lifetime checker // because the clear() call mutates the structure. // Mutating the data contained in the vector is permitted though. std::cout << cref1; } > Yes, in general, Rust takes a soundness-based approach. If you can't prove that it's safe, then it's not safe. The approach is not that different. The lifetime checker applies (or will apply) basically the same sorts of restrictions that the Rust compiler does (and "break" backward compatibility in the process), but only when necessary to enforce memory safety. I mean, the way the lifetime checker works is that it basically keeps track, at compile-time, of the latest possible death-time of every reference and the earliest possible death-time of the target object (or potential target objects) that each reference points at, and complains anytime the former is later than the latter.