about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNiv Kaminer <nivkner@zoho.com>2018-08-09 20:10:30 +0300
committerNiv Kaminer <nivkner@zoho.com>2018-08-23 01:37:03 +0300
commit30bb4af5d8191f016a82c75a0c2b4700b23bd724 (patch)
treeed9abea5606aa0f1f8ed0c3f5738b958311c5b2e
parent971d7ed24966e64c8ec8352ada433b672c25012f (diff)
downloadrust-30bb4af5d8191f016a82c75a0c2b4700b23bd724.tar.gz
rust-30bb4af5d8191f016a82c75a0c2b4700b23bd724.zip
add top-level documentation to the std pin module
-rw-r--r--src/liballoc/pin.rs4
-rw-r--r--src/libcore/pin.rs4
-rw-r--r--src/libstd/pin.rs81
3 files changed, 88 insertions, 1 deletions
diff --git a/src/liballoc/pin.rs b/src/liballoc/pin.rs
index 221a55472ab..1b6ccae456a 100644
--- a/src/liballoc/pin.rs
+++ b/src/liballoc/pin.rs
@@ -9,6 +9,10 @@
 // except according to those terms.
 
 //! Types which pin data to its location in memory
+//!
+//! see the [standard library module] for more information
+//!
+//! [standard library module]: ../../std/pin/index.html
 
 #![unstable(feature = "pin", issue = "49150")]
 
diff --git a/src/libcore/pin.rs b/src/libcore/pin.rs
index a41185e231b..74fb02d2e11 100644
--- a/src/libcore/pin.rs
+++ b/src/libcore/pin.rs
@@ -9,6 +9,10 @@
 // except according to those terms.
 
 //! Types which pin data to its location in memory
+//!
+//! see the [standard library module] for more information
+//!
+//! [standard library module]: ../../std/pin/index.html
 
 #![unstable(feature = "pin", issue = "49150")]
 
diff --git a/src/libstd/pin.rs b/src/libstd/pin.rs
index b3c5b5feb8c..0b78414e4bf 100644
--- a/src/libstd/pin.rs
+++ b/src/libstd/pin.rs
@@ -1,4 +1,4 @@
-// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -9,6 +9,85 @@
 // except according to those terms.
 
 //! Types which pin data to its location in memory
+//!
+//! It is sometimes useful to have objects that are guaranteed to not move,
+//! in the sense that their placement in memory in consistent, and can thus be relied upon.
+//!
+//! A prime example of such a scenario would be building self-referencial structs,
+//! since moving an object with pointers to itself will invalidate them,
+//! which could cause undefined behavior.
+//!
+//! In order to prevent objects from moving, they must be *pinned*,
+//! by wrapping the data in special pointer types, such as [`PinMut`] and [`PinBox`].
+//! These restrict access to the underlying data to only be immutable by implementing [`Deref`],
+//! unless the type implements the [`Unpin`] trait,
+//! which indicates that it doesn't need these restrictions and can be safely mutated,
+//! by implementing [`DerefMut`].
+//!
+//! This is done because, while modifying an object can be done in-place,
+//! it might also relocate a buffer when its at full capacity,
+//! or it might replace one object with another without logically "moving" them with [`swap`].
+//!
+//! [`PinMut`]: struct.PinMut.html
+//! [`PinBox`]: struct.PinBox.html
+//! [`Unpin`]: ../marker/trait.Unpin.html
+//! [`DerefMut`]: ../ops/trait.DerefMut.html
+//! [`Deref`]: ../ops/trait.Deref.html
+//! [`swap`]: ../mem/fn.swap.html
+//!
+//! # Examples
+//!
+//! ```rust
+//! #![feature(pin)]
+//!
+//! use std::pin::PinBox;
+//! use std::marker::Pinned;
+//! use std::ptr::NonNull;
+//!
+//! // This is a self referencial struct since the slice field points to the data field.
+//! // We cannot inform the compiler about that with a normal reference,
+//! // since this pattern cannot be described with the usual borrowing rules.
+//! // Instead we use a raw pointer, though one which is known to not be null,
+//! // since we know it's pointing at the string.
+//! struct Unmovable {
+//!     data: String,
+//!     slice: NonNull<String>,
+//!     _pin: Pinned,
+//! }
+//!
+//! impl Unmovable {
+//!     // To ensure the data doesn't move when the function returns,
+//!     // we place it in the heap where it will stay for the lifetime of the object,
+//!     // and the only way to access it would be through a pointer to it.
+//!     fn new(data: String) -> PinBox<Self> {
+//!         let res = Unmovable {
+//!             data,
+//!             // we only create the pointer once the data is in place
+//!             // otherwise it will have already moved before we even started
+//!             slice: NonNull::dangling(),
+//!             _pin: Pinned,
+//!         };
+//!         let mut boxed = PinBox::new(res);
+//!
+//!         let slice = NonNull::from(&boxed.data);
+//!         // we know this is safe because modifying a field doesn't move the whole struct
+//!         unsafe { PinBox::get_mut(&mut boxed).slice = slice };
+//!         boxed
+//!     }
+//! }
+//!
+//! let unmoved = Unmovable::new("hello".to_string());
+//! // The pointer should point to the correct location,
+//! // so long as the struct hasn't moved.
+//! // Meanwhile, we are free to move the pointer around.
+//! let mut still_unmoved = unmoved;
+//! assert_eq!(still_unmoved.slice, NonNull::from(&still_unmoved.data));
+//!
+//! // Now the only way to access to data (safely) is immutably,
+//! // so this will fail to compile:
+//! // still_unmoved.data.push_str(" world");
+//!
+//! ```
 
 #![unstable(feature = "pin", issue = "49150")]