Prompted by discussion in this thread.
There’s probably some problem that I’m missing that makes this not work, but:
Redefine Drop to be
trait Drop: !Copy {
fn drop(self);
}
(Compatibility with current impls is provided with a magic legacy_drop(&mut self).)
The magic of this definition is that you may move out of self even though Self: Drop, and that Drop is not called on self at the end of scope. (It’s still called on any members that aren’t moved.)
We no longer require the magic that you can’t refer to this fn directly.
Calling any function that takes Self is handled by the unconditional_recursion lint. (As it would unconditionally recurse back into Drop::drop.)
Pre-1.0 issue about by-value drop.
I think this trait definition, modulo supporting current trait impls, is less magic than the current. (Though I accept if changing this definition like this is undesirable or impossible.)
Current Drop:
- Cannot refer to
Drop::dropdirectly - Cannot move out of
Droptypes- Semantically moving out of
selfinDrop::droprequiresunsafeand wrapping members inmem::ManuallyDrop
- Semantically moving out of
- Calls to drop glue emitted at the end of every block that has types by-value
This Drop:
- Support for two ways of implementing the trait
- Can move out of
Droptypes inDrop::drop(but not elsewhere) - Drop glue in
Drop::dropskips coveringself, other by-value scopes emit full drop glue -
unconditional_recursionlint has to learn aboutdroprecursion
(Implementation note: this drop glue behavior can be implemented by handling drop glue for Self as if it were not Drop. Rather than the recursion lint, you could also consider Self to be a distinct type here only, so you cannot recurse (but also cannot mem::forget).)
The other proposal in the linked topic was to have a Drop version that required pattern matching self in the drop fn declaration. This seems like more magic than this formulation, but would also work.
Both ideas could also be applied to using a new DropMove type instead, and having magic interop instead of magic translation.