I don't understand that part: the moment there is an impl Drop
on some type, that type (and any containing type!) ceases to feature "trivial drop" and now has drop glue, so it can't keep implementing TrivialDrop
/ NoDropGlue
.
While that impl !NoDropGlue
could be done for each and every case of impl Drop
by the compiler, this is a situation where the usual approach is to be generic over that last case, hence the negative_impl
s usage (that is, the whole thing can be implemented differently with special compiler / lang
support, but that's only used when the current abstractions fail to express that).
-
But, as I mentioned, the
negative_impl
approach does not work:unsafe auto trait NoDropGlue {} impl<T : Drop> !NoDropGlue for T {} fn impls_NoDropGlue<T : ?Sized>() where T : NoDropGlue, {} const _: () = { // ERROR: the trait bound `u8: NoDropGlue` is not satisfied let _ = impls_NoDropGlue::<u8>; };
So we need some form of language support to handle that part (I suspect that making the Drop
trait #[fundamental]
would suffice to appease the proof obligations, but that would be way too overkill and problematic).
This last point is interesting: if users get the power to have <T : NoDropGlue>
generics, this means that drop glue becomes a type-level observable part of the API of types, even for types having only private types! This means that adding drop glue to a type would be a breaking change, which means the std
lib, for instance, would have to add many preemptive dummy Drop
impls / drop glues so as to keep the option open.
From there, we observe we have, yet again, hit the common problem of auto-traits (vs., for instance, derive(Copy)
).
So I think that type-level observability of NoDropGlue
ought to be opt-in (we could see it as a weaker version of Copy
).
All in all, I realize the current design with a mem::needs_drop()
function is actually really good