4 ms·
TL;DR: YOU MUST NOT (and as I haven't yet time to read the article I'm not sure if they convey that correctly) But for various (complicated) reasons Drop isn
by dathinab 2y ago
TL;DR: YOU MUST NOT
(and as I haven't yet time to read the article I'm not sure if they convey that correctly)
But for various (complicated) reasons Drop isn't guaranteed to run on a "safety" level. That means that means whatever you do you must not rely on Drop for safety.
Through what you can do is rely on it for _correctness_, leading to safe but not very correct outcomes if it's not uphold.
What that means is that while you can (and should) use drop for cleanup patterns with patterns like drop guards, but you need to make sure that if drop isn't run it's still safe, i.e. sound.
It's totally fine to abort the process if a drop which _really_ needed to be run isn't run.
One example from `std` would be `vec::Drain` which if dropped leaks all elements of the `Vec` (not just the drained ones) but is safe i.e. sound to leak (also the mem allocation of the vec itself is not leaked just any allocation from elements in the vector).
On exception is if the drop guard itself is part of a unsound block or similar, i.e. if you can limit the scope of unsafe code enough to place the "drop-must" run part into a unsafe contract. E.g. you create drop guard at the beginning of a (non-async) unsafe block and can guarantee as part of the contract for that unsafe block that it's run at the end of it. This is commonly used in compact unsafe code blocks where in go you would use defer.
- wizzwizz4 2y agoThis is exactly the example that the article uses.
- dathinab 2y agoI know, that was intentional. It doesn't change that you _must not_ use Drop for safety. You only can use it for cleanup, and that can involve unsafe code and that can make things easier, but you can't rely on drop running for anything safety i.e. soundness related. And the article fails to highlight this problem but IMHO you really have to highlight it every time you speak about safety+drop, as its one of the biggest pitfalls of current rust and not doing so is irresponsible. There had been too much unsound code due to people overlooking that drop isn't guaranteed to run. Like to quote: > What about after you finish with the draining iterator, though? How does Rust guarantee that part of the contract? > This is where it gets interesting. > When the iterator is dropped — either because you hit the end of a for loop over it or because you drop it after iterating over some subset of elements — the Drain type’s implementation of the Drop trait takes over. That means that impl Drop for Drain is responsible for making sure that Drain is sound. And that is _wrong_ the Drop impl _must not_ be responsible for making sure Drain is Sound. The `drain` function call does so by setting len==0, i.e. making the vector forget about all it's content, i.e. semantically moves out all of it's elements. The Drop impl. semantically just moves the parts it didn't drain back into the Vec. I.e. it's isn't responsible for soundness but for not leaking the non drained elements.