drop_in_place

Macro drop_in_place 

Source
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 ManuallyDrop alongside ManuallyDrop::drop() is significantly less dangerous w.r.t. double-dropping, but alas just as dangerous w.r.t. leaking when dealing with the Pin contract 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;
        }
    }
}