use std::marker::PhantomPinned;
use pin_project::pin_project;
#[pin_project]
struct Struct<T> {
field: T,
#[pin] // <------ This `#[pin]` is required to make `Struct` to `!Unpin`.
_pin: PhantomPinned,
}
Note that using PhantomPinned without #[pin] attribute has no effect.
Rust auto-implements Unpin when all struct fields implement Unpin, but with #[pin_project]'s macro, if no #[pin] field, the struct always implements Unpin, event if it has !Unpin fields.
Why is pin-project designed this way?
The #[pin_project] attribute is designed for structs and enums where at least one of the fields is !Unpin and provides a safe interface for accessing both Unpin and !Unpin fields. By default, no fields are considered structurally pinned by #[pin_project]. If you do not add a #[pin] then the macro will generate access to &mut Field from Pin<&mut Struct>.
So even if a field is !Unpin, by omitting #[pin], you are creating a way to access an unprotected &mut Field. Therefore, you are not treating it as pinned by Pin<&mut Struct> and thus your struct can still be Unpin.
Why
pin-projectimplementUnpinfor any struct when no structural fields?
Directly from the Rust std::pin module (emphasis mine): "The struct must only be Unpin if all the structural fields are Unpin." And by omitting #[pin], you are communicating to the macro that the field is not structural (unlike how the compiler considers all fields structural when auto-implementing Unpin).
Why is
pin-projectdesigned this way?
For one, a macro does not know the properties of the fields it sees, it only sees the AST for the struct or enum that it is attached to. So it cannot know that _pin is !Unpin or not and act accordingly.
With that in mind, it makes more sense for the structural pinning behavior to be opt-in rather than opt-out. Almost all Rust types are Unpin, and if you were to try to use a &mut Field that is !Unpin as a Pin<&mut Field> (as is common when implementing Future or third-party Async* trait) then you would have to use unsafe to do so and negates the benefits of using the macro.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With