Why is Pin::map_unchecked unsafe?

143 Views Asked by At
pub unsafe fn map_unchecked<U, F>(self, func: F) -> Pin<&'a U>
where
    F: FnOnce(&T) -> &U,
    U: ?Sized,

FnOnce(&T) -> &U params is a reference so it can't move T anyway. Why is this function unsafe?

There is a same question here, but can't understand this example:

enter image description here

1

There are 1 best solutions below

5
kmdreko On

Almost all unsafe functions in the Rust standard library have documentation explaining why. From the documentation for Pin::map_unchecked:

Constructs a new pin by mapping the interior value.

For example, if you wanted to get a Pin of a field of something, you could use this to get access to that field in one line of code. However, there are several gotchas with these “pinning projections”; see the pin module documentation for further details on that topic.

Safety

This function is unsafe. You must guarantee that the data you return will not move so long as the argument value does not move (for example, because it is one of the fields of that value), and also that you do not move out of the argument you receive to the interior function.

This is essentially the same reason why Pin::new_unchecked is unsafe. Pinning a value means that it must never move again not just while protected by the Pin. However, this function alone cannot ensure that guarantee and must be provided by the developer using it.

The pin module that is linked includes many requirements that must be followed for structural pinning i.e. if getting a field from Pin<&Self> requires the field to also be pinned which is a primary reason to use map_unchecked. Requirements include: you cannot give &mut access to it elsewhere, it cannot be moved from even in the Drop implementation, it cannot be deallocated unless it is dropped, etc.