How `std::mem::ManuallyDrop` work?

I was surprised to see that ManuallyDrop don't automatically call destructor.

The signature of std::mem::ManuallyDrop is :

pub struct ManuallyDrop<T: ?Sized> {
    value: T,
}
impl<T> ManuallyDrop<T> {
    pub const fn new(value: T) -> ManuallyDrop<T> {
        ManuallyDrop { value }
    }
    pub const fn into_inner(slot: ManuallyDrop<T>) -> T {
        slot.value
    }
}

Doesn't it call drop function ? What is the magic in here ?! Let's try it:

use std::mem::ManuallyDrop;
struct Foo(u8);
impl Drop for Foo {
    fn drop(&mut self) {
        println!("Dropping Foo({})", self.0);
    }
}
pub struct ConditionalDrop<T: ?Sized> {
    value: T,
}
impl<T> ConditionalDrop<T> {
    pub const fn new(value: T) -> ConditionalDrop<T> {
        ConditionalDrop { value }
    }
}
fn main() {
    let a = ManuallyDrop::new(Foo(4));
    let b = ManuallyDrop::new(Foo(3));

    let x = ConditionalDrop::new(Foo(2));
    let y = ConditionalDrop::new(Foo(1));
}

It print:

Dropping Foo(1)
Dropping Foo(2)

So why ManuallyDrop doesn't call destructor ? Or did I missed something?

3 Likes

It's a language-level type -- the compiler is aware of it and treats it specially, similar to UnsafeCell. Not calling the destructor is its purpose.

Here's the RFC.

1 Like

If you look up a few lines from the source you linked, the #[lang = "manually_drop"] attribute is what connects it to that special behavior in the compiler.

4 Likes

And I thought that those are some kind of useless attributes :roll_eyes:, So does every #[lang = ...] attributes are special as this one?

Sometimes lang items are relatively benign, like when the compiler needs IntoIterator, Iterator, and Option in order to transform for loops. Those things are otherwise pretty normal, whereas items like UnsafeCell and ManuallyDrop have deeper meaning.

edit: those for-loop examples aren't directly lang items, but their relevant methods / variants are.

1 Like

Here's a blog post about them from a little while ago.

3 Likes

That's a somewhat contentious topic and depends on what metric you use for specialness.

Not all lang items are special in the same ways, but in a sense they are all equally special. It's the code inside the compiler that determines what a lang item means.

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.