'How to destructure/move out of Drop implementing type?
I have a managed pointer type Uniq, implementing Drop, that has a method that is supposed to consume it without running drop and return a Box of its allocation.
struct Uniq<T> { data: ManuallyDropped<Box<T>>, metadata: Metadata }
impl Uniq<T> {
fn into_parts(/* mut */ self) -> (Box<T>, Metadata) {
(ManuallyDrop::into_inner(self.data), self.metadata) // doesn't work
// let Self { data, metadata } = self; // doesn't work either
}
}
impl<T> Drop for Uniq<T> {
fn drop(&mut self) {
// fancy_management_ledgerwork(self.metadata)
}
}
#[derive(Clone, Copy)]
struct Metadata(usize);
How do I accomplish this kind of "destructuring move" for my type which implements Drop?
Note: Literally every search engine result is about people not understanding move semantics. I do understand move semantics and I am trying to exploit them to ensure memory safety and I cannot figure out how. I'd rather not convert the ManuallyDrop<Box<T>> to something less-safe-but-Copy like NonNull<T>.
Solution 1:[1]
Use ManuallyDrop::take():
fn into_parts(mut self) -> (Box<T>, Metadata) {
(unsafe { ManuallyDrop::take(&mut self.data) }, self.metadata)
}
Edit: As correctly mentioned by @FilipeRodrigues, if your Drop implementation tries to do cleanup you also need to prevent it from running, either by std::mem::forget() or by wrapping self in ManuallyDrop.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
