(This kind of toes the line between irlo and urlo, as well as between the libs and language categories.)
Is it even theoretically possible to have a coherent language extension that allows a type to conditionally implement both Drop and Copy (in a disjoint manner, of course)?
My motivating example is `erasable::Thin|. It's a type roughly formulated as
struct Thin<Ptr: CanBeErased> {
ptr: ErasedPtr,
phantom<Ptr>,
}
(ErasedPtr is just ptr::NonNull<VoldemortZST>.) And, ideally, I'd want to support
impl<Ptr: CanBeErased> Copy for Thin<Ptr>
where
Ptr: Copy,
{}
impl<Ptr: CanBeErased> Drop for Thin<Ptr>
where
Ptr: !Copy,
{
fn drop(&mut self) {
let ptr: Ptr = Ptr::unerase(self.ptr);
drop(ptr);
}
}
This obviously isn't possible with current Rust, for multiple reasons:
- Drop cannot be bounded any differently than on the base structure (Drop impl must be universal).
- Negative bounds cannot be expressed (!Copy).
- Drop and Copy are mutually exclusive traits. (At least for a given instantiation of a type. As Drop is universal, we don't know whether a conditional Drop could share space with
Copysoundly.) - Coherence checker doesn't like having to prove disjointness of impls.
So my actual question here is: is it feasible for some future version of Rust to support this code (or something equivalent)?
I remain unconvinced as of posting this. While this is a "simple" case due to "obvious" disjointness (Trait and !Trait, there are a number of remaining flaws I'm worried about:
-
Dropis special, and very important to soundness and coherence of the Rust safety model. I knowDropimpls used to not require being universal (pre-1.0) but were given that requirement to make them easier for the compiler to reason about. - I'm pretty sure that we decided we'd ideally like
!Traitmean "explicitly promised to not implementTrait", either by explicitimpl !Traitor otherwise coherently prohibited from implementing the trait (maybe?). That way implementing a trait you didn't before still can't be a breaking change. (Thus neither impls would cover types which didn't implCopynorDrop, but might have (implementation detail)Dropglue.)
So I think it'll always be impossible to express Thin in a way that both inherits Copy and drop glue from its wrapped type in Rust, forever. I'd love to be proven wrong, though, even if I never see it available in rustc.