struct Foo {
b: Box<i32>,
}
impl Drop for Foo {
fn drop(&mut self) {
// do something
println!("foo destroyed")
}
}
And some day I add a function like this:
struct Bar {
b: Box<i32>,
}
impl Foo {
// a function to turn a foo to a bar.
pub fn to_bar(self) -> Bar {
Bar {
b: self.b,
}
}
}
But this will not compile since Foo has implemented the trait Drop.
I tried to use ManuallyDrop, but it seems that it is designed for struct fields, I don't found a way to use it in my case.
So what can I do? Notice that not only I want to get a Bar from a Foo, but also I don't want the drop() of foo get called at all.
P.S. If I write C++, I will add a field to tell if the object is "moved", and do nothing in the destructor by checking the field. I wondered if I should do the same in Rust, or there's a better way.
impl Foo {
// a function to turn a foo to a bar.
pub fn to_bar(self) -> Bar {
// Safety: okay because we'll never be touching "self.b" again.
let b = unsafe { std::ptr::read(&self.b) };
// Note: if Foo had other fields, you would need to
// call std::ptr::drop_in_place() for them here.
// Forget the value so we don't call its Drop implementation
std::mem::forget(self);
Bar { b }
}
}
@Michael-F-Bryan It's generally recommended to put self in ManuallyDrop and then doing the ptr::read as opposed to doing it in the other order. It is less fragile to stray panics leading to a double-free.