pub trait PureTryDrop {
type Error: Into<Error>;
type FallbackTryDropStrategy: TryDropStrategy;
type TryDropStrategy: FallibleTryDropStrategy;
// Required methods
fn fallback_try_drop_strategy(&self) -> &Self::FallbackTryDropStrategy;
fn try_drop_strategy(&self) -> &Self::TryDropStrategy;
unsafe fn try_drop(&mut self) -> Result<(), Self::Error>;
// Provided method
fn adapt(self) -> DropAdapter<Self>
where Self: Sized { ... }
}Expand description
A trait for types which can be dropped, but which may fail to do so.
This is a pure version of try drop, meaning that the drop strategies have to be explicitly specified, which means it does not depend on a global try drop strategy.
§Gotchas
Implementing this trait is not enough to make it droppable. In order for the try drop strategy
to be run, you need to put your type in a DropAdapter.
An easier way to make your type droppable is to call PureTryDrop::adapt on it.
Required Associated Types§
Sourcetype FallbackTryDropStrategy: TryDropStrategy
type FallbackTryDropStrategy: TryDropStrategy
The type which will be used if the drop strategy fails.
Sourcetype TryDropStrategy: FallibleTryDropStrategy
type TryDropStrategy: FallibleTryDropStrategy
The type which will be used if dropping fails.
Required Methods§
Sourcefn fallback_try_drop_strategy(&self) -> &Self::FallbackTryDropStrategy
fn fallback_try_drop_strategy(&self) -> &Self::FallbackTryDropStrategy
Get a reference to the fallback try drop strategy.
Sourcefn try_drop_strategy(&self) -> &Self::TryDropStrategy
fn try_drop_strategy(&self) -> &Self::TryDropStrategy
Get a reference to the try drop strategy.
Sourceunsafe fn try_drop(&mut self) -> Result<(), Self::Error>
unsafe fn try_drop(&mut self) -> Result<(), Self::Error>
Execute the fallible destructor for this type. This function is unsafe because if this is
called outside of a Drop::drop context, once the scope of the object implementing trait
ends, this function will be called twice, potentially resulting in a double-free.
Use DropAdapter to ensure that the destructor is only called once.
§Safety
The caller must ensure that this function is called within a Drop::drop context.
Provided Methods§
Sourcefn adapt(self) -> DropAdapter<Self>where
Self: Sized,
fn adapt(self) -> DropAdapter<Self>where
Self: Sized,
Adapts this type to take advantage of the specified try drop strategies.
§Notes
If Self implements Copy, and you call this function, at first it seems like there
would be a soundness hole:
use try_drop::{Infallible, PureTryDrop, TryDrop};
#[derive(Copy, Clone)]
struct T(usize);
impl TryDrop for T {
type Error = Infallible;
unsafe fn try_drop(&mut self) -> Result<(), Self::Error> {
self.0 += 1;
println!("{}", self.0);
Ok(())
}
}
// this is valid code and does not result in a compilation error
let t = T.adapt().adapt();You’d think the output would be:
1
2However, it’s actually:
1
1This is because Self implicitly get copied.
I may or may not have spent a large amount of time trying to get rid of this “soundness hole”.