Trying to understand Pin and drop

Hello. I am learning about pinning and don't fully understand about drop and pinning part.

Maybe someone can show minimal example with drop and pin?

Thanks.

Typically, once you have pinned a struct, you can never again call a &mut self method on it, but the drop method is an exception to this rule. This makes it difficult to write no-unsafe code that uses pinning in structs, since such no-unsafe code has to add extra mitigations against this exception.

I'm not sure there's much example to show.

Ok. Why calling drop is dangerous in pinned struct? Struct items can change their address through &mut self? But why it dangerous if it is drop, where only deallocation happen. It called only once? Right?

Yes. In particular, they could be mem::swapped to another location (into the static variable, for example), and stored there, which would violate Pin contract.

The danger is if the drop impl moves some of the values somewhere else, making then survive the drop.

But i can move out some values from non pinned struct in drop too? What's the difference then?

fn inner_drop(this: Pin<&mut Type>){}

Isn't it the same as &Type, because you can't get mutable reference with Pin?

If it isn't pinned, you haven't promised not to move them, so it's fine in this case.

Not quite. With unsafe code you can get a mutable reference, and additionally, creating a Pin<&mut T> is a promise to never move that value ever again, which a &T would not promise.


Generally all of this is only relevant when using something like pin-project, which lets you write a struct that contains a value that should be pinned, and "forward" that pinning from your wrapper struct to the inner struct. When you use a crate like pin-project, this wrapper struct does not need any unsafe code (besides the unsafe generated by the macros in pin-project). The problems with Drop is that the pin-project macro must prevent you from generating a Drop impl for your wrapper struct, as you could otherwise write code that used pin-project, but no unsafe of your own, that could pin a struct, then move it.

When you are not using pin-project, you are using unsafe code, and then the problems are moot because by using unsafe code, you have promised to write your code correctly.