I had a small realization (that may have been obvious to others here): The type-definition defines the Interior type, while implementing Drop creates an aliasing, zero-overhead, decorator of the Interior type. In other words, if we removed the “aliasing” function from Drop, we’d get something like the following:
struct DropType<T>(T);
struct Foo;
impl Drop for DropType<Foo> {
fn drop(self: &mut Foo) {
}
}
let x = Foo; // equivalent to `forget_outer(Foo)`
let x = DropType(Foo); // equivalent to current `Foo` construction.
Obviously that isn’t something we’d want to read or write in normal Rust code, the aliasing is very important for ergonomics and safety. But if we consider implementing Drop to define an aliasing decorator for the Internal type, the following sorts of things become possible (again, not code we’d actually write, just trying to demonstrate the idea):
struct DropValueType<T>(T);
trait DropValue<T> {
fn drop_value(self);
}
impl<T: DropMut> DropValue for DropValueType<T> {
#[inline]
fn drop_value(self) {
self.0.drop();
forget(self);
}
}
struct DropMoveType<T>(T);
trait DropMove<T> {
fn drop_move(&move self);
}
impl<T: DropValue> DropMove for DropMoveType<T> {
#[inline]
fn drop_move(&move self) {
self.0.drop_value();
forget(self);
}
}
With aliasing, it’d be considered that implemeting Drop for a type creates an aliasing Drop decorator, which then gets decorated by an aliasing DropValue type, which then gets decorated by an aliasing DropMove type. And now the drop-glue insertion only needs to consider the DropMove case - the rest is handled by the generic implementation of drop_move forwarding to drop_value, and drop_value forwarding to drop. I think this presentation shows that composability is handled just fine if multiple drop-traits are eventually supported… Using multiple drop-traits will also avoid code-churn for a large body of existing code, allow forward-compatibility, and allow drop-by-value optimization as well as immovable types (if and when they’re added).
That said, even though I don’t think there’s a forward-compatibility problem, I still think current Drop should be removed in favor of @eddyb’s Drop, if that can be made to fit within the project’s release time-line. Current Drop is strictly worse, and it’d be a shame to keep it forever. If immovable types are added in the future, they can be supported with a new DropMove trait, and that could be implemented using the mechanism I’ve described here.