diff options
Diffstat (limited to 'third_party/rust/pin-project/src/lib.rs')
-rw-r--r-- | third_party/rust/pin-project/src/lib.rs | 205 |
1 files changed, 205 insertions, 0 deletions
diff --git a/third_party/rust/pin-project/src/lib.rs b/third_party/rust/pin-project/src/lib.rs new file mode 100644 index 0000000000..7d2de26614 --- /dev/null +++ b/third_party/rust/pin-project/src/lib.rs @@ -0,0 +1,205 @@ +//! A crate for safe and ergonomic pin-projection. +//! +//! ## Examples +//! +//! [`pin_project`] attribute creates a projection struct covering all the fields. +//! +//! ```rust +//! use pin_project::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; // Pinned reference to the field +//! let _: &mut U = this.unpinned; // Normal reference to the field +//! } +//! } +//! ``` +//! +//! [Code like this will be generated](https://github.com/taiki-e/pin-project/blob/master/examples/struct-default-expanded.rs) +//! +//! See [`pin_project`] attribute for more details. +//! +//! Also, there are examples and generated code of each feature in [examples](https://github.com/taiki-e/pin-project/blob/master/examples/README.md) directory. +//! +//! [`pin_project`]: attr.pin_project.html + +#![no_std] +#![recursion_limit = "256"] +#![doc(html_root_url = "https://docs.rs/pin-project/0.4.9")] +#![doc(test( + no_crate_inject, + attr(deny(warnings, rust_2018_idioms, single_use_lifetimes), allow(dead_code)) +))] +#![warn(unsafe_code)] +#![warn(missing_docs, rust_2018_idioms, single_use_lifetimes, unreachable_pub)] +#![warn(clippy::all)] +// mem::take requires Rust 1.40 +#![allow(clippy::mem_replace_with_default)] +#![allow(clippy::needless_doctest_main)] + +#[doc(inline)] +pub use pin_project_internal::pin_project; + +#[doc(inline)] +pub use pin_project_internal::pinned_drop; + +#[doc(inline)] +pub use pin_project_internal::project; + +#[doc(inline)] +pub use pin_project_internal::project_ref; + +/// A trait used for custom implementations of [`Unpin`]. +/// This trait is used in conjunction with the `UnsafeUnpin` +/// argument to [`pin_project`] +/// +/// The Rust [`Unpin`] trait is safe to implement - by itself, +/// implementing it cannot lead to undefined behavior. Undefined +/// 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 +/// unsafety is contained within this crate, ensuring that it's impossible for +/// you to violate any of the guarantees required by pin projection. +/// +/// 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/nightly/std/pin/index.html#projections-and-structural-pinning), +/// you must be sure to only implement [`Unpin`] when all of your `#[pin]` fields (i.e. structurally +/// pinned fields) are also [`Unpin`]. +/// +/// To help highlight this unsafety, the `UnsafeUnpin` trait is provided. +/// Implementing this trait is logically equivalent to implementing [`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. +/// +/// Note that if you specify `#[pin_project(UnsafeUnpin)]`, but do *not* +/// provide an impl of `UnsafeUnpin`, your type will never implement [`Unpin`]. +/// This is effectively 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`. +/// +/// ## Examples +/// +/// An `UnsafeUnpin` impl which, in addition to requiring that structurally pinned +/// fields be [`Unpin`], imposes an additional requirement: +/// +/// ```rust +/// use pin_project::{pin_project, UnsafeUnpin}; +/// +/// #[pin_project(UnsafeUnpin)] +/// struct Foo<K, V> { +/// #[pin] +/// field_1: K, +/// field_2: V, +/// } +/// +/// unsafe impl<K, V> UnsafeUnpin for Foo<K, V> where K: Unpin + Clone {} +/// ``` +/// +/// [`PhantomPinned`]: core::marker::PhantomPinned +/// [`pin_project`]: attr.pin_project.html +#[allow(unsafe_code)] +pub unsafe trait UnsafeUnpin {} + +// Not public API. +#[doc(hidden)] +pub mod __private { + use super::UnsafeUnpin; + use core::{marker::PhantomData, pin::Pin}; + + #[doc(hidden)] + pub use pin_project_internal::__PinProjectInternalDerive; + + // It is safe to implement PinnedDrop::drop, but it is not safe to call it. + // This is because destructors can be called multiple times (double dropping + // is unsound: rust-lang/rust#62360). + // + // Ideally, it would be desirable to be able to prohibit manual calls in the + // same way as Drop::drop, but the library cannot. So, by using macros and + // replacing them with private traits, we prevent users from calling + // PinnedDrop::drop. + // + // Users can implement `Drop` safely using `#[pinned_drop]`. + // **Do not call or implement this trait directly.** + #[doc(hidden)] + pub trait PinnedDrop { + // Since calling it twice on the same object would be UB, + // this method is unsafe. + #[allow(unsafe_code)] + #[doc(hidden)] + unsafe fn drop(self: Pin<&mut Self>); + } + + // This is an internal helper struct used by `pin-project-internal`. + // This allows us to force an error if the user tries to provide + // a regular `Unpin` impl when they specify the `UnsafeUnpin` argument. + // This is why we need Wrapper: + // + // Supposed we have the following code: + // + // #[pin_project(UnsafeUnpin)] + // struct MyStruct<T> { + // #[pin] field: T + // } + // + // impl<T> Unpin for MyStruct<T> where MyStruct<T>: UnsafeUnpin {} // generated by pin-project-internal + // impl<T> Unpin for MyStruct<T> where T: Copy // written by the user + // + // We want this code to be rejected - the user is completely bypassing `UnsafeUnpin`, + // and providing an unsound Unpin impl in safe code! + // + // Unfortunately, the Rust compiler will accept the above code. + // Because MyStruct is declared in the same crate as the user-provided impl, + // the compiler will notice that 'MyStruct<T>: UnsafeUnpin' never holds. + // + // The solution is to introduce the 'Wrapper' struct, which is defined + // in the 'pin-project' crate. + // + // We now have code that looks like this: + // + // impl<T> Unpin for MyStruct<T> where Wrapper<MyStruct<T>>: UnsafeUnpin {} // generated by pin-project-internal + // impl<T> Unpin for MyStruct<T> where T: Copy // written by the user + // + // We also have 'unsafe impl<T> UnsafeUnpin for Wrapper<T> where T: UnsafeUnpin {}' in the + // 'pin-project' crate. + // + // Now, our generated impl has a bound involving a type defined in another crate - Wrapper. + // This will cause rust to conservatively assume that 'Wrapper<MyStruct<T>>: UnsafeUnpin' + // holds, in the interest of preserving forwards compatibility (in case such an impl is added + // for Wrapper<T> in a new version of the crate). + // + // This will cause rust to reject any other Unpin impls for MyStruct<T>, since it will + // assume that our generated impl could potentially apply in any situation. + // + // This achieves the desired effect - when the user writes `#[pin_project(UnsafeUnpin)]`, + // the user must either provide no impl of `UnsafeUnpin` (which is equivalent + // to making the type never implement Unpin), or provide an impl of `UnsafeUnpin`. + // It is impossible for them to provide an impl of `Unpin` + #[doc(hidden)] + pub struct Wrapper<'a, T: ?Sized>(PhantomData<&'a ()>, T); + + #[allow(unsafe_code)] + unsafe impl<T: ?Sized> UnsafeUnpin for Wrapper<'_, T> where T: UnsafeUnpin {} + + // This is an internal helper struct used by `pin-project-internal`. + // + // See https://github.com/taiki-e/pin-project/pull/53 for more details. + #[doc(hidden)] + pub struct AlwaysUnpin<'a, T: ?Sized>(PhantomData<&'a ()>, PhantomData<T>); + + impl<T: ?Sized> Unpin for AlwaysUnpin<'_, T> {} +} |