diff --git a/CHANGELOG.md b/CHANGELOG.md index ad680de3..3599bd55 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,21 @@ # Unreleased +# 0.4.0-alpha.1 - 2019-08-11 + +* **Pin projection has become a safe operation.** + +* `#[unsafe_project]` has been replaced with `#[pin_project]`. + +* The `Unpin` argument has been removed - an `Unpin` impl is now generated by default. + +* Drop impls must be specified with `#[pinned_drop]` instead of via a normal `Drop` impl. + +* `Unpin` impls must be specified with an impl of `UnsafeUnpin`, instead of implementing the normal `Unpin` trait. + +* Made `#[project]` attribute disabled by default. + +See also [tracking issue for 0.4 release](https://github.com/taiki-e/pin-project/issues/21). + # 0.3.4 - 2019-07-21 * Improved error messages. diff --git a/Cargo.toml b/Cargo.toml index ecc350b9..5b0f3b56 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,11 +1,11 @@ [package] name = "pin-project" # NB: When modifying, also modify html_root_url in lib.rs -version = "0.3.4" +version = "0.4.0-alpha.1" authors = ["Taiki Endo "] edition = "2018" license = "Apache-2.0/MIT" -description = "An attribute that creates a projection struct covering all the fields." +description = "A crate for safe and ergonomic pin-projection." repository = "https://github.com/taiki-e/pin-project" documentation = "https://docs.rs/pin-project/" readme = "README.md" @@ -22,7 +22,10 @@ project_attr = ["pin-project-internal/project_attr"] renamed = ["pin-project-internal/renamed"] [dependencies] -pin-project-internal = { version = "0.3.4", path = "pin-project-internal", default-features = false } +pin-project-internal = { version = "=0.4.0-alpha.1", path = "pin-project-internal", default-features = false } [dev-dependencies] compiletest = { version = "0.3.21", package = "compiletest_rs", features = ["stable", "tmp"] } + +[package.metadata.docs.rs] +all-features = true diff --git a/README.md b/README.md index 982a0ccc..50b9a94f 100644 --- a/README.md +++ b/README.md @@ -27,10 +27,10 @@ Add this to your `Cargo.toml`: ```toml [dependencies] -pin-project = "0.3" +pin-project = "0.4.0-alpha.1" ``` -The current version of pin-project requires Rust 1.33 or later. +The current pin-project requires Rust 1.33 or later. ## Examples @@ -58,7 +58,7 @@ impl Foo { [Code like this will be generated](doc/struct-example-1.md) -[`pin_project`]: https://docs.rs/pin-project/0.3/pin_project/attr.pin_project.html +[`pin_project`]: https://docs.rs/pin-project/0.4.0-alpha.1/pin_project/attr.pin_project.html ## License diff --git a/pin-project-internal/Cargo.toml b/pin-project-internal/Cargo.toml index e62068a9..d2fec65c 100644 --- a/pin-project-internal/Cargo.toml +++ b/pin-project-internal/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "pin-project-internal" # NB: When modifying, also modify html_root_url in lib.rs -version = "0.3.4" +version = "0.4.0-alpha.1" authors = ["Taiki Endo "] edition = "2018" license = "Apache-2.0/MIT" @@ -29,3 +29,9 @@ proc-macro-crate = { version = "0.1.4", optional = true } # and proc-macro-crate updates to that new version of toml-rs. serde = { version = "1.0.97", optional = true } lazy_static = { version = "1.3.0", optional = true } + +[dev-dependencies] +pin-project = { version = "=0.4.0-alpha.1", path = ".." } + +[package.metadata.docs.rs] +all-features = true diff --git a/pin-project-internal/src/lib.rs b/pin-project-internal/src/lib.rs index e42890fe..b734e37f 100644 --- a/pin-project-internal/src/lib.rs +++ b/pin-project-internal/src/lib.rs @@ -1,5 +1,7 @@ +//! An interal crate to support pin_project - **do not use directly** + #![recursion_limit = "256"] -#![doc(html_root_url = "https://docs.rs/pin-project-internal/0.3.3")] +#![doc(html_root_url = "https://docs.rs/pin-project-internal/0.4.0-alpha.1")] #![doc(test(attr(deny(warnings), allow(dead_code, unused_assignments, unused_variables))))] #![warn(unsafe_code)] #![warn(rust_2018_idioms, unreachable_pub)] @@ -18,20 +20,373 @@ mod pinned_drop; mod project; use proc_macro::TokenStream; - use utils::Nothing; +// TODO: Move this doc into pin-project crate when https://github.com/rust-lang/rust/pull/62855 merged. +/// An attribute that creates a projection struct covering all the fields. +/// +/// This attribute 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. +/// +/// ## Safety +/// +/// This attribute is completely safe. In the absence of other `unsafe` code *that you write*, +/// it is impossible to cause undefined behavior with this attribute. +/// +/// This is accomplished by enforcing the four requirements for pin projection +/// stated in [the Rust documentation](https://doc.rust-lang.org/beta/std/pin/index.html#projections-and-structural-pinning): +/// +/// 1. The struct must only be Unpin if all the structural fields are Unpin +/// +/// To enforce this, this attribute will automatically generate an `Unpin` implementation +/// for you, which will require that all structurally pinned fields be `Unpin` +/// If you wish to provide an manual `Unpin` impl, you can do so via the +/// `UnsafeUnpin` argument. +/// +/// 2. The destructor of the struct must not move structural fields out of its argument. +/// +/// To enforce this, this attribute will automatically generate a `Drop` impl. +/// If you wish to provide a custom `Drop` impl, you can annotate a function +/// with `#[pinned_drop]`. This function takes a pinned version of your struct - +/// that is, `Pin<&mut MyStruct>` where `MyStruct` is the type of your struct. +/// +/// You can call `project()` on this type as usual, along with any other +/// methods you have defined. Because your code is never provided with +/// a `&mut MyStruct`, it is impossible to move out of pin-projectable +/// fields in safe code in your destructor. +/// +/// 3. You must make sure that you uphold the Drop guarantee: once your struct is pinned, +/// the memory that contains the content is not overwritten or deallocated without calling the content's destructors +/// +/// Safe code doesn't need to worry about this - the only wait to violate this requirement +/// is to manually deallocate memory (which is `unsafe`), or to overwite a field with something else. +/// Becauese your custom destructor takes `Pin<&mut MyStruct`, it's impossible to obtain +/// a mutable reference to a pin-projected field in safe code. +/// +/// 4. You must not offer any other operations that could lead to data being moved out of the structural fields when your type is pinned. +/// +/// As with requirement 3, it is impossible for safe code to violate this. This crate ensures that safe code can never +/// obtain a mutable reference to `#[pin]` fields, which prevents you from ever moving out of them in safe code. +/// +/// Pin projections are also incompatible with `#[repr(packed)]` structs. Attempting to use this attribute +/// on a `#[repr(packed)]` struct results in a compile-time error. +/// +/// +/// ## Examples +/// +/// Using `#[pin_project]` will automatically create the appropriate +/// conditional [`Unpin`] implementation: +/// +/// ```rust +/// use pin_project::pin_project; +/// use std::pin::Pin; +/// +/// #[pin_project] +/// struct Foo { +/// #[pin] +/// future: T, +/// field: U, +/// } +/// +/// impl Foo { +/// fn baz(self: Pin<&mut Self>) { +/// let this = self.project(); +/// let _: Pin<&mut T> = this.future; // Pinned reference to the field +/// let _: &mut U = this.field; // Normal reference to the field +/// } +/// } +/// ``` +/// +/// If you want to implement [`Unpin`] manually, you must use the `UnsafeUnpin` +/// argument to `#[pin_project]`. +/// +/// ```rust +/// use pin_project::{pin_project, UnsafeUnpin}; +/// use std::pin::Pin; +/// +/// #[pin_project(UnsafeUnpin)] +/// struct Foo { +/// #[pin] +/// future: T, +/// field: U, +/// } +/// +/// impl Foo { +/// fn baz(self: Pin<&mut Self>) { +/// let this = self.project(); +/// let _: Pin<&mut T> = this.future; // Pinned reference to the field +/// let _: &mut U = this.field; // Normal reference to the field +/// } +/// } +/// +/// unsafe impl UnsafeUnpin for Foo {} // Conditional Unpin impl +/// ``` +/// +/// Note the usage of the unsafe [`UnsafeUnpin`] trait, instead of the usual +/// [`Unpin`] trait. [`UnsafeUnpin`] behaves exactly like [`Unpin`], except that is +/// unsafe to implement. This unsafety comes from the fact that pin projections +/// are being used. If you implement [`UnsafeUnpin`], you must ensure that it is +/// only implemented when all pin-projected fields implement [`Unpin`]. +/// +/// Note that borrowing the field where `#[pin]` attribute is used multiple +/// times requires using [`.as_mut()`][`Pin::as_mut`] to avoid +/// consuming the `Pin`. +/// +/// ### `#[pinned_drop]` +/// +/// In order to correctly implement pin projections, a type's `Drop` impl must +/// not move out of any stucturally pinned fields. Unfortunately, [`Drop::drop`] +/// takes `&mut Self`, not `Pin<&mut Self>`. +/// +/// To ensure that this requirement is upheld, the `pin_project` attribute will +/// provide a `Drop` impl for you. This `Drop` impl will delegate to a function +/// annotated with `#[pinned_drop]` if you use the `PinnedDrop` argument to +/// `#[pin_project]`. This function acts just like a normal [`drop`] impl, except +/// for the fact that it takes `Pin<&mut Self>`. In particular, it will never be +/// called more than once, just like [`Drop::drop`]. +/// +/// For example: +/// +/// ```rust +/// use pin_project::{pin_project, pinned_drop}; +/// use std::fmt::Debug; +/// use std::pin::Pin; +/// +/// #[pin_project(PinnedDrop)] +/// pub struct Foo { +/// #[pin] pinned_field: T, +/// unpin_field: U +/// } +/// +/// #[pinned_drop] +/// fn my_drop_fn(foo: Pin<&mut Foo>) { +/// let foo = foo.project(); +/// println!("Dropping pinned field: {:?}", foo.pinned_field); +/// println!("Dropping unpin field: {:?}", foo.unpin_field); +/// } +/// +/// fn main() { +/// Foo { pinned_field: true, unpin_field: 40 }; +/// } +/// ``` +/// +/// See also [`pinned_drop`] attribute. +/// +/// ## Supported Items +/// +/// The current pin-project supports the following types of items. +/// +/// ### Structs (structs with named fields): +/// +/// ```rust +/// use pin_project::pin_project; +/// use std::pin::Pin; +/// +/// #[pin_project] +/// struct Foo { +/// #[pin] +/// future: T, +/// field: U, +/// } +/// +/// impl Foo { +/// fn baz(self: Pin<&mut Self>) { +/// let this = self.project(); +/// let _: Pin<&mut T> = this.future; +/// let _: &mut U = this.field; +/// } +/// } +/// ``` +/// +/// ### Tuple structs (structs with unnamed fields): +/// +/// ```rust +/// use pin_project::pin_project; +/// use std::pin::Pin; +/// +/// #[pin_project] +/// struct Foo(#[pin] T, U); +/// +/// impl Foo { +/// fn baz(self: Pin<&mut Self>) { +/// let this = self.project(); +/// let _: Pin<&mut T> = this.0; +/// let _: &mut U = this.1; +/// } +/// } +/// ``` +/// +/// Structs without fields (unit-like struct and zero fields struct) are not +/// supported. +/// +/// ### Enums +/// +/// `pin_project` also supports enums, but to use it ergonomically, you need +/// to use the [`project`] attribute. +/// +/// *This attribute is only available if pin-project is built +/// with the `"project_attr"` feature.* +/// +/// The attribute at the expression position is not stable, so you need to use +/// a dummy `#[project]` attribute for the function. +/// +/// ```rust +/// # #[cfg(feature = "project_attr")] +/// use pin_project::{project, pin_project}; +/// # #[cfg(feature = "project_attr")] +/// use std::pin::Pin; +/// +/// # #[cfg(feature = "project_attr")] +/// #[pin_project] +/// enum Foo { +/// Tuple(#[pin] A, B), +/// Struct { field: C }, +/// Unit, +/// } +/// +/// # #[cfg(feature = "project_attr")] +/// impl Foo { +/// #[project] // Nightly does not need a dummy attribute to the function. +/// fn baz(self: Pin<&mut Self>) { +/// #[project] +/// match self.project() { +/// Foo::Tuple(x, y) => { +/// let _: Pin<&mut A> = x; +/// let _: &mut B = y; +/// } +/// Foo::Struct { field } => { +/// let _: &mut C = field; +/// } +/// Foo::Unit => {} +/// } +/// } +/// } +/// ``` +/// +/// Enums without variants (zero-variant enums) are not supported. +/// +/// See also [`project`] attribute. +/// +/// [`Pin::as_mut`]: core::pin::Pin::as_mut +/// [`drop`]: Drop::drop +/// [`UnsafeUnpin`]: https://docs.rs/pin-project/0.4.0-alpha.1/pin_project/trait.UnsafeUnpin.html +/// [`project`]: ./attr.project.html +/// [`pinned_drop`]: ./attr.pinned_drop.html #[proc_macro_attribute] pub fn pin_project(args: TokenStream, input: TokenStream) -> TokenStream { pin_project::attribute(args.into(), input.into()).into() } +// TODO: Move this doc into pin-project crate when https://github.com/rust-lang/rust/pull/62855 merged. +/// An attribute for annotating a function that implements [`Drop`]. +/// +/// This attribute is only needed when you wish to provide a [`Drop`] +/// impl for your type. The function annotated with `#[pinned_drop]` acts just +/// like a normal [`drop`](Drop::drop) impl, except for the fact that it takes +/// `Pin<&mut Self>`. In particular, it will never be called more than once, +/// just like [`Drop::drop`]. +/// +/// Example: +/// +/// ```rust +/// use pin_project::{pin_project, pinned_drop}; +/// use std::pin::Pin; +/// +/// #[pin_project(PinnedDrop)] +/// struct Foo { +/// #[pin] field: u8 +/// } +/// +/// #[pinned_drop] +/// fn my_drop(foo: Pin<&mut Foo>) { +/// println!("Dropping: {}", foo.field); +/// } +/// +/// fn main() { +/// Foo { field: 50 }; +/// } +/// ``` +/// +/// See ["pinned-drop" section of `pin_project` attribute][pinned-drop] for more. +/// +/// [pinned-drop]: ./attr.pin_project.html#pinned_drop #[proc_macro_attribute] pub fn pinned_drop(args: TokenStream, input: TokenStream) -> TokenStream { let _: Nothing = syn::parse_macro_input!(args); pinned_drop::attribute(input.into()).into() } +// TODO: Move this doc into pin-project crate when https://github.com/rust-lang/rust/pull/62855 merged. +/// An attribute to support pattern matching. +/// +/// *This attribute is available if pin-project is built with the +/// `"project_attr"` feature.* +/// +/// The attribute at the expression position is not stable, so you need to use +/// a dummy `#[project]` attribute for the function. +/// +/// ## Examples +/// +/// The following two syntaxes are supported. +/// +/// ### `let` bindings +/// +/// ```rust +/// use pin_project::{pin_project, project}; +/// use std::pin::Pin; +/// +/// #[pin_project] +/// struct Foo { +/// #[pin] +/// future: T, +/// field: U, +/// } +/// +/// impl Foo { +/// #[project] // Nightly does not need a dummy attribute to the function. +/// fn baz(self: Pin<&mut Self>) { +/// #[project] +/// let Foo { future, field } = self.project(); +/// +/// let _: Pin<&mut T> = future; +/// let _: &mut U = field; +/// } +/// } +/// ``` +/// +/// ### `match` expressions +/// +/// ```rust +/// use pin_project::{project, pin_project}; +/// use std::pin::Pin; +/// +/// #[pin_project] +/// enum Foo { +/// Tuple(#[pin] A, B), +/// Struct { field: C }, +/// Unit, +/// } +/// +/// impl Foo { +/// #[project] // Nightly does not need a dummy attribute to the function. +/// fn baz(self: Pin<&mut Self>) { +/// #[project] +/// match self.project() { +/// Foo::Tuple(x, y) => { +/// let _: Pin<&mut A> = x; +/// let _: &mut B = y; +/// } +/// Foo::Struct { field } => { +/// let _: &mut C = field; +/// } +/// Foo::Unit => {} +/// } +/// } +/// } +/// ``` #[cfg(feature = "project_attr")] #[proc_macro_attribute] pub fn project(args: TokenStream, input: TokenStream) -> TokenStream { diff --git a/pin-project-internal/src/pin_project/enums.rs b/pin-project-internal/src/pin_project/enums.rs index ecb2bd6a..18a27069 100644 --- a/pin-project-internal/src/pin_project/enums.rs +++ b/pin-project-internal/src/pin_project/enums.rs @@ -2,9 +2,9 @@ use proc_macro2::{Ident, Span, TokenStream}; use quote::{quote, ToTokens}; use syn::{Field, Fields, FieldsNamed, FieldsUnnamed, ItemEnum, Result, Variant}; -use crate::utils::{proj_ident, VecExt}; +use crate::utils::{proj_ident, Nothing, VecExt}; -use super::*; +use super::{proj_generics, Args, ImplUnpin, PIN}; pub(super) fn parse(args: Args, mut item: ItemEnum) -> Result { let mut impl_unpin = args.impl_unpin(&item.generics); diff --git a/pin-project-internal/src/pin_project/mod.rs b/pin-project-internal/src/pin_project/mod.rs index f9e49626..f9f3922b 100644 --- a/pin-project-internal/src/pin_project/mod.rs +++ b/pin-project-internal/src/pin_project/mod.rs @@ -6,7 +6,7 @@ use syn::{ Result, Type, }; -use crate::utils::{crate_path, Nothing}; +use crate::utils::crate_path; mod enums; mod structs; diff --git a/pin-project-internal/src/pin_project/structs.rs b/pin-project-internal/src/pin_project/structs.rs index 17edc52a..12ae39a2 100644 --- a/pin-project-internal/src/pin_project/structs.rs +++ b/pin-project-internal/src/pin_project/structs.rs @@ -4,7 +4,7 @@ use syn::{Field, Fields, FieldsNamed, FieldsUnnamed, Index, ItemStruct, Result}; use crate::utils::{proj_ident, Nothing, VecExt}; -use super::*; +use super::{proj_generics, Args, ImplUnpin, PIN}; pub(super) fn parse(args: Args, mut item: ItemStruct) -> Result { let mut impl_unpin = args.impl_unpin(&item.generics); diff --git a/pin-project-internal/src/pinned_drop.rs b/pin-project-internal/src/pinned_drop.rs index 9764e022..929affcd 100644 --- a/pin-project-internal/src/pinned_drop.rs +++ b/pin-project-internal/src/pinned_drop.rs @@ -12,8 +12,7 @@ pub(super) fn attribute(input: TokenStream) -> TokenStream { } fn parse_arg(arg: &FnArg) -> Result<&Type> { - if let FnArg::Captured(ArgCaptured { ty: Type::Path(TypePath { qself: None, path }), .. }) = - &arg + if let FnArg::Captured(ArgCaptured { ty: Type::Path(TypePath { qself: None, path }), .. }) = arg { let ty = &path.segments[path.segments.len() - 1]; if let PathArguments::AngleBracketed(args) = &ty.arguments { diff --git a/pin-project-internal/src/project.rs b/pin-project-internal/src/project.rs index 8d5eeee9..c8b00bde 100644 --- a/pin-project-internal/src/project.rs +++ b/pin-project-internal/src/project.rs @@ -4,7 +4,8 @@ use syn::{ punctuated::Punctuated, token::Or, visit_mut::{self, VisitMut}, - *, + Arm, Expr, ExprMatch, Ident, Item, ItemFn, Local, Pat, PatBox, PatIdent, PatPath, PatRef, + PatStruct, PatTupleStruct, Path, Result, Stmt, }; use crate::utils::{proj_ident, Nothing, VecExt}; @@ -17,21 +18,17 @@ pub(super) fn attribute(input: TokenStream) -> TokenStream { } fn parse(input: TokenStream) -> Result { - fn replace_stmt(stmt: &mut Stmt) { - match stmt { - Stmt::Expr(Expr::Match(expr)) | Stmt::Semi(Expr::Match(expr), _) => { - expr.replace(&mut Register::default()) - } - Stmt::Local(local) => local.replace(&mut Register::default()), - Stmt::Item(Item::Fn(ItemFn { block, .. })) => Dummy.visit_block_mut(block), - _ => {} + let mut stmt = syn::parse2(input)?; + match &mut stmt { + Stmt::Expr(Expr::Match(expr)) | Stmt::Semi(Expr::Match(expr), _) => { + expr.replace(&mut Register::default()) } + Stmt::Local(local) => local.replace(&mut Register::default()), + Stmt::Item(Item::Fn(ItemFn { block, .. })) => Dummy.visit_block_mut(block), + _ => {} } - syn::parse2(input).map(|mut stmt| { - replace_stmt(&mut stmt); - stmt.into_token_stream() - }) + Ok(stmt.into_token_stream()) } trait Replace { @@ -139,5 +136,5 @@ impl VisitMut for Dummy { } // Stop at item bounds - fn visit_item_mut(&mut self, _item: &mut Item) {} + fn visit_item_mut(&mut self, _: &mut Item) {} } diff --git a/pin-project-internal/src/utils.rs b/pin-project-internal/src/utils.rs index 7216f95e..df2078a3 100644 --- a/pin-project-internal/src/utils.rs +++ b/pin-project-internal/src/utils.rs @@ -1,7 +1,7 @@ use proc_macro2::{Ident, Span}; use syn::{ - parse::{Parse, ParseStream}, - Attribute, Result, + parse::{Parse, ParseStream, Result}, + Attribute, }; /// Makes the ident of projected type from the reference of the original ident. @@ -25,7 +25,7 @@ pub(crate) struct Nothing; impl Parse for Nothing { fn parse(_input: ParseStream<'_>) -> Result { - Ok(Nothing) + Ok(Self) } } diff --git a/src/lib.rs b/src/lib.rs index ebfef311..6f2b227d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,10 @@ -//! An attribute that creates a projection struct covering all the fields. +//! A crate for safe and ergonomic pin-projection. +//! +//! This crate provides the following attribute macros: +//! +//! * [`pin_project`] - An attribute that creates a projection struct covering all the fields. +//! * [`pinned_drop`] - An attribute for annotating a function that implements `Drop`. +//! * [`project`] - An attribute to support pattern matching. //! //! ## Examples //! @@ -64,12 +70,16 @@ //! //! //! +//!
+//! //! See [`pin_project`] attribute for more details. //! -//! [`pin_project`]: ./attr.pin_project.html +//! [`pin_project`]: https://docs.rs/pin-project-internal/0.4.0-alpha.1/pin_project_internal/attr.pin_project.html +//! [`pinned_drop`]: https://docs.rs/pin-project-internal/0.4.0-alpha.1/pin_project_internal/attr.pinned_drop.html +//! [`project`]: https://docs.rs/pin-project-internal/0.4.0-alpha.1/pin_project_internal/attr.project.html #![recursion_limit = "256"] -#![doc(html_root_url = "https://docs.rs/pin-project/0.3.4")] +#![doc(html_root_url = "https://docs.rs/pin-project/0.4.0-alpha.1")] #![doc(test(attr(deny(warnings), allow(dead_code, unused_assignments, unused_variables))))] #![no_std] #![warn(unsafe_code)] @@ -78,364 +88,14 @@ #![warn(clippy::all, clippy::pedantic)] #![allow(clippy::use_self)] -/// An attribute that creates a projection struct covering all the fields. -/// -/// This attribute 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. -/// -/// ## Safety -/// -/// This attribute is completely safe. In the absence of other `unsafe` code *that you write*, -/// it is impossible to cause undefined behavior with this attribute. -/// -/// This is accomplished by enforcing the four requirements for pin projection -/// stated in [the Rust documentation](https://doc.rust-lang.org/beta/std/pin/index.html#projections-and-structural-pinning): -/// -/// 1. The struct must only be Unpin if all the structural fields are Unpin -/// -/// To enforce this, this attribute will automatically generate an `Unpin` implementation -/// for you, which will require that all structurally pinned fields be `Unpin` -/// If you wish to provide an manual `Unpin` impl, you can do so via the -/// `UnsafeUnpin` argument. -/// -/// 2. The destructor of the struct must not move structural fields out of its argument. -/// -/// To enforce this, this attribute will automatically generate a `Drop` impl. -/// If you wish to provide a custom `Drop` impl, you can annotate a function -/// with `#[pinned_drop]`. This function takes a pinned version of your struct - -/// that is, `Pin<&mut MyStruct>` where `MyStruct` is the type of your struct. -/// -/// You can call `project()` on this type as usual, along with any other -/// methods you have defined. Because your code is never provided with -/// a `&mut MyStruct`, it is impossible to move out of pin-projectable -/// fields in safe code in your destructor. -/// -/// 3. You must make sure that you uphold the Drop guarantee: once your struct is pinned, -/// the memory that contains the content is not overwritten or deallocated without calling the content's destructors -/// -/// Safe code doesn't need to worry about this - the only wait to violate this requirement -/// is to manually deallocate memory (which is `unsafe`), or to overwite a field with something else. -/// Becauese your custom destructor takes `Pin<&mut MyStruct`, it's impossible to obtain -/// a mutable reference to a pin-projected field in safe code. -/// -/// 4. You must not offer any other operations that could lead to data being moved out of the structural fields when your type is pinned. -/// -/// As with requirement 3, it is impossible for safe code to violate this. This crate ensures that safe code can never -/// obtain a mutable reference to `#[pin]` fields, which prevents you from ever moving out of them in safe code. -/// -/// Pin projections are also incompatible with `#[repr(packed)]` structs. Attempting to use this attribute -/// on a `#[repr(packed)]` struct results in a compile-time error. -/// -/// -/// ## Examples -/// -/// Using `#[pin_project]` will automatically create the appropriate -/// conditional [`Unpin`] implementation: -/// -/// ```rust -/// use pin_project::pin_project; -/// use std::pin::Pin; -/// -/// #[pin_project] -/// struct Foo { -/// #[pin] -/// future: T, -/// field: U, -/// } -/// -/// impl Foo { -/// fn baz(self: Pin<&mut Self>) { -/// let this = self.project(); -/// let _: Pin<&mut T> = this.future; // Pinned reference to the field -/// let _: &mut U = this.field; // Normal reference to the field -/// } -/// } -/// ``` -/// -/// If you want to implement [`Unpin`] manually, -/// you must use the `UnsafeUnpin` argument to -/// `#[pin_project]`. -/// -/// ```rust -/// use pin_project::{pin_project, UnsafeUnpin}; -/// use std::pin::Pin; -/// -/// #[pin_project(UnsafeUnpin)] -/// struct Foo { -/// #[pin] -/// future: T, -/// field: U, -/// } -/// -/// impl Foo { -/// fn baz(self: Pin<&mut Self>) { -/// let this = self.project(); -/// let _: Pin<&mut T> = this.future; // Pinned reference to the field -/// let _: &mut U = this.field; // Normal reference to the field -/// } -/// } -/// -/// unsafe impl UnsafeUnpin for Foo {} // Conditional Unpin impl -/// ``` -/// -/// Note the usage of the unsafe [`UnsafeUnpin`] trait, instead of the usual -/// [`Unpin`] trait. [`UnsafeUnpin`] behaves exactly like [`Unpin`], except that is -/// unsafe to implement. This unsafety comes from the fact that pin projections -/// are being used. If you implement [`UnsafeUnpin`], you must ensure that it is -/// only implemented when all pin-projected fields implement [`Unpin`]. -/// -/// Note that borrowing the field where `#[pin]` attribute is used multiple -/// times requires using [`.as_mut()`](core::pin::Pin::as_mut) to avoid -/// consuming the `Pin`. -/// -/// ### `#[pinned_drop]` -/// -/// In order to correctly implement pin projections, a type's `Drop` impl must -/// not move out of any stucturally pinned fields. Unfortunately, [`Drop::drop`] -/// takes `&mut Self`, not `Pin<&mut Self>`. -/// -/// To ensure that this requirement is upheld, the `pin_project` attribute will -/// provide a `Drop` impl for you. This `Drop` impl will delegate to a function -/// annotated with `#[pinned_drop]` if you use the `PinnedDrop` argument to -/// `#[pin_project]`. This function acts just like a normal [`drop`] impl, except -/// for the fact that it takes `Pin<&mut Self>`. In particular, it will never be -/// called more than once, just like [`Drop::drop`]. -/// -/// For example: -/// -/// ```rust -/// use pin_project::{pin_project, pinned_drop}; -/// use std::fmt::Debug; -/// use std::pin::Pin; -/// -/// #[pin_project(PinnedDrop)] -/// pub struct Foo { -/// #[pin] pinned_field: T, -/// unpin_field: U -/// } -/// -/// #[pinned_drop] -/// fn my_drop_fn(foo: Pin<&mut Foo>) { -/// let foo = foo.project(); -/// println!("Dropping pinned field: {:?}", foo.pinned_field); -/// println!("Dropping unpin field: {:?}", foo.unpin_field); -/// } -/// -/// fn main() { -/// Foo { pinned_field: true, unpin_field: 40 }; -/// } -/// ``` -/// -/// See also [`pinned_drop`] attribute. -/// -/// ## Supported Items -/// -/// The current version of pin-project supports the following types of items. -/// -/// ### Structs (structs with named fields): -/// -/// ```rust -/// use pin_project::pin_project; -/// use std::pin::Pin; -/// -/// #[pin_project] -/// struct Foo { -/// #[pin] -/// future: T, -/// field: U, -/// } -/// -/// impl Foo { -/// fn baz(self: Pin<&mut Self>) { -/// let this = self.project(); -/// let _: Pin<&mut T> = this.future; -/// let _: &mut U = this.field; -/// } -/// } -/// ``` -/// -/// ### Tuple structs (structs with unnamed fields): -/// -/// ```rust -/// use pin_project::pin_project; -/// use std::pin::Pin; -/// -/// #[pin_project] -/// struct Foo(#[pin] T, U); -/// -/// impl Foo { -/// fn baz(self: Pin<&mut Self>) { -/// let this = self.project(); -/// let _: Pin<&mut T> = this.0; -/// let _: &mut U = this.1; -/// } -/// } -/// ``` -/// -/// Structs without fields (unit-like struct and zero fields struct) are not -/// supported. -/// -/// ### Enums -/// -/// `pin_project` also supports enums, but to use it ergonomically, you need -/// to use the [`project`] attribute. -/// -/// *This attribute is only available if pin-project is built -/// with the `"project_attr"` feature.* -/// -/// The attribute at the expression position is not stable, so you need to use -/// a dummy `#[project]` attribute for the function. -/// -/// ```rust -/// # #[cfg(feature = "project_attr")] -/// use pin_project::{project, pin_project}; -/// # #[cfg(feature = "project_attr")] -/// use std::pin::Pin; -/// -/// # #[cfg(feature = "project_attr")] -/// #[pin_project] -/// enum Foo { -/// Tuple(#[pin] A, B), -/// Struct { field: C }, -/// Unit, -/// } -/// -/// # #[cfg(feature = "project_attr")] -/// impl Foo { -/// #[project] // Nightly does not need a dummy attribute to the function. -/// fn baz(self: Pin<&mut Self>) { -/// #[project] -/// match self.project() { -/// Foo::Tuple(x, y) => { -/// let _: Pin<&mut A> = x; -/// let _: &mut B = y; -/// } -/// Foo::Struct { field } => { -/// let _: &mut C = field; -/// } -/// Foo::Unit => {} -/// } -/// } -/// } -/// ``` -/// -/// Enums without variants (zero-variant enums) are not supported. -/// -/// See also [`project`] attribute. -/// -/// [`drop`]: Drop::drop -/// [`project`]: ./attr.project.html -/// [`pinned_drop`]: ./attr.pinned_drop.html -#[doc(inline)] +#[doc(hidden)] pub use pin_project_internal::pin_project; -/// An attribute for annotating a function that implements [`Drop`]. -/// -/// This attribute is only needed when you wish to provide a [`Drop`] -/// impl for your type. The function annotated with `#[pinned_drop]` acts just -/// like a normal [`drop`](Drop::drop) impl, except for the fact that it takes -/// `Pin<&mut Self>`. In particular, it will never be called more than once, -/// just like [`Drop::drop`]. -/// -/// Example: -/// -/// ```rust -/// use pin_project::{pin_project, pinned_drop}; -/// use std::pin::Pin; -/// -/// #[pin_project(PinnedDrop)] -/// struct Foo { -/// #[pin] field: u8 -/// } -/// -/// #[pinned_drop] -/// fn my_drop(foo: Pin<&mut Foo>) { -/// println!("Dropping: {}", foo.field); -/// } -/// -/// fn main() { -/// Foo { field: 50 }; -/// } -/// ``` -/// -/// See [`pin_project`] attribute for more. -/// -/// [`pin_project`]: ./attr.pin_project.html -#[doc(inline)] +#[doc(hidden)] pub use pin_project_internal::pinned_drop; -/// An attribute to support pattern matching. -/// -/// *This attribute is available if pin-project is built with the -/// `"project_attr"` feature.* -/// -/// The attribute at the expression position is not stable, so you need to use -/// a dummy `#[project]` attribute for the function. -/// -/// ## Examples -/// -/// The following two syntaxes are supported. -/// -/// ### `let` bindings -/// -/// ```rust -/// use pin_project::{pin_project, project}; -/// use std::pin::Pin; -/// -/// #[pin_project] -/// struct Foo { -/// #[pin] -/// future: T, -/// field: U, -/// } -/// -/// impl Foo { -/// #[project] // Nightly does not need a dummy attribute to the function. -/// fn baz(self: Pin<&mut Self>) { -/// #[project] -/// let Foo { future, field } = self.project(); -/// -/// let _: Pin<&mut T> = future; -/// let _: &mut U = field; -/// } -/// } -/// ``` -/// -/// ### `match` expressions -/// -/// ```rust -/// use pin_project::{project, pin_project}; -/// use std::pin::Pin; -/// -/// #[pin_project] -/// enum Foo { -/// Tuple(#[pin] A, B), -/// Struct { field: C }, -/// Unit, -/// } -/// -/// impl Foo { -/// #[project] // Nightly does not need a dummy attribute to the function. -/// fn baz(self: Pin<&mut Self>) { -/// #[project] -/// match self.project() { -/// Foo::Tuple(x, y) => { -/// let _: Pin<&mut A> = x; -/// let _: &mut B = y; -/// } -/// Foo::Struct { field } => { -/// let _: &mut C = field; -/// } -/// Foo::Unit => {} -/// } -/// } -/// } -/// ``` #[cfg(feature = "project_attr")] -#[doc(inline)] +#[doc(hidden)] pub use pin_project_internal::project; /// A trait used for custom implementations of [`Unpin`]. @@ -447,27 +107,27 @@ pub use pin_project_internal::project; /// behavior can only occur when other unsafe code is used. /// /// It turns out that using pin projections, which requires unsafe code, -/// imposes additional requirements on an `Unpin` impl. Normally, all of this +/// imposes additional requirements on an [`Unpin`] impl. Normally, all of this /// unsafety is contained within this crate, ensuring that it's impossible for /// you to violate any of the guarnatees required by pin projection. /// -/// However, things change if you want to provide a custom `Unpin` impl +/// However, things change if you want to provide a custom [`Unpin`] impl /// for your `#[pin_project]` type. As stated in [the Rust /// documentation](https://doc.rust-lang.org/beta/std/pin/index.html#projections-and-structural-pinning), -/// you must be sure to only implement `Unpin` when all of your `#[pin]` fields (i.e. struturally -/// pinend fields) are also `Unpin`. +/// you must be sure to only implement [`Unpin`] when all of your `#[pin]` fields (i.e. struturally +/// pinend fields) are also [`Unpin`]. /// /// To help highlight this unsafety, the `UnsafeUnpin` trait is provided. -/// Implementing this trait is logically equivalent to implemnting `Unpin` - -/// this crate will generate an `Unpin` impl for your type that 'forwards' to +/// Implementing this trait is logically equivalent to implemnting [`Unpin`] - +/// this crate will generate an [`Unpin`] impl for your type that 'forwards' to /// your `UnsafeUnpin` impl. However, this trait is `unsafe` - since your type /// uses structural pinning (otherwise, you wouldn't be using this crate!), /// you must be sure that your `UnsafeUnpin` impls follows all of -/// the requirements for an `Unpin` impl of a structurally-pinned type. +/// the requirements for an [`Unpin`] impl of a structurally-pinned type. /// /// Note that if you specify `#[pin_project(UnsafeUnpin)]`, but do *not* -/// provide an impl of `UnsafeUnpin`, your type will never implement `Unpin`. -/// This is effectly the same thing as adding a `PhantomUnpin` to your type +/// provide an impl of `UnsafeUnpin`, your type will never implement [`Unpin`]. +/// This is effectly the same thing as adding a [`PhantomPinned`] to your type /// /// Since this trait is `unsafe`, impls of it will be detected by the `unsafe_code` lint, /// and by tools like `cargo geiger`. @@ -475,7 +135,7 @@ pub use pin_project_internal::project; /// ## Examples /// /// An `UnsafeUnpin` impl which, in addition to requiring that structually pinned -/// fields be `Unpin`, imposes an additional requirement: +/// fields be [`Unpin`], imposes an additional requirement: /// /// ```rust /// use pin_project::{pin_project, UnsafeUnpin}; @@ -490,7 +150,8 @@ pub use pin_project_internal::project; /// unsafe impl UnsafeUnpin for Foo where K: Unpin + Clone {} /// ``` /// -/// [`pin_project`]: ./attr.pin_project.html +/// [`PhantomPinned`]: core::marker::PhantomPinned +/// [`pin_project`]: https://docs.rs/pin-project-internal/0.4.0-alpha.1/pin_project_internal/attr.pin_project.html #[allow(unsafe_code)] pub unsafe trait UnsafeUnpin {}