(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
Copy
soundly.) - 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:
-
Drop
is special, and very important to soundness and coherence of the Rust safety model. I knowDrop
impls 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
!Trait
mean "explicitly promised to not implementTrait
", either by explicitimpl !Trait
or 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 implCopy
norDrop
, but might have (implementation detail)Drop
glue.)
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.