Skip to content

Commit a7e9c3b

Browse files
committed
update doubly linked list commentary and fix links
1 parent c13e11a commit a7e9c3b

File tree

1 file changed

+26
-19
lines changed

1 file changed

+26
-19
lines changed

library/core/src/pin.rs

+26-19
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
//! * [Examples of types with address-sensitive states][address-sensitive-examples]
2727
//! * [Self-referential struct][self-ref]
2828
//! * [Intrusive, doubly-linked list][linked-list]
29-
//! * [Subtle Details][subtle-details]
29+
//! * [Subtle details and the `Drop` guarantee][subtle-details]
3030
//!
3131
//! # What is "*moving*"?
3232
//! [what-is-moving]: self#what-is-moving
@@ -156,7 +156,7 @@
156156
//!
157157
//! In order to pin a value, we wrap a *pointer to that value* (of some type `Ptr`) in a
158158
//! [`Pin<Ptr>`]. [`Pin<Ptr>`] can wrap any pointer type, forming a promise that the **pointee**
159-
//! will not be *moved* or [otherwise invalidated][self#subtle-details].
159+
//! will not be *moved* or [otherwise invalidated][subtle-details].
160160
//!
161161
//! We call such a [`Pin`]-wrapped pointer a **pinning pointer,** (or pinning reference, or pinning
162162
//! `Box`, etc.) because its existince is the thing that is pinning the underlying pointee in place:
@@ -376,29 +376,34 @@
376376
//! // std::mem::swap(&mut *still_unmoved, &mut *new_unmoved);
377377
//! ```
378378
//!
379-
//! ## Intrusive, doubly-linked list
379+
//! ## An intrusive, doubly-linked list
380380
//! [linked-list]: #an-intrusive-doubly-linked-list
381381
//!
382382
//! In an intrusive doubly-linked list, the collection does not actually allocate the memory for the
383383
//! nodes itself. Allocation is controlled by the clients, and nodes can live on a stack frame
384384
//! that lives shorter than the collection does provided the nodes are removed from the
385385
//! collection before returning.
386386
//!
387-
//! To make this work, every element has pointers to its predecessor and successor in
388-
//! the list. Elements can only be added when they are pinned, because moving the elements
389-
//! around would invalidate the pointers. Moreover, the [`Drop`][Drop] implementation of a linked
390-
//! list element will patch the pointers of its predecessor and successor to remove itself
391-
//! from the list.
387+
//! The full implementation details of such a data structure are outside the scope of this
388+
//! documentation, but we will discuss how [`Pin`] can help to do so.
392389
//!
393-
//! Crucially, we have to be able to rely on [`drop`] being called before an element is invalidated.
394-
//! If an element could be deallocated or otherwise invalidated without calling [`drop`], the
395-
//! pointers into it from its neighboring elements would become invalid, which would break the data
396-
//! structure.
390+
//! To make such an intrusive data structure work, every element stores pointers to its predecessor
391+
//! and successor within its own data, rather than having the list structure itself manage those
392+
//! pointers. Elements can only be added when they are pinned, because moving the elements
393+
//! around would invalidate the pointers to it which are contained in the element ahead and behind
394+
//! it. Moreover, the [`Drop`][Drop] implementation of the element types themselves will in some
395+
//! way patch the pointers of its predecessor and successor elements to remove itself from the list.
397396
//!
398-
//! Therefore, we rely on [the `Drop` guarantee][drop-guarantee] which comes with pinning data.
397+
//! Crucially, this means we have to be able to rely on [`drop`] always being called before that
398+
//! element is invalidated. If an element could be deallocated or otherwise invalidated without
399+
//! calling [`drop`], the pointers into it which are stored in its neighboring elements would
400+
//! become invalid, which would break the data structure.
399401
//!
400-
//! # Subtle details
401-
//! [subtle-details]: #subtle-details
402+
//! Therefore, we rely on [the `Drop` guarantee][drop-guarantee] which comes with pinning data,
403+
//!
404+
//! # Subtle details and the `Drop` guarantee
405+
//! [subtle-details]: self#subtle-details-and-the-drop-guarantee
406+
//! [drop-guarantee]: self#subtle-details-and-the-drop-guarantee
402407
//!
403408
//! The purpose of pinning is not *just* to prevent a value from being *moved*, but rather more
404409
//! generally to be able to rely on the pinned value *remaining valid **at a specific place*** in
@@ -425,7 +430,6 @@
425430
//! This point is subtle but required for intrusive data structures to be implemented soundly.
426431
//!
427432
//! ## `Drop` guarantee
428-
//! [drop-guarantee]: self#drop-guarantee
429433
//!
430434
//! There needs to be a way for a pinned value to notify any code that is relying on its pinned
431435
//! status that it is about to be destroyed, so that such code can remove its address from their
@@ -482,7 +486,7 @@
482486
//! address-sensitive types, which are different from merely using [`Pin<P>`] in a generic
483487
//! way.
484488
//!
485-
//! ## Implementing [`Drop`] for types with address-sensitive state
489+
//! ## Implementing [`Drop`] for types with address-sensitive states
486490
//! [drop-impl]: self#implementing-drop-for-types-with-address-sensitive-states
487491
//!
488492
//! The [`drop`] function takes [`&mut self`], but this is called *even if that `self` has been
@@ -818,7 +822,7 @@ use crate::{
818822
///
819823
/// In order to pin a value, we wrap a *pointer to that value* (of some type `Ptr`) in a
820824
/// [`Pin<Ptr>`]. [`Pin<Ptr>`] can wrap any pointer type, forming a promise that the **pointee**
821-
/// will not be *moved* or [otherwise invalidated][self#subtle-details].
825+
/// will not be *moved* or [otherwise invalidated][subtle-details].
822826
///
823827
/// We call such a [`Pin`]-wrapped pointer a **pinning pointer,** (or pinning ref, or pinning
824828
/// [`Box`], etc.) because its existince is the thing that is pinning the underlying pointee in
@@ -834,6 +838,7 @@ use crate::{
834838
///
835839
/// [`pin` module]: self
836840
/// [`Box`]: ../../std/boxed/struct.Box.html
841+
/// [subtle-details]: self#subtle-details-and-the-drop-guarantee
837842
//
838843
// Note: the `Clone` derive below causes unsoundness as it's possible to implement
839844
// `Clone` for mutable references.
@@ -1169,7 +1174,7 @@ impl<P: DerefMut> Pin<P> {
11691174
///
11701175
/// This overwrites pinned data, but that is okay: the original pinned value's destructor gets
11711176
/// run before being overwritten and the new value is also a valid value of the same type, so
1172-
/// no pinning invariant is violated. See [the `pin` module documentation][self#subtle-details]
1177+
/// no pinning invariant is violated. See [the `pin` module documentation][subtle-details]
11731178
/// for more information on how this upholds the pinning invariants.
11741179
///
11751180
/// # Example
@@ -1183,6 +1188,8 @@ impl<P: DerefMut> Pin<P> {
11831188
/// pinned.set(10);
11841189
/// println!("{}", pinned); // 10
11851190
/// ```
1191+
///
1192+
/// [subtle-details]: self#subtle-details-and-the-drop-guarantee
11861193
#[stable(feature = "pin", since = "1.33.0")]
11871194
#[inline(always)]
11881195
pub fn set(&mut self, value: P::Target)

0 commit comments

Comments
 (0)