About Pin, why should drop be careful for a possible pinned T?

The documents:

This can never cause a problem in safe code because implementing a type that relies on pinning requires unsafe code, but be aware that deciding to make use of pinning in your type (for example by implementing some operation on Pin<&Self> or Pin<&mut Self>) has consequences for your Drop implementation as well: if an element of your type could have been pinned, you must treat Drop as implicitly taking Pin<&mut Self>.

For example, you could implement Drop as follows:

impl Drop for Type {
    fn drop(&mut self) {
        // `new_unchecked` is okay because we know this value is never used
        // again after being dropped.
        inner_drop(unsafe { Pin::new_unchecked(self)});
        fn inner_drop(this: Pin<&mut Type>) {
            // Actual drop code goes here.
        }
    }
}

My question is Pin is some pointer of T, which can't outlive T. Meaning, when drop(&mut T) is called, the pointer should be out of scope already.

So, there should be no Pin alive, then, dropping T should not be so dangerous.

Is there something I missed?

Problem is that, once the value was pinned, code can assume that it will be pinned forever (that is, until the corresponding block of memory is either deallocated or repurposed), not just for the timespan of the Pin. And this includes the Drop implementation.

1 Like

Ok, another question unrelated the origin, but it's indeed just below of the drop.

Moreover, if your type is #[repr(packed)] , the compiler will automatically move fields around to be able to drop them. It might even do that for fields that happen to be sufficiently aligned. As a consequence, you cannot use pinning with a #[repr(packed)] type.

What means move fields around to be able to drop them?
It does not seems reordering of the fields because of align or something, well, does it means the compiler will move the fields out of the struct at dropping, so the field's drop glue may see a proper aligned &mut self?

yes, that should be exactly what it means

Drop::drop() takes &mut self which is a reference. A reference must always be aligned. Packed fields may not be stored in aligned location, so they must be moved to aligned storage before drop.