Skip to content

Commit 30bb4af

Browse files
committed
add top-level documentation to the std pin module
1 parent 971d7ed commit 30bb4af

File tree

3 files changed

+88
-1
lines changed

3 files changed

+88
-1
lines changed

src/liballoc/pin.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@
99
// except according to those terms.
1010

1111
//! Types which pin data to its location in memory
12+
//!
13+
//! see the [standard library module] for more information
14+
//!
15+
//! [standard library module]: ../../std/pin/index.html
1216
1317
#![unstable(feature = "pin", issue = "49150")]
1418

src/libcore/pin.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@
99
// except according to those terms.
1010

1111
//! Types which pin data to its location in memory
12+
//!
13+
//! see the [standard library module] for more information
14+
//!
15+
//! [standard library module]: ../../std/pin/index.html
1216
1317
#![unstable(feature = "pin", issue = "49150")]
1418

src/libstd/pin.rs

Lines changed: 80 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
22
// file at the top-level directory of this distribution and at
33
// http://rust-lang.org/COPYRIGHT.
44
//
@@ -9,6 +9,85 @@
99
// except according to those terms.
1010

1111
//! Types which pin data to its location in memory
12+
//!
13+
//! It is sometimes useful to have objects that are guaranteed to not move,
14+
//! in the sense that their placement in memory in consistent, and can thus be relied upon.
15+
//!
16+
//! A prime example of such a scenario would be building self-referencial structs,
17+
//! since moving an object with pointers to itself will invalidate them,
18+
//! which could cause undefined behavior.
19+
//!
20+
//! In order to prevent objects from moving, they must be *pinned*,
21+
//! by wrapping the data in special pointer types, such as [`PinMut`] and [`PinBox`].
22+
//! These restrict access to the underlying data to only be immutable by implementing [`Deref`],
23+
//! unless the type implements the [`Unpin`] trait,
24+
//! which indicates that it doesn't need these restrictions and can be safely mutated,
25+
//! by implementing [`DerefMut`].
26+
//!
27+
//! This is done because, while modifying an object can be done in-place,
28+
//! it might also relocate a buffer when its at full capacity,
29+
//! or it might replace one object with another without logically "moving" them with [`swap`].
30+
//!
31+
//! [`PinMut`]: struct.PinMut.html
32+
//! [`PinBox`]: struct.PinBox.html
33+
//! [`Unpin`]: ../marker/trait.Unpin.html
34+
//! [`DerefMut`]: ../ops/trait.DerefMut.html
35+
//! [`Deref`]: ../ops/trait.Deref.html
36+
//! [`swap`]: ../mem/fn.swap.html
37+
//!
38+
//! # Examples
39+
//!
40+
//! ```rust
41+
//! #![feature(pin)]
42+
//!
43+
//! use std::pin::PinBox;
44+
//! use std::marker::Pinned;
45+
//! use std::ptr::NonNull;
46+
//!
47+
//! // This is a self referencial struct since the slice field points to the data field.
48+
//! // We cannot inform the compiler about that with a normal reference,
49+
//! // since this pattern cannot be described with the usual borrowing rules.
50+
//! // Instead we use a raw pointer, though one which is known to not be null,
51+
//! // since we know it's pointing at the string.
52+
//! struct Unmovable {
53+
//! data: String,
54+
//! slice: NonNull<String>,
55+
//! _pin: Pinned,
56+
//! }
57+
//!
58+
//! impl Unmovable {
59+
//! // To ensure the data doesn't move when the function returns,
60+
//! // we place it in the heap where it will stay for the lifetime of the object,
61+
//! // and the only way to access it would be through a pointer to it.
62+
//! fn new(data: String) -> PinBox<Self> {
63+
//! let res = Unmovable {
64+
//! data,
65+
//! // we only create the pointer once the data is in place
66+
//! // otherwise it will have already moved before we even started
67+
//! slice: NonNull::dangling(),
68+
//! _pin: Pinned,
69+
//! };
70+
//! let mut boxed = PinBox::new(res);
71+
//!
72+
//! let slice = NonNull::from(&boxed.data);
73+
//! // we know this is safe because modifying a field doesn't move the whole struct
74+
//! unsafe { PinBox::get_mut(&mut boxed).slice = slice };
75+
//! boxed
76+
//! }
77+
//! }
78+
//!
79+
//! let unmoved = Unmovable::new("hello".to_string());
80+
//! // The pointer should point to the correct location,
81+
//! // so long as the struct hasn't moved.
82+
//! // Meanwhile, we are free to move the pointer around.
83+
//! let mut still_unmoved = unmoved;
84+
//! assert_eq!(still_unmoved.slice, NonNull::from(&still_unmoved.data));
85+
//!
86+
//! // Now the only way to access to data (safely) is immutably,
87+
//! // so this will fail to compile:
88+
//! // still_unmoved.data.push_str(" world");
89+
//!
90+
//! ```
1291
1392
#![unstable(feature = "pin", issue = "49150")]
1493

0 commit comments

Comments
 (0)