1560 lines
49 KiB
Rust
1560 lines
49 KiB
Rust
//! A lightweight version of [pin-project] written with declarative macros.
|
|
//!
|
|
//! # Examples
|
|
//!
|
|
//! [`pin_project!`] macro creates a projection type covering all the fields of struct.
|
|
//!
|
|
//! ```rust
|
|
//! use std::pin::Pin;
|
|
//!
|
|
//! use pin_project_lite::pin_project;
|
|
//!
|
|
//! pin_project! {
|
|
//! struct Struct<T, U> {
|
|
//! #[pin]
|
|
//! pinned: T,
|
|
//! unpinned: U,
|
|
//! }
|
|
//! }
|
|
//!
|
|
//! impl<T, U> Struct<T, U> {
|
|
//! fn method(self: Pin<&mut Self>) {
|
|
//! let this = self.project();
|
|
//! let _: Pin<&mut T> = this.pinned; // Pinned reference to the field
|
|
//! let _: &mut U = this.unpinned; // Normal reference to the field
|
|
//! }
|
|
//! }
|
|
//! ```
|
|
//!
|
|
//! To use [`pin_project!`] on enums, you need to name the projection type
|
|
//! returned from the method.
|
|
//!
|
|
//! ```rust
|
|
//! use std::pin::Pin;
|
|
//!
|
|
//! use pin_project_lite::pin_project;
|
|
//!
|
|
//! pin_project! {
|
|
//! #[project = EnumProj]
|
|
//! enum Enum<T, U> {
|
|
//! Variant { #[pin] pinned: T, unpinned: U },
|
|
//! }
|
|
//! }
|
|
//!
|
|
//! impl<T, U> Enum<T, U> {
|
|
//! fn method(self: Pin<&mut Self>) {
|
|
//! match self.project() {
|
|
//! EnumProj::Variant { pinned, unpinned } => {
|
|
//! let _: Pin<&mut T> = pinned;
|
|
//! let _: &mut U = unpinned;
|
|
//! }
|
|
//! }
|
|
//! }
|
|
//! }
|
|
//! ```
|
|
//!
|
|
//! # [pin-project] vs pin-project-lite
|
|
//!
|
|
//! Here are some similarities and differences compared to [pin-project].
|
|
//!
|
|
//! ## Similar: Safety
|
|
//!
|
|
//! pin-project-lite guarantees safety in much the same way as [pin-project].
|
|
//! Both are completely safe unless you write other unsafe code.
|
|
//!
|
|
//! ## Different: Minimal design
|
|
//!
|
|
//! This library does not tackle as expansive of a range of use cases as
|
|
//! [pin-project] does. If your use case is not already covered, please use
|
|
//! [pin-project].
|
|
//!
|
|
//! ## Different: No proc-macro related dependencies
|
|
//!
|
|
//! This is the **only** reason to use this crate. However, **if you already
|
|
//! have proc-macro related dependencies in your crate's dependency graph, there
|
|
//! is no benefit from using this crate.** (Note: There is almost no difference
|
|
//! in the amount of code generated between [pin-project] and pin-project-lite.)
|
|
//!
|
|
//! ## Different: No useful error messages
|
|
//!
|
|
//! This macro does not handle any invalid input. So error messages are not to
|
|
//! be useful in most cases. If you do need useful error messages, then upon
|
|
//! error you can pass the same input to [pin-project] to receive a helpful
|
|
//! description of the compile error.
|
|
//!
|
|
//! ## Different: No support for custom Unpin implementation
|
|
//!
|
|
//! pin-project supports this by [`UnsafeUnpin`][unsafe-unpin] and [`!Unpin`][not-unpin].
|
|
//!
|
|
//! ## Different: No support for tuple structs and tuple variants
|
|
//!
|
|
//! pin-project supports this.
|
|
//!
|
|
//! [not-unpin]: https://docs.rs/pin-project/1/pin_project/attr.pin_project.html#unpin
|
|
//! [pin-project]: https://github.com/taiki-e/pin-project
|
|
//! [unsafe-unpin]: https://docs.rs/pin-project/1/pin_project/attr.pin_project.html#unsafeunpin
|
|
|
|
#![no_std]
|
|
#![doc(test(
|
|
no_crate_inject,
|
|
attr(
|
|
deny(warnings, rust_2018_idioms, single_use_lifetimes),
|
|
allow(dead_code, unused_variables)
|
|
)
|
|
))]
|
|
#![warn(rust_2018_idioms, single_use_lifetimes, unreachable_pub)]
|
|
#![warn(clippy::default_trait_access, clippy::wildcard_imports)]
|
|
|
|
/// A macro that creates a projection type covering all the fields of struct.
|
|
///
|
|
/// This macro creates a projection type 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.
|
|
///
|
|
/// And the following methods are implemented on the original type:
|
|
///
|
|
/// ```rust
|
|
/// # use std::pin::Pin;
|
|
/// # type Projection<'a> = &'a ();
|
|
/// # type ProjectionRef<'a> = &'a ();
|
|
/// # trait Dox {
|
|
/// fn project(self: Pin<&mut Self>) -> Projection<'_>;
|
|
/// fn project_ref(self: Pin<&Self>) -> ProjectionRef<'_>;
|
|
/// # }
|
|
/// ```
|
|
///
|
|
/// By passing an attribute with the same name as the method to the macro,
|
|
/// you can name the projection type returned from the method. This allows you
|
|
/// to use pattern matching on the projected types.
|
|
///
|
|
/// ```rust
|
|
/// # use pin_project_lite::pin_project;
|
|
/// # use std::pin::Pin;
|
|
/// pin_project! {
|
|
/// #[project = EnumProj]
|
|
/// enum Enum<T> {
|
|
/// Variant { #[pin] field: T },
|
|
/// }
|
|
/// }
|
|
///
|
|
/// impl<T> Enum<T> {
|
|
/// fn method(self: Pin<&mut Self>) {
|
|
/// let this: EnumProj<'_, T> = self.project();
|
|
/// match this {
|
|
/// EnumProj::Variant { field } => {
|
|
/// let _: Pin<&mut T> = field;
|
|
/// }
|
|
/// }
|
|
/// }
|
|
/// }
|
|
/// ```
|
|
///
|
|
/// By passing the `#[project_replace = MyProjReplace]` attribute you may create an additional
|
|
/// method which allows the contents of `Pin<&mut Self>` to be replaced while simultaneously moving
|
|
/// out all unpinned fields in `Self`.
|
|
///
|
|
/// ```rust
|
|
/// # use std::pin::Pin;
|
|
/// # type MyProjReplace = ();
|
|
/// # trait Dox {
|
|
/// fn project_replace(self: Pin<&mut Self>, replacement: Self) -> MyProjReplace;
|
|
/// # }
|
|
/// ```
|
|
///
|
|
/// Also, note that the projection types returned by `project` and `project_ref` have
|
|
/// an additional lifetime at the beginning of generics.
|
|
///
|
|
/// ```text
|
|
/// let this: EnumProj<'_, T> = self.project();
|
|
/// ^^
|
|
/// ```
|
|
///
|
|
/// The visibility of the projected types and projection methods is based on the
|
|
/// original type. However, if the visibility of the original type is `pub`, the
|
|
/// visibility of the projected types and the projection methods is downgraded
|
|
/// to `pub(crate)`.
|
|
///
|
|
/// # Safety
|
|
///
|
|
/// `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.
|
|
///
|
|
/// # Examples
|
|
///
|
|
/// ```rust
|
|
/// use std::pin::Pin;
|
|
///
|
|
/// use pin_project_lite::pin_project;
|
|
///
|
|
/// pin_project! {
|
|
/// struct Struct<T, U> {
|
|
/// #[pin]
|
|
/// pinned: T,
|
|
/// unpinned: U,
|
|
/// }
|
|
/// }
|
|
///
|
|
/// impl<T, U> Struct<T, U> {
|
|
/// fn method(self: Pin<&mut Self>) {
|
|
/// let this = self.project();
|
|
/// let _: Pin<&mut T> = this.pinned; // Pinned reference to the field
|
|
/// let _: &mut U = this.unpinned; // Normal reference to the field
|
|
/// }
|
|
/// }
|
|
/// ```
|
|
///
|
|
/// To use `pin_project!` on enums, you need to name the projection type
|
|
/// returned from the method.
|
|
///
|
|
/// ```rust
|
|
/// use std::pin::Pin;
|
|
///
|
|
/// use pin_project_lite::pin_project;
|
|
///
|
|
/// pin_project! {
|
|
/// #[project = EnumProj]
|
|
/// enum Enum<T> {
|
|
/// Struct {
|
|
/// #[pin]
|
|
/// field: T,
|
|
/// },
|
|
/// Unit,
|
|
/// }
|
|
/// }
|
|
///
|
|
/// impl<T> Enum<T> {
|
|
/// fn method(self: Pin<&mut Self>) {
|
|
/// match self.project() {
|
|
/// EnumProj::Struct { field } => {
|
|
/// let _: Pin<&mut T> = field;
|
|
/// }
|
|
/// EnumProj::Unit => {}
|
|
/// }
|
|
/// }
|
|
/// }
|
|
/// ```
|
|
///
|
|
/// If you want to call the `project()` method multiple times or later use the
|
|
/// original [`Pin`] type, it needs to use [`.as_mut()`][`Pin::as_mut`] to avoid
|
|
/// consuming the [`Pin`].
|
|
///
|
|
/// ```rust
|
|
/// use std::pin::Pin;
|
|
///
|
|
/// use pin_project_lite::pin_project;
|
|
///
|
|
/// pin_project! {
|
|
/// struct Struct<T> {
|
|
/// #[pin]
|
|
/// field: T,
|
|
/// }
|
|
/// }
|
|
///
|
|
/// impl<T> Struct<T> {
|
|
/// fn call_project_twice(mut self: Pin<&mut Self>) {
|
|
/// // `project` consumes `self`, so reborrow the `Pin<&mut Self>` via `as_mut`.
|
|
/// self.as_mut().project();
|
|
/// self.as_mut().project();
|
|
/// }
|
|
/// }
|
|
/// ```
|
|
///
|
|
/// # `!Unpin`
|
|
///
|
|
/// If you want to ensure that [`Unpin`] is not implemented, use `#[pin]`
|
|
/// attribute for a [`PhantomPinned`] field.
|
|
///
|
|
/// ```rust
|
|
/// use std::marker::PhantomPinned;
|
|
///
|
|
/// use pin_project_lite::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.
|
|
///
|
|
/// [`PhantomPinned`]: core::marker::PhantomPinned
|
|
/// [`Pin::as_mut`]: core::pin::Pin::as_mut
|
|
/// [`Pin`]: core::pin::Pin
|
|
/// [pin-project]: https://github.com/taiki-e/pin-project
|
|
#[macro_export]
|
|
macro_rules! pin_project {
|
|
($($tt:tt)*) => {
|
|
$crate::__pin_project_internal! {
|
|
[][][][]
|
|
$($tt)*
|
|
}
|
|
};
|
|
}
|
|
|
|
// limitations:
|
|
// - no support for tuple structs and tuple variant (wontfix).
|
|
// - no support for multiple trait/lifetime bounds.
|
|
// - no support for `Self` in where clauses. (wontfix)
|
|
// - no support for overlapping lifetime names. (wontfix)
|
|
// - no interoperability with other field attributes.
|
|
// - no useful error messages. (wontfix)
|
|
// etc...
|
|
|
|
#[doc(hidden)]
|
|
#[macro_export]
|
|
macro_rules! __pin_project_expand {
|
|
(
|
|
[$($proj_mut_ident:ident)?]
|
|
[$($proj_ref_ident:ident)?]
|
|
[$($proj_replace_ident:ident)?]
|
|
[$proj_vis:vis]
|
|
[$(#[$attrs:meta])* $vis:vis $struct_ty_ident:ident $ident:ident]
|
|
[$($def_generics:tt)*]
|
|
[$($impl_generics:tt)*] [$($ty_generics:tt)*] [$(where $($where_clause:tt)*)?]
|
|
{
|
|
$($body_data:tt)*
|
|
}
|
|
$(impl $($pinned_drop:tt)*)?
|
|
) => {
|
|
$crate::__pin_project_reconstruct! {
|
|
[$(#[$attrs])* $vis $struct_ty_ident $ident]
|
|
[$($def_generics)*] [$($impl_generics)*]
|
|
[$($ty_generics)*] [$(where $($where_clause)*)?]
|
|
{
|
|
$($body_data)*
|
|
}
|
|
}
|
|
|
|
$crate::__pin_project_make_proj_ty! {
|
|
[$($proj_mut_ident)?]
|
|
[$proj_vis $struct_ty_ident $ident]
|
|
[__pin_project_make_proj_field_mut]
|
|
[$($impl_generics)*] [$($ty_generics)*] [$(where $($where_clause)*)?]
|
|
{
|
|
$($body_data)*
|
|
}
|
|
}
|
|
$crate::__pin_project_make_proj_ty! {
|
|
[$($proj_ref_ident)?]
|
|
[$proj_vis $struct_ty_ident $ident]
|
|
[__pin_project_make_proj_field_ref]
|
|
[$($impl_generics)*] [$($ty_generics)*] [$(where $($where_clause)*)?]
|
|
{
|
|
$($body_data)*
|
|
}
|
|
}
|
|
$crate::__pin_project_make_proj_replace_ty! {
|
|
[$($proj_replace_ident)?]
|
|
[$proj_vis $struct_ty_ident]
|
|
[__pin_project_make_proj_field_replace]
|
|
[$($impl_generics)*] [$($ty_generics)*] [$(where $($where_clause)*)?]
|
|
{
|
|
$($body_data)*
|
|
}
|
|
}
|
|
|
|
$crate::__pin_project_constant! {
|
|
[$(#[$attrs])* $vis $struct_ty_ident $ident]
|
|
[$($proj_mut_ident)?] [$($proj_ref_ident)?] [$($proj_replace_ident)?]
|
|
[$proj_vis]
|
|
[$($def_generics)*] [$($impl_generics)*]
|
|
[$($ty_generics)*] [$(where $($where_clause)*)?]
|
|
{
|
|
$($body_data)*
|
|
}
|
|
$(impl $($pinned_drop)*)?
|
|
}
|
|
};
|
|
}
|
|
|
|
#[doc(hidden)]
|
|
#[macro_export]
|
|
macro_rules! __pin_project_constant {
|
|
(
|
|
[$(#[$attrs:meta])* $vis:vis struct $ident:ident]
|
|
[$($proj_mut_ident:ident)?] [$($proj_ref_ident:ident)?] [$($proj_replace_ident:ident)?]
|
|
[$proj_vis:vis]
|
|
[$($def_generics:tt)*]
|
|
[$($impl_generics:tt)*] [$($ty_generics:tt)*] [$(where $($where_clause:tt)*)?]
|
|
{
|
|
$(
|
|
$(#[$pin:ident])?
|
|
$field_vis:vis $field:ident: $field_ty:ty
|
|
),+ $(,)?
|
|
}
|
|
$(impl $($pinned_drop:tt)*)?
|
|
) => {
|
|
#[allow(explicit_outlives_requirements)] // https://github.com/rust-lang/rust/issues/60993
|
|
#[allow(single_use_lifetimes)] // https://github.com/rust-lang/rust/issues/55058
|
|
// This lint warns of `clippy::*` generated by external macros.
|
|
// We allow this lint for compatibility with older compilers.
|
|
#[allow(clippy::unknown_clippy_lints)]
|
|
#[allow(clippy::redundant_pub_crate)] // This lint warns `pub(crate)` field in private struct.
|
|
#[allow(clippy::used_underscore_binding)]
|
|
const _: () = {
|
|
$crate::__pin_project_make_proj_ty! {
|
|
[$($proj_mut_ident)? Projection]
|
|
[$proj_vis struct $ident]
|
|
[__pin_project_make_proj_field_mut]
|
|
[$($impl_generics)*] [$($ty_generics)*] [$(where $($where_clause)*)?]
|
|
{
|
|
$(
|
|
$(#[$pin])?
|
|
$field_vis $field: $field_ty
|
|
),+
|
|
}
|
|
}
|
|
$crate::__pin_project_make_proj_ty! {
|
|
[$($proj_ref_ident)? ProjectionRef]
|
|
[$proj_vis struct $ident]
|
|
[__pin_project_make_proj_field_ref]
|
|
[$($impl_generics)*] [$($ty_generics)*] [$(where $($where_clause)*)?]
|
|
{
|
|
$(
|
|
$(#[$pin])?
|
|
$field_vis $field: $field_ty
|
|
),+
|
|
}
|
|
}
|
|
|
|
impl <$($impl_generics)*> $ident <$($ty_generics)*>
|
|
$(where
|
|
$($where_clause)*)?
|
|
{
|
|
$crate::__pin_project_struct_make_proj_method! {
|
|
[$($proj_mut_ident)? Projection]
|
|
[$proj_vis]
|
|
[project get_unchecked_mut mut]
|
|
[$($ty_generics)*]
|
|
{
|
|
$(
|
|
$(#[$pin])?
|
|
$field_vis $field
|
|
),+
|
|
}
|
|
}
|
|
$crate::__pin_project_struct_make_proj_method! {
|
|
[$($proj_ref_ident)? ProjectionRef]
|
|
[$proj_vis]
|
|
[project_ref get_ref]
|
|
[$($ty_generics)*]
|
|
{
|
|
$(
|
|
$(#[$pin])?
|
|
$field_vis $field
|
|
),+
|
|
}
|
|
}
|
|
$crate::__pin_project_struct_make_proj_replace_method! {
|
|
[$($proj_replace_ident)?]
|
|
[$proj_vis]
|
|
[ProjectionReplace]
|
|
[$($ty_generics)*]
|
|
{
|
|
$(
|
|
$(#[$pin])?
|
|
$field_vis $field
|
|
),+
|
|
}
|
|
}
|
|
}
|
|
|
|
$crate::__pin_project_make_unpin_impl! {
|
|
[$vis $ident]
|
|
[$($impl_generics)*] [$($ty_generics)*] [$(where $($where_clause)*)?]
|
|
$(
|
|
$field: $crate::__pin_project_make_unpin_bound!(
|
|
$(#[$pin])? $field_ty
|
|
)
|
|
),+
|
|
}
|
|
|
|
$crate::__pin_project_make_drop_impl! {
|
|
[$ident]
|
|
[$($impl_generics)*] [$($ty_generics)*] [$(where $($where_clause)*)?]
|
|
$(impl $($pinned_drop)*)?
|
|
}
|
|
|
|
// Ensure that it's impossible to use pin projections on a #[repr(packed)] struct.
|
|
//
|
|
// Taking a reference to a packed field is UB, and applying
|
|
// `#[forbid(unaligned_references)]` makes sure that doing this is a hard error.
|
|
//
|
|
// If the struct ends up having #[repr(packed)] applied somehow,
|
|
// this will generate an (unfriendly) error message. Under all reasonable
|
|
// circumstances, we'll detect the #[repr(packed)] attribute, and generate
|
|
// a much nicer error above.
|
|
//
|
|
// See https://github.com/taiki-e/pin-project/pull/34 for more details.
|
|
//
|
|
// Note:
|
|
// - Lint-based tricks aren't perfect, but they're much better than nothing:
|
|
// https://github.com/taiki-e/pin-project-lite/issues/26
|
|
//
|
|
// - Enable both unaligned_references and safe_packed_borrows lints
|
|
// because unaligned_references lint does not exist in older compilers:
|
|
// https://github.com/taiki-e/pin-project-lite/pull/55
|
|
// https://github.com/rust-lang/rust/pull/82525
|
|
#[forbid(unaligned_references, safe_packed_borrows)]
|
|
fn __assert_not_repr_packed <$($impl_generics)*> (this: &$ident <$($ty_generics)*>)
|
|
$(where
|
|
$($where_clause)*)?
|
|
{
|
|
$(
|
|
let _ = &this.$field;
|
|
)+
|
|
}
|
|
};
|
|
};
|
|
(
|
|
[$(#[$attrs:meta])* $vis:vis enum $ident:ident]
|
|
[$($proj_mut_ident:ident)?] [$($proj_ref_ident:ident)?] [$($proj_replace_ident:ident)?]
|
|
[$proj_vis:vis]
|
|
[$($def_generics:tt)*]
|
|
[$($impl_generics:tt)*] [$($ty_generics:tt)*] [$(where $($where_clause:tt)*)?]
|
|
{
|
|
$(
|
|
$(#[$variant_attrs:meta])*
|
|
$variant:ident $({
|
|
$(
|
|
$(#[$pin:ident])?
|
|
$field:ident: $field_ty:ty
|
|
),+ $(,)?
|
|
})?
|
|
),+ $(,)?
|
|
}
|
|
$(impl $($pinned_drop:tt)*)?
|
|
) => {
|
|
#[allow(single_use_lifetimes)] // https://github.com/rust-lang/rust/issues/55058
|
|
// This lint warns of `clippy::*` generated by external macros.
|
|
// We allow this lint for compatibility with older compilers.
|
|
#[allow(clippy::unknown_clippy_lints)]
|
|
#[allow(clippy::used_underscore_binding)]
|
|
const _: () = {
|
|
impl <$($impl_generics)*> $ident <$($ty_generics)*>
|
|
$(where
|
|
$($where_clause)*)?
|
|
{
|
|
$crate::__pin_project_enum_make_proj_method! {
|
|
[$($proj_mut_ident)?]
|
|
[$proj_vis]
|
|
[project get_unchecked_mut mut]
|
|
[$($ty_generics)*]
|
|
{
|
|
$(
|
|
$variant $({
|
|
$(
|
|
$(#[$pin])?
|
|
$field
|
|
),+
|
|
})?
|
|
),+
|
|
}
|
|
}
|
|
$crate::__pin_project_enum_make_proj_method! {
|
|
[$($proj_ref_ident)?]
|
|
[$proj_vis]
|
|
[project_ref get_ref]
|
|
[$($ty_generics)*]
|
|
{
|
|
$(
|
|
$variant $({
|
|
$(
|
|
$(#[$pin])?
|
|
$field
|
|
),+
|
|
})?
|
|
),+
|
|
}
|
|
}
|
|
$crate::__pin_project_enum_make_proj_replace_method! {
|
|
[$($proj_replace_ident)?]
|
|
[$proj_vis]
|
|
[$($ty_generics)*]
|
|
{
|
|
$(
|
|
$variant $({
|
|
$(
|
|
$(#[$pin])?
|
|
$field
|
|
),+
|
|
})?
|
|
),+
|
|
}
|
|
}
|
|
}
|
|
|
|
$crate::__pin_project_make_unpin_impl! {
|
|
[$vis $ident]
|
|
[$($impl_generics)*] [$($ty_generics)*] [$(where $($where_clause)*)?]
|
|
$(
|
|
$variant: ($(
|
|
$(
|
|
$crate::__pin_project_make_unpin_bound!(
|
|
$(#[$pin])? $field_ty
|
|
)
|
|
),+
|
|
)?)
|
|
),+
|
|
}
|
|
|
|
$crate::__pin_project_make_drop_impl! {
|
|
[$ident]
|
|
[$($impl_generics)*] [$($ty_generics)*] [$(where $($where_clause)*)?]
|
|
$(impl $($pinned_drop)*)?
|
|
}
|
|
|
|
// We don't need to check for '#[repr(packed)]',
|
|
// since it does not apply to enums.
|
|
};
|
|
};
|
|
}
|
|
|
|
#[doc(hidden)]
|
|
#[macro_export]
|
|
macro_rules! __pin_project_reconstruct {
|
|
(
|
|
[$(#[$attrs:meta])* $vis:vis struct $ident:ident]
|
|
[$($def_generics:tt)*] [$($impl_generics:tt)*]
|
|
[$($ty_generics:tt)*] [$(where $($where_clause:tt)*)?]
|
|
{
|
|
$(
|
|
$(#[$pin:ident])?
|
|
$field_vis:vis $field:ident: $field_ty:ty
|
|
),+ $(,)?
|
|
}
|
|
) => {
|
|
$(#[$attrs])*
|
|
$vis struct $ident $($def_generics)*
|
|
$(where
|
|
$($where_clause)*)?
|
|
{
|
|
$(
|
|
$field_vis $field: $field_ty
|
|
),+
|
|
}
|
|
};
|
|
(
|
|
[$(#[$attrs:meta])* $vis:vis enum $ident:ident]
|
|
[$($def_generics:tt)*] [$($impl_generics:tt)*]
|
|
[$($ty_generics:tt)*] [$(where $($where_clause:tt)*)?]
|
|
{
|
|
$(
|
|
$(#[$variant_attrs:meta])*
|
|
$variant:ident $({
|
|
$(
|
|
$(#[$pin:ident])?
|
|
$field:ident: $field_ty:ty
|
|
),+ $(,)?
|
|
})?
|
|
),+ $(,)?
|
|
}
|
|
) => {
|
|
$(#[$attrs])*
|
|
$vis enum $ident $($def_generics)*
|
|
$(where
|
|
$($where_clause)*)?
|
|
{
|
|
$(
|
|
$(#[$variant_attrs])*
|
|
$variant $({
|
|
$(
|
|
$field: $field_ty
|
|
),+
|
|
})?
|
|
),+
|
|
}
|
|
};
|
|
}
|
|
|
|
#[doc(hidden)]
|
|
#[macro_export]
|
|
macro_rules! __pin_project_make_proj_ty {
|
|
([] $($field:tt)*) => {};
|
|
(
|
|
[$proj_ty_ident:ident $default_ident:ident]
|
|
[$proj_vis:vis struct $ident:ident]
|
|
$($field:tt)*
|
|
) => {};
|
|
(
|
|
[$proj_ty_ident:ident]
|
|
[$proj_vis:vis struct $ident:ident]
|
|
[$__pin_project_make_proj_field:ident]
|
|
[$($impl_generics:tt)*] [$($ty_generics:tt)*] [$(where $($where_clause:tt)*)?]
|
|
{
|
|
$(
|
|
$(#[$pin:ident])?
|
|
$field_vis:vis $field:ident: $field_ty:ty
|
|
),+ $(,)?
|
|
}
|
|
) => {
|
|
$crate::__pin_project_make_proj_ty_body! {
|
|
[$proj_ty_ident]
|
|
[$proj_vis struct $ident]
|
|
[$($impl_generics)*] [$($ty_generics)*] [$(where $($where_clause)*)?]
|
|
[
|
|
$(
|
|
$field_vis $field: $crate::$__pin_project_make_proj_field!(
|
|
$(#[$pin])? $field_ty
|
|
)
|
|
),+
|
|
]
|
|
}
|
|
};
|
|
(
|
|
[$proj_ty_ident:ident]
|
|
[$proj_vis:vis enum $ident:ident]
|
|
[$__pin_project_make_proj_field:ident]
|
|
[$($impl_generics:tt)*] [$($ty_generics:tt)*] [$(where $($where_clause:tt)*)?]
|
|
{
|
|
$(
|
|
$(#[$variant_attrs:meta])*
|
|
$variant:ident $({
|
|
$(
|
|
$(#[$pin:ident])?
|
|
$field:ident: $field_ty:ty
|
|
),+ $(,)?
|
|
})?
|
|
),+ $(,)?
|
|
}
|
|
) => {
|
|
$crate::__pin_project_make_proj_ty_body! {
|
|
[$proj_ty_ident]
|
|
[$proj_vis enum $ident]
|
|
[$($impl_generics)*] [$($ty_generics)*] [$(where $($where_clause)*)?]
|
|
[
|
|
$(
|
|
$variant $({
|
|
$(
|
|
$field: $crate::$__pin_project_make_proj_field!(
|
|
$(#[$pin])? $field_ty
|
|
)
|
|
),+
|
|
})?
|
|
),+
|
|
]
|
|
}
|
|
};
|
|
}
|
|
|
|
#[doc(hidden)]
|
|
#[macro_export]
|
|
macro_rules! __pin_project_make_proj_ty_body {
|
|
(
|
|
[$proj_ty_ident:ident]
|
|
[$proj_vis:vis $struct_ty_ident:ident $ident:ident]
|
|
[$($impl_generics:tt)*] [$($ty_generics:tt)*] [$(where $($where_clause:tt)*)?]
|
|
[$($body_data:tt)+]
|
|
) => {
|
|
#[allow(dead_code)] // This lint warns unused fields/variants.
|
|
#[allow(single_use_lifetimes)] // https://github.com/rust-lang/rust/issues/55058
|
|
// This lint warns of `clippy::*` generated by external macros.
|
|
// We allow this lint for compatibility with older compilers.
|
|
#[allow(clippy::unknown_clippy_lints)]
|
|
#[allow(clippy::mut_mut)] // This lint warns `&mut &mut <ty>`. (only needed for project)
|
|
#[allow(clippy::redundant_pub_crate)] // This lint warns `pub(crate)` field in private struct.
|
|
#[allow(clippy::ref_option_ref)] // This lint warns `&Option<&<ty>>`. (only needed for project_ref)
|
|
#[allow(clippy::type_repetition_in_bounds)] // https://github.com/rust-lang/rust-clippy/issues/4326
|
|
$proj_vis $struct_ty_ident $proj_ty_ident <'__pin, $($impl_generics)*>
|
|
where
|
|
$ident <$($ty_generics)*>: '__pin
|
|
$(, $($where_clause)*)?
|
|
{
|
|
$($body_data)+
|
|
}
|
|
};
|
|
}
|
|
|
|
#[doc(hidden)]
|
|
#[macro_export]
|
|
macro_rules! __pin_project_make_proj_replace_ty {
|
|
([] $($field:tt)*) => {};
|
|
(
|
|
[$proj_ty_ident:ident]
|
|
[$proj_vis:vis struct]
|
|
[$__pin_project_make_proj_field:ident]
|
|
[$($impl_generics:tt)*] [$($ty_generics:tt)*] [$(where $($where_clause:tt)*)?]
|
|
{
|
|
$(
|
|
$(#[$pin:ident])?
|
|
$field_vis:vis $field:ident: $field_ty:ty
|
|
),+ $(,)?
|
|
}
|
|
) => {
|
|
$crate::__pin_project_make_proj_replace_ty_body! {
|
|
[$proj_ty_ident]
|
|
[$proj_vis struct]
|
|
[$($impl_generics)*] [$($ty_generics)*] [$(where $($where_clause)*)?]
|
|
[
|
|
$(
|
|
$field_vis $field: $crate::$__pin_project_make_proj_field!(
|
|
$(#[$pin])? $field_ty
|
|
)
|
|
),+
|
|
]
|
|
}
|
|
};
|
|
(
|
|
[$proj_ty_ident:ident]
|
|
[$proj_vis:vis enum]
|
|
[$__pin_project_make_proj_field:ident]
|
|
[$($impl_generics:tt)*] [$($ty_generics:tt)*] [$(where $($where_clause:tt)*)?]
|
|
{
|
|
$(
|
|
$(#[$variant_attrs:meta])*
|
|
$variant:ident $({
|
|
$(
|
|
$(#[$pin:ident])?
|
|
$field:ident: $field_ty:ty
|
|
),+ $(,)?
|
|
})?
|
|
),+ $(,)?
|
|
}
|
|
) => {
|
|
$crate::__pin_project_make_proj_replace_ty_body! {
|
|
[$proj_ty_ident]
|
|
[$proj_vis enum]
|
|
[$($impl_generics)*] [$($ty_generics)*] [$(where $($where_clause)*)?]
|
|
[
|
|
$(
|
|
$variant $({
|
|
$(
|
|
$field: $crate::$__pin_project_make_proj_field!(
|
|
$(#[$pin])? $field_ty
|
|
)
|
|
),+
|
|
})?
|
|
),+
|
|
]
|
|
}
|
|
};
|
|
}
|
|
|
|
#[doc(hidden)]
|
|
#[macro_export]
|
|
macro_rules! __pin_project_make_proj_replace_ty_body {
|
|
(
|
|
[$proj_ty_ident:ident]
|
|
[$proj_vis:vis $struct_ty_ident:ident]
|
|
[$($impl_generics:tt)*] [$($ty_generics:tt)*] [$(where $($where_clause:tt)*)?]
|
|
[$($body_data:tt)+]
|
|
) => {
|
|
#[allow(dead_code)] // This lint warns unused fields/variants.
|
|
#[allow(single_use_lifetimes)] // https://github.com/rust-lang/rust/issues/55058
|
|
#[allow(clippy::mut_mut)] // This lint warns `&mut &mut <ty>`. (only needed for project)
|
|
#[allow(clippy::redundant_pub_crate)] // This lint warns `pub(crate)` field in private struct.
|
|
#[allow(clippy::type_repetition_in_bounds)] // https://github.com/rust-lang/rust-clippy/issues/4326
|
|
$proj_vis $struct_ty_ident $proj_ty_ident <$($impl_generics)*>
|
|
where
|
|
$($($where_clause)*)?
|
|
{
|
|
$($body_data)+
|
|
}
|
|
};
|
|
}
|
|
|
|
#[doc(hidden)]
|
|
#[macro_export]
|
|
macro_rules! __pin_project_make_proj_replace_block {
|
|
(
|
|
[$($proj_path:tt)+]
|
|
{
|
|
$(
|
|
$(#[$pin:ident])?
|
|
$field_vis:vis $field:ident
|
|
),+
|
|
}
|
|
) => {
|
|
let result = $($proj_path)* {
|
|
$(
|
|
$field: $crate::__pin_project_make_replace_field_proj!(
|
|
$(#[$pin])? $field
|
|
)
|
|
),+
|
|
};
|
|
|
|
{
|
|
( $(
|
|
$crate::__pin_project_make_unsafe_drop_in_place_guard!(
|
|
$(#[$pin])? $field
|
|
),
|
|
)* );
|
|
}
|
|
|
|
result
|
|
};
|
|
([$($proj_path:tt)+]) => { $($proj_path)* };
|
|
}
|
|
|
|
#[doc(hidden)]
|
|
#[macro_export]
|
|
macro_rules! __pin_project_struct_make_proj_method {
|
|
([] $($variant:tt)*) => {};
|
|
(
|
|
[$proj_ty_ident:ident $_ignored_default_arg:ident]
|
|
[$proj_vis:vis]
|
|
[$method_ident:ident $get_method:ident $($mut:ident)?]
|
|
[$($ty_generics:tt)*]
|
|
$($variant:tt)*
|
|
) => {
|
|
$crate::__pin_project_struct_make_proj_method! {
|
|
[$proj_ty_ident]
|
|
[$proj_vis]
|
|
[$method_ident $get_method $($mut)?]
|
|
[$($ty_generics)*]
|
|
$($variant)*
|
|
}
|
|
};
|
|
(
|
|
[$proj_ty_ident:ident]
|
|
[$proj_vis:vis]
|
|
[$method_ident:ident $get_method:ident $($mut:ident)?]
|
|
[$($ty_generics:tt)*]
|
|
{
|
|
$(
|
|
$(#[$pin:ident])?
|
|
$field_vis:vis $field:ident
|
|
),+
|
|
}
|
|
) => {
|
|
$proj_vis fn $method_ident<'__pin>(
|
|
self: $crate::__private::Pin<&'__pin $($mut)? Self>,
|
|
) -> $proj_ty_ident <'__pin, $($ty_generics)*> {
|
|
unsafe {
|
|
let Self { $($field),* } = self.$get_method();
|
|
$proj_ty_ident {
|
|
$(
|
|
$field: $crate::__pin_project_make_unsafe_field_proj!(
|
|
$(#[$pin])? $field
|
|
)
|
|
),+
|
|
}
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
#[doc(hidden)]
|
|
#[macro_export]
|
|
macro_rules! __pin_project_struct_make_proj_replace_method {
|
|
([] $($field:tt)*) => {};
|
|
(
|
|
[$proj_ty_ident:ident]
|
|
[$proj_vis:vis]
|
|
[$_proj_ty_ident:ident]
|
|
[$($ty_generics:tt)*]
|
|
{
|
|
$(
|
|
$(#[$pin:ident])?
|
|
$field_vis:vis $field:ident
|
|
),+
|
|
}
|
|
) => {
|
|
$proj_vis fn project_replace(
|
|
self: $crate::__private::Pin<&mut Self>,
|
|
replacement: Self,
|
|
) -> $proj_ty_ident <$($ty_generics)*> {
|
|
unsafe {
|
|
let __self_ptr: *mut Self = self.get_unchecked_mut();
|
|
|
|
// Destructors will run in reverse order, so next create a guard to overwrite
|
|
// `self` with the replacement value without calling destructors.
|
|
let __guard = $crate::__private::UnsafeOverwriteGuard::new(__self_ptr, replacement);
|
|
|
|
let Self { $($field),* } = &mut *__self_ptr;
|
|
|
|
$crate::__pin_project_make_proj_replace_block! {
|
|
[$proj_ty_ident]
|
|
{
|
|
$(
|
|
$(#[$pin])?
|
|
$field
|
|
),+
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
#[doc(hidden)]
|
|
#[macro_export]
|
|
macro_rules! __pin_project_enum_make_proj_method {
|
|
([] $($variant:tt)*) => {};
|
|
(
|
|
[$proj_ty_ident:ident]
|
|
[$proj_vis:vis]
|
|
[$method_ident:ident $get_method:ident $($mut:ident)?]
|
|
[$($ty_generics:tt)*]
|
|
{
|
|
$(
|
|
$variant:ident $({
|
|
$(
|
|
$(#[$pin:ident])?
|
|
$field:ident
|
|
),+
|
|
})?
|
|
),+
|
|
}
|
|
) => {
|
|
$proj_vis fn $method_ident<'__pin>(
|
|
self: $crate::__private::Pin<&'__pin $($mut)? Self>,
|
|
) -> $proj_ty_ident <'__pin, $($ty_generics)*> {
|
|
unsafe {
|
|
match self.$get_method() {
|
|
$(
|
|
Self::$variant $({
|
|
$($field),+
|
|
})? => {
|
|
$proj_ty_ident::$variant $({
|
|
$(
|
|
$field: $crate::__pin_project_make_unsafe_field_proj!(
|
|
$(#[$pin])? $field
|
|
)
|
|
),+
|
|
})?
|
|
}
|
|
),+
|
|
}
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
#[doc(hidden)]
|
|
#[macro_export]
|
|
macro_rules! __pin_project_enum_make_proj_replace_method {
|
|
([] $($field:tt)*) => {};
|
|
(
|
|
[$proj_ty_ident:ident]
|
|
[$proj_vis:vis]
|
|
[$($ty_generics:tt)*]
|
|
{
|
|
$(
|
|
$variant:ident $({
|
|
$(
|
|
$(#[$pin:ident])?
|
|
$field:ident
|
|
),+
|
|
})?
|
|
),+
|
|
}
|
|
) => {
|
|
$proj_vis fn project_replace(
|
|
self: $crate::__private::Pin<&mut Self>,
|
|
replacement: Self,
|
|
) -> $proj_ty_ident <$($ty_generics)*> {
|
|
unsafe {
|
|
let __self_ptr: *mut Self = self.get_unchecked_mut();
|
|
|
|
// Destructors will run in reverse order, so next create a guard to overwrite
|
|
// `self` with the replacement value without calling destructors.
|
|
let __guard = $crate::__private::UnsafeOverwriteGuard::new(__self_ptr, replacement);
|
|
|
|
match &mut *__self_ptr {
|
|
$(
|
|
Self::$variant $({
|
|
$($field),+
|
|
})? => {
|
|
$crate::__pin_project_make_proj_replace_block! {
|
|
[$proj_ty_ident :: $variant]
|
|
$({
|
|
$(
|
|
$(#[$pin])?
|
|
$field
|
|
),+
|
|
})?
|
|
}
|
|
}
|
|
),+
|
|
}
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
#[doc(hidden)]
|
|
#[macro_export]
|
|
macro_rules! __pin_project_make_unpin_impl {
|
|
(
|
|
[$vis:vis $ident:ident]
|
|
[$($impl_generics:tt)*] [$($ty_generics:tt)*] [$(where $($where_clause:tt)*)?]
|
|
$($field:tt)*
|
|
) => {
|
|
// Automatically create the appropriate conditional `Unpin` implementation.
|
|
//
|
|
// Basically this is equivalent to the following code:
|
|
// ```rust
|
|
// impl<T, U> Unpin for Struct<T, U> where T: Unpin {}
|
|
// ```
|
|
//
|
|
// However, if struct is public and there is a private type field,
|
|
// this would cause an E0446 (private type in public interface).
|
|
//
|
|
// When RFC 2145 is implemented (rust-lang/rust#48054),
|
|
// this will become a lint, rather then a hard error.
|
|
//
|
|
// As a workaround for this, we generate a new struct, containing all of the pinned
|
|
// fields from our #[pin_project] type. This struct is declared within
|
|
// a function, which makes it impossible to be named by user code.
|
|
// This guarantees that it will use the default auto-trait impl for Unpin -
|
|
// that is, it will implement Unpin iff all of its fields implement Unpin.
|
|
// This type can be safely declared as 'public', satisfying the privacy
|
|
// checker without actually allowing user code to access it.
|
|
//
|
|
// This allows users to apply the #[pin_project] attribute to types
|
|
// regardless of the privacy of the types of their fields.
|
|
//
|
|
// See also https://github.com/taiki-e/pin-project/pull/53.
|
|
#[allow(non_snake_case)]
|
|
$vis struct __Origin <'__pin, $($impl_generics)*>
|
|
$(where
|
|
$($where_clause)*)?
|
|
{
|
|
__dummy_lifetime: $crate::__private::PhantomData<&'__pin ()>,
|
|
$($field)*
|
|
}
|
|
impl <'__pin, $($impl_generics)*> $crate::__private::Unpin for $ident <$($ty_generics)*>
|
|
where
|
|
__Origin <'__pin, $($ty_generics)*>: $crate::__private::Unpin
|
|
$(, $($where_clause)*)?
|
|
{
|
|
}
|
|
};
|
|
}
|
|
|
|
#[doc(hidden)]
|
|
#[macro_export]
|
|
macro_rules! __pin_project_make_drop_impl {
|
|
(
|
|
[$_ident:ident]
|
|
[$($_impl_generics:tt)*] [$($_ty_generics:tt)*] [$(where $($_where_clause:tt)*)?]
|
|
impl $(<
|
|
$( $lifetime:lifetime $(: $lifetime_bound:lifetime)? ),* $(,)?
|
|
$( $generics:ident
|
|
$(: $generics_bound:path)?
|
|
$(: ?$generics_unsized_bound:path)?
|
|
$(: $generics_lifetime_bound:lifetime)?
|
|
),*
|
|
>)? PinnedDrop for $self_ty:ty
|
|
$(where
|
|
$( $where_clause_ty:ty
|
|
$(: $where_clause_bound:path)?
|
|
$(: ?$where_clause_unsized_bound:path)?
|
|
$(: $where_clause_lifetime_bound:lifetime)?
|
|
),* $(,)?
|
|
)?
|
|
{
|
|
fn drop($($arg:ident)+: Pin<&mut Self>) {
|
|
$($tt:tt)*
|
|
}
|
|
}
|
|
) => {
|
|
impl $(<
|
|
$( $lifetime $(: $lifetime_bound)? ,)*
|
|
$( $generics
|
|
$(: $generics_bound)?
|
|
$(: ?$generics_unsized_bound)?
|
|
$(: $generics_lifetime_bound)?
|
|
),*
|
|
>)? $crate::__private::Drop for $self_ty
|
|
$(where
|
|
$( $where_clause_ty
|
|
$(: $where_clause_bound)?
|
|
$(: ?$where_clause_unsized_bound)?
|
|
$(: $where_clause_lifetime_bound)?
|
|
),*
|
|
)?
|
|
{
|
|
fn drop(&mut self) {
|
|
// Implementing `__DropInner::__drop_inner` is safe, but calling it is not safe.
|
|
// This is because destructors can be called multiple times in safe code and
|
|
// [double dropping is unsound](https://github.com/rust-lang/rust/pull/62360).
|
|
//
|
|
// `__drop_inner` is defined as a safe method, but this is fine since
|
|
// `__drop_inner` is not accessible by the users and we call `__drop_inner` only
|
|
// once.
|
|
//
|
|
// Users can implement [`Drop`] safely using `pin_project!` and can drop a
|
|
// type that implements `PinnedDrop` using the [`drop`] function safely.
|
|
fn __drop_inner $(<
|
|
$( $lifetime $(: $lifetime_bound)? ,)*
|
|
$( $generics
|
|
$(: $generics_bound)?
|
|
$(: ?$generics_unsized_bound)?
|
|
$(: $generics_lifetime_bound)?
|
|
),*
|
|
>)? (
|
|
$($arg)+: $crate::__private::Pin<&mut $self_ty>,
|
|
)
|
|
$(where
|
|
$( $where_clause_ty
|
|
$(: $where_clause_bound)?
|
|
$(: ?$where_clause_unsized_bound)?
|
|
$(: $where_clause_lifetime_bound)?
|
|
),*
|
|
)?
|
|
{
|
|
// A dummy `__drop_inner` function to prevent users call outer `__drop_inner`.
|
|
fn __drop_inner() {}
|
|
$($tt)*
|
|
}
|
|
|
|
// Safety - we're in 'drop', so we know that 'self' will
|
|
// never move again.
|
|
let pinned_self: $crate::__private::Pin<&mut Self>
|
|
= unsafe { $crate::__private::Pin::new_unchecked(self) };
|
|
// We call `__drop_inner` only once. Since `__DropInner::__drop_inner`
|
|
// is not accessible by the users, it is never called again.
|
|
__drop_inner(pinned_self);
|
|
}
|
|
}
|
|
};
|
|
(
|
|
[$ident:ident]
|
|
[$($impl_generics:tt)*] [$($ty_generics:tt)*] [$(where $($where_clause:tt)*)?]
|
|
) => {
|
|
// Ensure that struct does not implement `Drop`.
|
|
//
|
|
// There are two possible cases:
|
|
// 1. The user type does not implement Drop. In this case,
|
|
// the first blanked impl will not apply to it. This code
|
|
// will compile, as there is only one impl of MustNotImplDrop for the user type
|
|
// 2. The user type does impl Drop. This will make the blanket impl applicable,
|
|
// which will then conflict with the explicit MustNotImplDrop impl below.
|
|
// This will result in a compilation error, which is exactly what we want.
|
|
trait MustNotImplDrop {}
|
|
#[allow(clippy::drop_bounds, drop_bounds)]
|
|
impl<T: $crate::__private::Drop> MustNotImplDrop for T {}
|
|
impl <$($impl_generics)*> MustNotImplDrop for $ident <$($ty_generics)*>
|
|
$(where
|
|
$($where_clause)*)?
|
|
{
|
|
}
|
|
};
|
|
}
|
|
|
|
#[doc(hidden)]
|
|
#[macro_export]
|
|
macro_rules! __pin_project_make_unpin_bound {
|
|
(#[pin] $field_ty:ty) => {
|
|
$field_ty
|
|
};
|
|
($field_ty:ty) => {
|
|
$crate::__private::AlwaysUnpin<$field_ty>
|
|
};
|
|
}
|
|
|
|
#[doc(hidden)]
|
|
#[macro_export]
|
|
macro_rules! __pin_project_make_unsafe_field_proj {
|
|
(#[pin] $field:ident) => {
|
|
$crate::__private::Pin::new_unchecked($field)
|
|
};
|
|
($field:ident) => {
|
|
$field
|
|
};
|
|
}
|
|
|
|
#[doc(hidden)]
|
|
#[macro_export]
|
|
macro_rules! __pin_project_make_replace_field_proj {
|
|
(#[pin] $field:ident) => {
|
|
$crate::__private::PhantomData
|
|
};
|
|
($field:ident) => {
|
|
$crate::__private::ptr::read($field)
|
|
};
|
|
}
|
|
|
|
#[doc(hidden)]
|
|
#[macro_export]
|
|
macro_rules! __pin_project_make_unsafe_drop_in_place_guard {
|
|
(#[pin] $field:ident) => {
|
|
$crate::__private::UnsafeDropInPlaceGuard::new($field)
|
|
};
|
|
($field:ident) => {
|
|
()
|
|
};
|
|
}
|
|
|
|
#[doc(hidden)]
|
|
#[macro_export]
|
|
macro_rules! __pin_project_make_proj_field_mut {
|
|
(#[pin] $field_ty:ty) => {
|
|
$crate::__private::Pin<&'__pin mut ($field_ty)>
|
|
};
|
|
($field_ty:ty) => {
|
|
&'__pin mut ($field_ty)
|
|
};
|
|
}
|
|
|
|
#[doc(hidden)]
|
|
#[macro_export]
|
|
macro_rules! __pin_project_make_proj_field_ref {
|
|
(#[pin] $field_ty:ty) => {
|
|
$crate::__private::Pin<&'__pin ($field_ty)>
|
|
};
|
|
($field_ty:ty) => {
|
|
&'__pin ($field_ty)
|
|
};
|
|
}
|
|
|
|
#[doc(hidden)]
|
|
#[macro_export]
|
|
macro_rules! __pin_project_make_proj_field_replace {
|
|
(#[pin] $field_ty:ty) => {
|
|
$crate::__private::PhantomData<$field_ty>
|
|
};
|
|
($field_ty:ty) => {
|
|
$field_ty
|
|
};
|
|
}
|
|
|
|
#[doc(hidden)]
|
|
#[macro_export]
|
|
macro_rules! __pin_project_internal {
|
|
// parsing proj_mut_ident
|
|
(
|
|
[]
|
|
[$($proj_ref_ident:ident)?]
|
|
[$($proj_replace_ident:ident)?]
|
|
[$($attrs:tt)*]
|
|
|
|
#[project = $proj_mut_ident:ident]
|
|
$($tt:tt)*
|
|
) => {
|
|
$crate::__pin_project_internal! {
|
|
[$proj_mut_ident]
|
|
[$($proj_ref_ident)?]
|
|
[$($proj_replace_ident)?]
|
|
[$($attrs)*]
|
|
$($tt)*
|
|
}
|
|
};
|
|
// parsing proj_ref_ident
|
|
(
|
|
[$($proj_mut_ident:ident)?]
|
|
[]
|
|
[$($proj_replace_ident:ident)?]
|
|
[$($attrs:tt)*]
|
|
|
|
#[project_ref = $proj_ref_ident:ident]
|
|
$($tt:tt)*
|
|
) => {
|
|
$crate::__pin_project_internal! {
|
|
[$($proj_mut_ident)?]
|
|
[$proj_ref_ident]
|
|
[$($proj_replace_ident)?]
|
|
[$($attrs)*]
|
|
$($tt)*
|
|
}
|
|
};
|
|
// parsing proj_replace_ident
|
|
(
|
|
[$($proj_mut_ident:ident)?]
|
|
[$($proj_ref_ident:ident)?]
|
|
[]
|
|
[$($attrs:tt)*]
|
|
|
|
#[project_replace = $proj_replace_ident:ident]
|
|
$($tt:tt)*
|
|
) => {
|
|
$crate::__pin_project_internal! {
|
|
[$($proj_mut_ident)?]
|
|
[$($proj_ref_ident)?]
|
|
[$proj_replace_ident]
|
|
[$($attrs)*]
|
|
$($tt)*
|
|
}
|
|
};
|
|
// this is actually part of a recursive step that picks off a single non-`pin_project_lite` attribute
|
|
// there could be more to parse
|
|
(
|
|
[$($proj_mut_ident:ident)?]
|
|
[$($proj_ref_ident:ident)?]
|
|
[$($proj_replace_ident:ident)?]
|
|
[$($attrs:tt)*]
|
|
|
|
#[$($attr:tt)*]
|
|
$($tt:tt)*
|
|
) => {
|
|
$crate::__pin_project_internal! {
|
|
[$($proj_mut_ident)?]
|
|
[$($proj_ref_ident)?]
|
|
[$($proj_replace_ident)?]
|
|
[$($attrs)* #[$($attr)*]]
|
|
$($tt)*
|
|
}
|
|
};
|
|
// now determine visibility
|
|
// if public, downgrade
|
|
(
|
|
[$($proj_mut_ident:ident)?]
|
|
[$($proj_ref_ident:ident)?]
|
|
[$($proj_replace_ident:ident)?]
|
|
[$($attrs:tt)*]
|
|
pub $struct_ty_ident:ident $ident:ident
|
|
$($tt:tt)*
|
|
) => {
|
|
$crate::__pin_project_parse_generics! {
|
|
[$($proj_mut_ident)?]
|
|
[$($proj_ref_ident)?]
|
|
[$($proj_replace_ident)?]
|
|
[$($attrs)*]
|
|
[pub $struct_ty_ident $ident pub(crate)]
|
|
$($tt)*
|
|
}
|
|
};
|
|
(
|
|
[$($proj_mut_ident:ident)?]
|
|
[$($proj_ref_ident:ident)?]
|
|
[$($proj_replace_ident:ident)?]
|
|
[$($attrs:tt)*]
|
|
$vis:vis $struct_ty_ident:ident $ident:ident
|
|
$($tt:tt)*
|
|
) => {
|
|
$crate::__pin_project_parse_generics! {
|
|
[$($proj_mut_ident)?]
|
|
[$($proj_ref_ident)?]
|
|
[$($proj_replace_ident)?]
|
|
[$($attrs)*]
|
|
[$vis $struct_ty_ident $ident $vis]
|
|
$($tt)*
|
|
}
|
|
};
|
|
}
|
|
|
|
#[doc(hidden)]
|
|
#[macro_export]
|
|
macro_rules! __pin_project_parse_generics {
|
|
(
|
|
[$($proj_mut_ident:ident)?]
|
|
[$($proj_ref_ident:ident)?]
|
|
[$($proj_replace_ident:ident)?]
|
|
[$($attrs:tt)*]
|
|
[$vis:vis $struct_ty_ident:ident $ident:ident $proj_ty_vis:vis]
|
|
$(<
|
|
$( $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)?
|
|
$(: ?$where_clause_unsized_bound:path)?
|
|
$(: $where_clause_lifetime_bound:lifetime)?
|
|
),* $(,)?
|
|
)?
|
|
{
|
|
$($body_data:tt)*
|
|
}
|
|
$(impl $($pinned_drop:tt)*)?
|
|
) => {
|
|
$crate::__pin_project_expand! {
|
|
[$($proj_mut_ident)?]
|
|
[$($proj_ref_ident)?]
|
|
[$($proj_replace_ident)?]
|
|
[$proj_ty_vis]
|
|
[$($attrs)* $vis $struct_ty_ident $ident]
|
|
[$(<
|
|
$( $lifetime $(: $lifetime_bound)? ,)*
|
|
$( $generics
|
|
$(: $generics_bound)?
|
|
$(: ?$generics_unsized_bound)?
|
|
$(: $generics_lifetime_bound)?
|
|
$(= $generics_default)?
|
|
),*
|
|
>)?]
|
|
[$(
|
|
$( $lifetime $(: $lifetime_bound)? ,)*
|
|
$( $generics
|
|
$(: $generics_bound)?
|
|
$(: ?$generics_unsized_bound)?
|
|
$(: $generics_lifetime_bound)?
|
|
),*
|
|
)?]
|
|
[$( $( $lifetime ,)* $( $generics ),* )?]
|
|
[$(where $( $where_clause_ty
|
|
$(: $where_clause_bound)?
|
|
$(: ?$where_clause_unsized_bound)?
|
|
$(: $where_clause_lifetime_bound)?
|
|
),* )?]
|
|
{
|
|
$($body_data)*
|
|
}
|
|
$(impl $($pinned_drop)*)?
|
|
}
|
|
};
|
|
}
|
|
|
|
#[doc(hidden)]
|
|
pub mod __private {
|
|
use core::mem::ManuallyDrop;
|
|
#[doc(hidden)]
|
|
pub use core::{
|
|
marker::{PhantomData, Unpin},
|
|
ops::Drop,
|
|
pin::Pin,
|
|
ptr,
|
|
};
|
|
|
|
// This is an internal helper struct used by `pin_project!`.
|
|
#[doc(hidden)]
|
|
pub struct AlwaysUnpin<T: ?Sized>(PhantomData<T>);
|
|
|
|
impl<T: ?Sized> Unpin for AlwaysUnpin<T> {}
|
|
|
|
// This is an internal helper used to ensure a value is dropped.
|
|
#[doc(hidden)]
|
|
pub struct UnsafeDropInPlaceGuard<T: ?Sized>(*mut T);
|
|
|
|
impl<T: ?Sized> UnsafeDropInPlaceGuard<T> {
|
|
#[doc(hidden)]
|
|
pub unsafe fn new(ptr: *mut T) -> Self {
|
|
Self(ptr)
|
|
}
|
|
}
|
|
|
|
impl<T: ?Sized> Drop for UnsafeDropInPlaceGuard<T> {
|
|
fn drop(&mut self) {
|
|
unsafe {
|
|
ptr::drop_in_place(self.0);
|
|
}
|
|
}
|
|
}
|
|
|
|
// This is an internal helper used to ensure a value is overwritten without
|
|
// its destructor being called.
|
|
#[doc(hidden)]
|
|
pub struct UnsafeOverwriteGuard<T> {
|
|
target: *mut T,
|
|
value: ManuallyDrop<T>,
|
|
}
|
|
|
|
impl<T> UnsafeOverwriteGuard<T> {
|
|
#[doc(hidden)]
|
|
pub unsafe fn new(target: *mut T, value: T) -> Self {
|
|
Self { target, value: ManuallyDrop::new(value) }
|
|
}
|
|
}
|
|
|
|
impl<T> Drop for UnsafeOverwriteGuard<T> {
|
|
fn drop(&mut self) {
|
|
unsafe {
|
|
ptr::write(self.target, ptr::read(&*self.value));
|
|
}
|
|
}
|
|
}
|
|
}
|