Trait safer_ffi::prelude::ManuallyDropMut
source · pub trait ManuallyDropMut {
type Ret: ?Sized;
// Required method
fn manually_drop_mut(&mut self) -> &mut Self::Ret;
}
Expand description
Extension trait providing a cast to the ManuallyDrop
type.
This is useful if you want to use an [Out
] reference to something that
is not Copy
(potentially because it has drop glue, in which case you
either don’t mind leaking / skipping that drop glue, or you know you will
be manually handling it).
⚠️ Misusage of this function can thus lead to memory leaks ⚠️
Example
The following fails to compile because of the missing Copy
bound:
ⓘ
use ::uninit::prelude::*;
use ::core::cell::Cell;
let mut cell = Cell::new(0);
cell.as_out().write(Cell::new(42)); // Error, not `Copy`
assert_eq!(cell.get(), 42);
We see here that the Copy
bound can be too restrictive. By calling
.manually_drop_mut()
, we no longer need to satisfy this Copy
bound; but
then we need to be careful with memory leaks.
Since ::core::mem::needs_drop::<Cell<_>>() == false
, there is nothing to
worry about:
use ::uninit::prelude::*;
use ::core::cell::Cell;
let mut cell = Cell::new(0);
cell.manually_drop_mut().as_out().write(Cell::new(42)); // OK
assert_eq!(cell.get(), 42);
Counterexample
use ::uninit::prelude::*;
use ::std::rc::Rc;
let rc = Rc::new(());
assert_eq!(Rc::strong_count(&rc), 1);
let mut rc2 = Some(Rc::clone(&rc));
assert_eq!(Rc::strong_count(&rc), 2);
// This overwrites `rc2` without running any destructor whatsoever, hence
// leaking the `rc` clone.
rc2.manually_drop_mut().as_out().write(None);
assert_eq!(Rc::strong_count(&rc), 2);
assert!(Rc::try_unwrap(rc).is_err());