macro_rules! drop_in_place {
( $var:ident $(,)? ) => { ... };
}Expand description
Safe API around MaybeDangling::drop_in_place(), which performs the mandatory
::core::mem::forget() on the given var.
Equivalent to doing drop::<MaybeDangling>($var), but for not moving the
given $var before doing so (important with, for instance, Pin stuff).
-
Using
MaybeDangling::drop_in_place()directly is so wildly dangerous that it is discouraged. -
Using
ManuallyDropalongsideManuallyDrop::drop()is significantly less dangerous w.r.t. double-dropping, but alas just as dangerous w.r.t. leaking when dealing with thePincontract for which a lack of drop in certain cases is just as unsound.
Remark: this macro requires the given $var binding to have been declared mutable.
ยงExample
Imagine, as a library author, wanting to offer the following kind of API:
pub use ::core;
pub use ::maybe_dangling;
macro_rules! my_droppable_pin {(
let mut $var:ident = pin!($value:expr);
) => (
let mut pinned_value = $crate::maybe_dangling::MaybeDangling::new($value);
macro_rules! drop_it {() => (
$crate::maybe_dangling::drop_in_place!(pinned_value);
)}
#[allow(unused_mut)]
let mut $var = unsafe {
$crate::core::pin::Pin::new_unchecked(&mut *pinned_value)
};
)}
fn main() {
use ::core::{marker::PhantomPinned, pin::*};
my_droppable_pin! {
let mut p = pin!(PhantomPinned);
}
let _: Pin<&mut PhantomPinned> = p.as_mut(); // properly pinned!
for i in 0.. {
if i == 5 {
drop_it!(); // drops the `PhantomPinned` in-place, abiding by the drop guarantee.
// stuff runs after `PhantomPinned` has been dropped, rather than before.
stuff();
break;
}
}
}