I have a major use case for destructuring Drop types that is not met by this match #[avoid_drop]
proposal. In serde_json we have:
pub enum Value {
Null,
Bool(bool),
Number(Number),
String(String),
Array(Vec<Value>),
Object(Map<String, Value>),
}
If someone creates a deeply nested Value, its compiler-generated Drop will overflow the stack—serde-rs/json#440.
The correct fix would be to implement Drop for Value in a way that uses a loop and heap-allocated stack to drop the whole thing without recursion. I have code for this. The problem is:
-
We cannot implement Drop for Value because it breaks the ability to destructure Value, which is an extremely common and important use case that needs to be supported;
-
We cannot implement Drop for Vec<Value> because it overlaps Vec<T>'s impl;
-
We cannot implement Drop for serde_json::Map<String, Value> because implementations of Drop cannot apply to a specialized choice of type parameters;
-
We cannot implement Drop for serde_json::Map<K, V> because that requires a recursive call to V’s drop so wouldn’t solve the problem.
I believe the stack overflows are not possible to fix today nor with this proposal. Instead of (or in addition to) the match #[avoid_drop]
in this proposal I would need some attribute on Value or on its Drop impl that says the type is fine to destructure despite having a Drop impl.