#![allow(dead_code)]
use std::mem::ManuallyDrop;
use std::ops::{Deref, DerefMut};
use std::panic;

pub struct SilentDrop<T: panic::UnwindSafe> {
    inner: ManuallyDrop<T>,
}

impl<T: panic::UnwindSafe> SilentDrop<T> {
    pub fn new(inner: T) -> Self {
        Self {
            inner: ManuallyDrop::new(inner),
        }
    }
}

impl<T: panic::UnwindSafe> Deref for SilentDrop<T> {
    type Target = T;

    fn deref(&self) -> &Self::Target {
        self.inner.deref()
    }
}

impl<T: panic::UnwindSafe> DerefMut for SilentDrop<T> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        self.inner.deref_mut()
    }
}

impl<T: panic::UnwindSafe> Drop for SilentDrop<T> {
    fn drop(&mut self) {
        let prev_hook = panic::take_hook();
        panic::set_hook(Box::new(|_| {}));
        let inner = unsafe { ManuallyDrop::take(&mut self.inner) };
        let destroy_closure = || {
            drop(inner);
        };
        if panic::catch_unwind(destroy_closure).is_err() {};
        panic::set_hook(prev_hook);
    }
}
