summaryrefslogtreecommitdiffstats
path: root/third_party/rust/pin-project/src/lib.rs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 01:47:29 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 01:47:29 +0000
commit0ebf5bdf043a27fd3dfb7f92e0cb63d88954c44d (patch)
treea31f07c9bcca9d56ce61e9a1ffd30ef350d513aa /third_party/rust/pin-project/src/lib.rs
parentInitial commit. (diff)
downloadfirefox-esr-0ebf5bdf043a27fd3dfb7f92e0cb63d88954c44d.tar.xz
firefox-esr-0ebf5bdf043a27fd3dfb7f92e0cb63d88954c44d.zip
Adding upstream version 115.8.0esr.upstream/115.8.0esr
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/pin-project/src/lib.rs')
-rw-r--r--third_party/rust/pin-project/src/lib.rs315
1 files changed, 315 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..5fa9298011
--- /dev/null
+++ b/third_party/rust/pin-project/src/lib.rs
@@ -0,0 +1,315 @@
+//! A crate for safe and ergonomic [pin-projection].
+//!
+//! # Examples
+//!
+//! [`#[pin_project]`][`pin_project`] attribute creates projection types
+//! covering all the fields of struct or enum.
+//!
+//! ```rust
+//! use std::pin::Pin;
+//!
+//! use pin_project::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
+//! }
+//! }
+//! ```
+//!
+//! [*code like this will be generated*][struct-default-expanded]
+//!
+//! 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::pin_project;
+//!
+//! #[pin_project(project = EnumProj)]
+//! enum Enum<T, U> {
+//! Pinned(#[pin] T),
+//! Unpinned(U),
+//! }
+//!
+//! impl<T, U> Enum<T, U> {
+//! fn method(self: Pin<&mut Self>) {
+//! match self.project() {
+//! EnumProj::Pinned(x) => {
+//! let _: Pin<&mut T> = x;
+//! }
+//! EnumProj::Unpinned(y) => {
+//! let _: &mut U = y;
+//! }
+//! }
+//! }
+//! }
+//! ```
+//!
+//! [*code like this will be generated*][enum-default-expanded]
+//!
+//! See [`#[pin_project]`][`pin_project`] attribute for more details, and
+//! see [examples] directory for more examples and generated code.
+//!
+//! [examples]: https://github.com/taiki-e/pin-project/blob/HEAD/examples/README.md
+//! [enum-default-expanded]: https://github.com/taiki-e/pin-project/blob/HEAD/examples/enum-default-expanded.rs
+//! [pin-projection]: core::pin#projections-and-structural-pinning
+//! [struct-default-expanded]: https://github.com/taiki-e/pin-project/blob/HEAD/examples/struct-default-expanded.rs
+
+#![no_std]
+#![doc(test(
+ no_crate_inject,
+ attr(
+ deny(warnings, rust_2018_idioms, single_use_lifetimes),
+ allow(dead_code, unused_variables)
+ )
+))]
+#![warn(missing_docs, rust_2018_idioms, single_use_lifetimes, unreachable_pub)]
+#![warn(
+ clippy::pedantic,
+ // lints for public library
+ clippy::alloc_instead_of_core,
+ clippy::exhaustive_enums,
+ clippy::exhaustive_structs,
+ clippy::std_instead_of_alloc,
+ clippy::std_instead_of_core,
+ // lints that help writing unsafe code
+ clippy::default_union_representation,
+ clippy::trailing_empty_array,
+ clippy::transmute_undefined_repr,
+ clippy::undocumented_unsafe_blocks,
+)]
+#![allow(clippy::needless_doctest_main)]
+
+#[doc(inline)]
+pub use pin_project_internal::pin_project;
+#[doc(inline)]
+pub use pin_project_internal::pinned_drop;
+
+/// A trait used for custom implementations of [`Unpin`].
+///
+/// This trait is used in conjunction with the `UnsafeUnpin` argument to
+/// the [`#[pin_project]`][macro@pin_project] attribute.
+///
+/// # Safety
+///
+/// The Rust [`Unpin`] trait is safe to implement - by itself,
+/// implementing it cannot lead to [undefined behavior][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][pin-projection], 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`][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 Struct<K, V> {
+/// #[pin]
+/// field_1: K,
+/// field_2: V,
+/// }
+///
+/// unsafe impl<K, V> UnsafeUnpin for Struct<K, V> where K: Unpin + Clone {}
+/// ```
+///
+/// [`PhantomPinned`]: core::marker::PhantomPinned
+/// [cargo-geiger]: https://github.com/rust-secure-code/cargo-geiger
+/// [pin-projection]: core::pin#projections-and-structural-pinning
+/// [undefined-behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
+pub unsafe trait UnsafeUnpin {}
+
+// Not public API.
+#[doc(hidden)]
+pub mod __private {
+ use core::mem::ManuallyDrop;
+ #[doc(hidden)]
+ pub use core::{
+ marker::{PhantomData, PhantomPinned, Unpin},
+ ops::Drop,
+ pin::Pin,
+ ptr,
+ };
+
+ #[doc(hidden)]
+ pub use pin_project_internal::__PinProjectInternalDerive;
+
+ use super::UnsafeUnpin;
+
+ // An internal trait used for custom implementations of [`Drop`].
+ //
+ // **Do not call or implement this trait directly.**
+ //
+ // # Why this trait is private and `#[pinned_drop]` attribute is needed?
+ //
+ // Implementing `PinnedDrop::drop` 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][rust-lang/rust#62360].
+ //
+ // Ideally, it would be desirable to be able to forbid manual calls in
+ // the same way as [`Drop::drop`], but the library cannot do it. So, by using
+ // macros and replacing them with private traits,
+ // this crate prevent users from calling `PinnedDrop::drop` in safe code.
+ //
+ // This allows implementing [`Drop`] safely using `#[pinned_drop]`.
+ // Also by using the [`drop`] function just like dropping a type that directly
+ // implements [`Drop`], can drop safely a type that implements `PinnedDrop`.
+ //
+ // [rust-lang/rust#62360]: https://github.com/rust-lang/rust/pull/62360
+ #[doc(hidden)]
+ pub trait PinnedDrop {
+ #[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:
+ //
+ // ```rust
+ // #[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:
+ //
+ // ```rust
+ // 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);
+
+ // SAFETY: `T` implements UnsafeUnpin.
+ unsafe impl<T: ?Sized + UnsafeUnpin> UnsafeUnpin for Wrapper<'_, T> {}
+
+ // 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>(PhantomData<&'a ()>, PhantomData<T>);
+
+ impl<T> 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) {
+ // SAFETY: the caller of `UnsafeDropInPlaceGuard::new` must guarantee
+ // that `ptr` is valid for drop when this guard is destructed.
+ 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) {
+ // SAFETY: the caller of `UnsafeOverwriteGuard::new` must guarantee
+ // that `target` is valid for writes when this guard is destructed.
+ unsafe {
+ ptr::write(self.target, ptr::read(&*self.value));
+ }
+ }
+ }
+}