So, by passing self by value to the ::callback(), you're basically telling users "hey, BTW, don't forget to defer the drop to some workqueue if you think it's not atomic-safe". And how can users know that the thing they're about to drop can be dropped in atomic context? They basically have to audit the ::drop() of all the resources they embed in their type implementing FenceCb. Not only that, but they also have to design the thing so the deferral of this ::drop() doesn't allocate, because, obviously, allocating in atomic context is tricky/fallible. AFAIK, none of this can be spot at compile-time (I remember Gary/Danilo mentioning that we could teach the klint about some of these rules). This would leave us with runtime checks like might_sleep(), but most of the C putters (xxx_put(object)) don't have might_sleep() in the path where the decref doesn't lead to a refcnt=0 situation.
TLDR; Call this PTSD if you want, but this is the sort of bugs I struggled with on the C side, and I can predict that the exact same will happen in rust drivers if we expose the FenceCb as it is designed here and we don't have a way to check the soundness of the FenceCb implementations at compile time.
My guess would be that the existence of unsafe-traits is the admission of Rust that this just cannot be guaranteed by design.
If a driver cannot know whether this or that is safe to drop, then it would have to defer it's dropping. Or would there be cases where this also doesn't work?
Although I totally understand where Boris is coming from here, and I agree with him, the reality is that the current &mut self design doesn’t solve this. An unsafe trait could work as a pinky-promise by drivers, which is half-way there.
What we ideally would like to have is a bound though, something like:
T: !Drop
If I recall correctly there were people working to get support for that on Rust? I think there are two things here: !Trait, which is not supported except for !Sized IIRC, and having an auto trait that represents types that implement Drop, similar to Send and Sync.
In fact, ping the pin-init people here, i.e.: Benno, Gary, etc.
What is the magic behind “MustNotImplDrop”? Perhaps we could apply that here?
— Daniel