3 ms·
Reordering destructors is not safe in C++, as it's fairly common to rely on objects being destroyed in reverse order and doing stuff like A a; B b(&a); In
by im3w1l 2mo ago
Reordering destructors is not safe in C++, as it's fairly common to rely on objects being destroyed in reverse order and doing stuff like
A a;
B b(&a);
In rust the borrow checker would guard against reordering such things, but a caveat is that there might be unsafe code relying on drop-order which the borrow checker would be oblivious to. There could also potentially be objects representing external resources like a temp file where dropping them out of order leads to issues.
- tialaramex 2mo agoThat Rust was in fact always unsound if it would cause problems to core::mem::drop(a); and the `become` call just drops things so it's the same. Safe-but-undesirable outcomes are acceptable. For example maybe our tail call ends up reverting a database transaction and we wish it were otherwise. But if the code did compile but wasn't memory safe as a result of this new drop then it was always unsound and shouldn't have existed. Just as the guts of some STL classes are very complicated in order to deliver the promised exception safety promises, the guts of unsafe Rust code are often tricky for similar reasons, you are mandated to deliver safety, it's not up to you to say "That's stupid, don't do that" either ensure it won't compile or safely cope.
- steveklabnik 2mo ago> In rust the borrow checker would guard against reordering such things It doesn't even get that far: Rust guarantees that things drop in reverse order of declaration, full stop. One interesting wrinkle here: for struct members, Rust does the opposite of what C++ does. We debated changing it to match, but > there might be unsafe code relying on drop-order which the borrow checker would be oblivious to. There was no super real compelling argument to choose one direction over the other in the abstract, and "be the same as C++" was not considered important enough to risk breaking unsafe code that relied on the (what was at the time) implementation defined behavior.
- tialaramex 2mo ago> It doesn't even get that far: Rust guarantees that things drop in reverse order of declaration, full stop. The drops happen (if implemented) in the same order, but in a different place, half the point of become is to put any needed drops first before the call, as otherwise it's not in tail position and we can't do the optimisation. So the borrowck can become involved if our become foo(bar, &baz) borrows baz but baz's type impl Drop - the diagnostics aren't great today, but then the feature isn't finished so it's not a priority.
- steveklabnik 2mo agoI was talking about regular old today's Rust, not the specifics about become.