Bounding a generic type on Drop
is essentially useless, to the point there's even a default warn lint against it:
warning: bounds on `T: Drop` are most likely incorrect, consider instead using `std::mem::needs_drop` to detect whether a type can be trivially dropped
--> src/lib.rs:1:13
|
1 | pub fn f<T: Drop>(_: T) {}
| ^^^^
|
= note: `#[warn(drop_bounds)]` on by default
A trait bound on Drop
requires that an explicit impl
of Drop
for the type is present. That this is writable is actually quite awkward for API stability as well â generally people want to consider replacing a Drop
implementation with drop glue that accomplishes the same cleanup to be a compatible change, but explicit bounds on Drop
mean that removing an impl is API breaking, and it doesn't fall under any category of allowed minor name resolution breakage.
On the other hand, an empty trait that is blanket implemented for all types (e.g. Destruct
) can actually be useful in some cases. Potential applications include:
dyn Destruct
as a maximally erased trait object where you have the vtable entries fordrop_in_place
,size_of_val
, andalign_of_val
but nothing else. Like usingdyn Any
for when you want to hold ownership of something but don't need the ability to downcast and/or want to avoidAny
's'static
requirement.~const Destruct
for expressing~const
bounds on drop glue.- As part of an unbound hierarchy[1] where a bound on
Destruct
removes the defaultSized
bound and only provides the ability todrop_in_place
.
I'd like to propose that we just forbid writing trait bounds on Drop
over an edition boundary with the hope of eventually making Drop
as a trait bound actually mean "can be dropped." Doing this would have the added benefit of making !Drop
actually mean something closer to linear types like that syntax gets informally used instead of "doesn't have a Drop
impl but could still have nontrivial drop glue."
The only thing that really suffers from such a change IMHO is that Drop
and Copy
(the trait bounds) aren't mutually exclusive anymore. What people actually mean when they say they're mutually exclusive still holds â Copy
and nontrivial drop glue are still mutually exclusive â but it does become possible to have types that are Copy + Destruct
.
The "less than
Sized
" capabilities/traits:Pointee
: can be the target of a pointer, can be by-value function parameter (potentially unsized)Destruct
: canptr::drop_in_place
DynAligned
: canmem::align_of_val
(may require reading from the value)DynSized
: canmem::size_of_val
(may require reading from the value)MetaAligned
: can determine required alignment from just wide pointer metadata, can be a dynamically sized struct tailMetaSized
: can determine size from just wide pointer metadataAligned
: canmem::align_of
, canoffset_of!
to a field of this typeSized
: canmem::size_of
, canoffset_of!
over a field of this typeRelocate
: can be trivially relocated to different addresses by justptr::copy
(while unpinned)- I feel like I've definitely missed some