about summary refs log tree commit diff
diff options
context:
space:
mode:
authorGray Olson <gray@grayolson.com>2023-09-25 16:00:35 +0200
committerManish Goregaokar <manishsmail@gmail.com>2024-01-07 08:56:04 -0800
commit46f9d77bd1eadd637a78df9e413cb689d39d6246 (patch)
tree23d24b98b191ea30a5866fa7e212406674b0b4d1
parentec8a01a4798ca76b09e4c626fc47eb8cab960e24 (diff)
update doubly linked list commentary and fix links
-rw-r--r--library/core/src/pin.rs45
1 files changed, 26 insertions, 19 deletions
diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs
index dcabf359f52..dc4730f4f5d 100644
--- a/library/core/src/pin.rs
+++ b/library/core/src/pin.rs
@@ -26,7 +26,7 @@
 //! * [Examples of types with address-sensitive states][address-sensitive-examples]
 //!   * [Self-referential struct][self-ref]
 //!   * [Intrusive, doubly-linked list][linked-list]
-//! * [Subtle Details][subtle-details]
+//! * [Subtle details and the `Drop` guarantee][subtle-details]
 //!
 //! # What is "*moving*"?
 //! [what-is-moving]: self#what-is-moving
@@ -156,7 +156,7 @@
 //!
 //! In order to pin a value, we wrap a *pointer to that value* (of some type `Ptr`) in a
 //! [`Pin<Ptr>`]. [`Pin<Ptr>`] can wrap any pointer type, forming a promise that the **pointee**
-//! will not be *moved* or [otherwise invalidated][self#subtle-details].
+//! will not be *moved* or [otherwise invalidated][subtle-details].
 //!
 //! We call such a [`Pin`]-wrapped pointer a **pinning pointer,** (or pinning reference, or pinning
 //! `Box`, etc.) because its existince is the thing that is pinning the underlying pointee in place:
@@ -376,7 +376,7 @@
 //! // std::mem::swap(&mut *still_unmoved, &mut *new_unmoved);
 //! ```
 //!
-//! ## Intrusive, doubly-linked list
+//! ## An intrusive, doubly-linked list
 //! [linked-list]: #an-intrusive-doubly-linked-list
 //!
 //! In an intrusive doubly-linked list, the collection does not actually allocate the memory for the
@@ -384,21 +384,26 @@
 //! that lives shorter than the collection does provided the nodes are removed from the
 //! collection before returning.
 //!
-//! To make this work, every element has pointers to its predecessor and successor in
-//! the list. Elements can only be added when they are pinned, because moving the elements
-//! around would invalidate the pointers. Moreover, the [`Drop`][Drop] implementation of a linked
-//! list element will patch the pointers of its predecessor and successor to remove itself
-//! from the list.
+//! The full implementation details of such a data structure are outside the scope of this
+//! documentation, but we will discuss how [`Pin`] can help to do so.
 //!
-//! Crucially, we have to be able to rely on [`drop`] being called before an element is invalidated.
-//! If an element could be deallocated or otherwise invalidated without calling [`drop`], the
-//! pointers into it from its neighboring elements would become invalid, which would break the data
-//! structure.
+//! To make such an intrusive data structure work, every element stores pointers to its predecessor
+//! and successor within its own data, rather than having the list structure itself manage those
+//! pointers. Elements can only be added when they are pinned, because moving the elements
+//! around would invalidate the pointers to it which are contained in the element ahead and behind
+//! it. Moreover, the [`Drop`][Drop] implementation of the element types themselves will in some
+//! way patch the pointers of its predecessor and successor elements to remove itself from the list.
 //!
-//! Therefore, we rely on [the `Drop` guarantee][drop-guarantee] which comes with pinning data.
+//! Crucially, this means we have to be able to rely on [`drop`] always being called before that
+//! element is invalidated. If an element could be deallocated or otherwise invalidated without
+//! calling [`drop`], the pointers into it which are stored in its neighboring elements would
+//! become invalid, which would break the data structure.
 //!
-//! # Subtle details
-//! [subtle-details]: #subtle-details
+//! Therefore, we rely on [the `Drop` guarantee][drop-guarantee] which comes with pinning data,
+//!
+//! # Subtle details and the `Drop` guarantee
+//! [subtle-details]: self#subtle-details-and-the-drop-guarantee
+//! [drop-guarantee]: self#subtle-details-and-the-drop-guarantee
 //!
 //! The purpose of pinning is not *just* to prevent a value from being *moved*, but rather more
 //! generally to be able to rely on the pinned value *remaining valid **at a specific place*** in
@@ -425,7 +430,6 @@
 //! This point is subtle but required for intrusive data structures to be implemented soundly.
 //!
 //! ## `Drop` guarantee
-//! [drop-guarantee]: self#drop-guarantee
 //!
 //! There needs to be a way for a pinned value to notify any code that is relying on its pinned
 //! status that it is about to be destroyed, so that such code can remove its address from their
@@ -482,7 +486,7 @@
 //! address-sensitive types, which are different from merely using [`Pin<P>`] in a generic
 //! way.
 //!
-//! ## Implementing [`Drop`] for types with address-sensitive state
+//! ## Implementing [`Drop`] for types with address-sensitive states
 //! [drop-impl]: self#implementing-drop-for-types-with-address-sensitive-states
 //!
 //! The [`drop`] function takes [`&mut self`], but this is called *even if that `self` has been
@@ -817,7 +821,7 @@ use crate::{
 ///
 /// In order to pin a value, we wrap a *pointer to that value* (of some type `Ptr`) in a
 /// [`Pin<Ptr>`]. [`Pin<Ptr>`] can wrap any pointer type, forming a promise that the **pointee**
-/// will not be *moved* or [otherwise invalidated][self#subtle-details].
+/// will not be *moved* or [otherwise invalidated][subtle-details].
 ///
 /// We call such a [`Pin`]-wrapped pointer a **pinning pointer,** (or pinning ref, or pinning
 /// [`Box`], etc.) because its existince is the thing that is pinning the underlying pointee in
@@ -833,6 +837,7 @@ use crate::{
 ///
 /// [`pin` module]: self
 /// [`Box`]: ../../std/boxed/struct.Box.html
+/// [subtle-details]: self#subtle-details-and-the-drop-guarantee
 //
 // Note: the `Clone` derive below causes unsoundness as it's possible to implement
 // `Clone` for mutable references.
@@ -1171,7 +1176,7 @@ impl<P: DerefMut> Pin<P> {
     ///
     /// This overwrites pinned data, but that is okay: the original pinned value's destructor gets
     /// run before being overwritten and the new value is also a valid value of the same type, so
-    /// no pinning invariant is violated. See [the `pin` module documentation][self#subtle-details]
+    /// no pinning invariant is violated. See [the `pin` module documentation][subtle-details]
     /// for more information on how this upholds the pinning invariants.
     ///
     /// # Example
@@ -1185,6 +1190,8 @@ impl<P: DerefMut> Pin<P> {
     /// pinned.set(10);
     /// println!("{}", pinned); // 10
     /// ```
+    ///
+    /// [subtle-details]: self#subtle-details-and-the-drop-guarantee
     #[stable(feature = "pin", since = "1.33.0")]
     #[inline(always)]
     pub fn set(&mut self, value: P::Target)