macro_rules! pin_project {
(
$(#[$attrs:meta])*
pub struct $ident:ident
$(<
$( $lifetime:lifetime $(: $lifetime_bound:lifetime)? ),* $(,)?
$( $generics:ident $(: $generics_bound:path)? $(: ?$generics_unsized_bound:path)? $(: $generics_lifetime_bound:lifetime)? $(= $generics_default:ty)? ),* $(,)?
>)?
$(where
$($where_clause_ty:ty : $where_clause_bound:path),* $(,)?
)?
{
$(
$(#[$pin:ident])?
$field_vis:vis $field:ident: $field_ty:ty
),+ $(,)?
}
) => { ... };
(
$(#[$attrs:meta])*
$vis:vis struct $ident:ident
$(<
$( $lifetime:lifetime $(: $lifetime_bound:lifetime)? ),* $(,)?
$( $generics:ident $(: $generics_bound:path)? $(: ?$generics_unsized_bound:path)? $(: $generics_lifetime_bound:lifetime)? $(= $generics_default:ty)? ),* $(,)?
>)?
$(where
$($where_clause_ty:ty : $where_clause_bound:path),* $(,)?
)?
{
$(
$(#[$pin:ident])?
$field_vis:vis $field:ident: $field_ty:ty
),+ $(,)?
}
) => { ... };
(@internal ($proj_vis:vis)
$(#[$attrs:meta])*
$vis:vis struct $ident:ident
$(<
$( $lifetime:lifetime $(: $lifetime_bound:lifetime)? ),*
$( $generics:ident $(: $generics_bound:path)? $(: ?$generics_unsized_bound:path)? $(: $generics_lifetime_bound:lifetime)? $(= $generics_default:ty)? ),*
>)?
$(where
$($where_clause_ty:ty : $where_clause_bound:path),*
)?
{
$(
$(#[$pin:ident])?
$field_vis:vis $field:ident: $field_ty:ty
),+
}
) => { ... };
(@make_unpin_bound
#[pin]
$field_ty:ty
) => { ... };
(@make_unpin_bound
$field_ty:ty
) => { ... };
(@make_unsafe_field_proj
$this:ident;
#[pin]
$field:ident;
$($mut:ident)?
) => { ... };
(@make_unsafe_field_proj
$this:ident;
$field:ident;
$($mut:ident)?
) => { ... };
(@make_proj_field
#[pin]
$field_ty:ty;
$($mut:ident)?
) => { ... };
(@make_proj_field
$field_ty:ty;
$($mut:ident)?
) => { ... };
}
A macro that creates a projection struct covering all the fields.
This macro creates a projection struct according to the following rules:
- For the field that uses
#[pin] attribute, makes the pinned reference to
the field.
- For the other fields, makes the unpinned reference to the field.
The following methods are implemented on the original type:
fn project(self: Pin<&mut Self>) -> Projection<'_>;
fn project_ref(self: Pin<&Self>) -> ProjectionRef<'_>;
The visibility of the projected type and projection method is based on the
original type. However, if the visibility of the original type is pub,
the visibility of the projected type and the projection method is pub(crate).
If you want to call the project method multiple times or later use the
original Pin type, it needs to use .as_mut() to avoid
consuming the Pin.
pin_project! macro guarantees safety in much the same way as pin-project crate.
Both are completely safe unless you write other unsafe code.
See pin-project crate for more details.
use pin_project_lite::pin_project;
use std::pin::Pin;
pin_project! {
struct Struct<T, U> {
#[pin]
pinned: T,
unpinned: U,
}
}
impl<T, U> Struct<T, U> {
fn foo(self: Pin<&mut Self>) {
let this = self.project();
let _: Pin<&mut T> = this.pinned;
let _: &mut U = this.unpinned;
}
}
Note that borrowing the field where #[pin] attribute is used multiple
times requires using .as_mut() to avoid
consuming the Pin.