Skip to content

Commit 3040380

Browse files
committed
rewrite pin module intro
1 parent 0ba99f6 commit 3040380

File tree

2 files changed

+27
-24
lines changed

2 files changed

+27
-24
lines changed

src/libcore/marker.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -610,7 +610,8 @@ unsafe impl<T: ?Sized> Freeze for &mut T {}
610610
/// which then allows it to move out with functions such as [`mem::replace`].
611611
///
612612
/// `Unpin` has no consequence at all for non-pinned data. In particular,
613-
/// [`mem::replace`] happily moves `!Unpin` data. However, you cannot use
613+
/// [`mem::replace`] happily moves `!Unpin` data (it works for any `&mut T`, not
614+
/// just when `T: Unpin`). However, you cannot use
614615
/// [`mem::replace`] on data wrapped inside a [`Pin`] because you cannot get the
615616
/// `&mut T` you need for that, and *that* is what makes this system work.
616617
///

src/libcore/pin.rs

Lines changed: 25 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2,33 +2,35 @@
22
//!
33
//! It is sometimes useful to have objects that are guaranteed to not move,
44
//! in the sense that their placement in memory does not change, and can thus be relied upon.
5-
//!
65
//! A prime example of such a scenario would be building self-referential structs,
76
//! since moving an object with pointers to itself will invalidate them,
87
//! which could cause undefined behavior.
98
//!
9+
//! [`Pin`] ensures that the pointee of any pointer type has a stable location in memory,
10+
//! meaning it cannot be moved elsewhere and its memory cannot be deallocated
11+
//! until it gets dropped. We say that the pointee is "pinned".
12+
//!
1013
//! By default, all types in Rust are movable. Rust allows passing all types by-value,
11-
//! and common smart-pointer types such as `Box`, `Rc`, and `&mut` allow replacing and
12-
//! moving the values they contain. In order to prevent objects from moving, they must
13-
//! be pinned by wrapping a pointer to the data in the [`Pin`] type.
14-
//! Doing this prohibits moving the value behind the pointer.
15-
//! For example, `Pin<Box<T>>` functions much like a regular `Box<T>`,
16-
//! but doesn't allow moving `T`. The pointer value itself (the `Box`) can still be moved,
17-
//! but the value behind it cannot.
18-
//!
19-
//! Since data can be moved out of `&mut` and `Box` with functions such as [`mem::swap`],
20-
//! changing the location of the underlying data, [`Pin`] prohibits accessing the
21-
//! underlying pointer type (the `&mut` or `Box`) directly, and provides its own set of
22-
//! APIs for accessing and using the value. [`Pin`] also guarantees that no other
23-
//! functions will move the pointed-to value. This allows for the creation of
24-
//! self-references and other special behaviors that are only possible for unmovable
25-
//! values.
14+
//! and common smart-pointer types such as `Box` and `&mut` allow replacing and
15+
//! moving the values they contain: you can move out of a `Box`, or you can use [`mem::swap`].
16+
//! [`Pin`] wraps a pointer type, so `Pin<Box<T>>` functions much like a regular `Box<T>`
17+
//! (when a `Pin<Box<T>>` gets dropped, so do its contents, and the memory gets deallocated).
18+
//! Similarily, `Pin<&mut T>` is a lot like `&mut T`. However, [`Pin`] does not let clients actually
19+
//! obtain a `Box` or reference to pinned data, which implies that you cannot use
20+
//! operations such as [`mem::swap`]:
21+
//! ```
22+
//! fn swap_pins<T>(x: Pin<&mut T>, y: Pin<&mut T>) {
23+
//! // `mem::swap` needs `&mut T`, but we cannot get it.
24+
//! // We are stuck, we cannot swap the contents of these references.
25+
//! // We could use `Pin::get_unchecked_mut`, but that is unsafe for a reason:
26+
//! // we are not allowed to use it for moving things out of the `Pin`.
27+
//! }
28+
//! ```
2629
//!
2730
//! It is worth reiterating that [`Pin`] does *not* change the fact that a Rust compiler
2831
//! considers all types movable. [`mem::swap`] remains callable for any `T`. Instead, `Pin`
2932
//! prevents certain *values* (pointed to by pointers wrapped in `Pin`) from being
30-
//! moved by making it impossible to call methods like [`mem::swap`] on them. These
31-
//! methods all need an `&mut T`, and you cannot obtain that from a `Pin`.
33+
//! moved by making it impossible to call methods like [`mem::swap`] on them.
3234
//!
3335
//! # `Unpin`
3436
//!
@@ -43,7 +45,7 @@
4345
//! `Unpin` has no effect on the behavior of `Pin<Box<T>>` (here, `T` is the
4446
//! pointed-to type).
4547
//!
46-
//! # Example: Self-referential struct
48+
//! # Example: self-referential struct
4749
//!
4850
//! ```rust
4951
//! use std::pin::Pin;
@@ -119,7 +121,7 @@
119121
//! To make this work, not just moving the data is restricted; deallocating, repurposing or
120122
//! otherwise invalidating the memory used to store the data is restricted, too.
121123
//! Concretely, for pinned data you have to maintain the invariant
122-
//! that *its memory will not get invalidated from the momentit gets pinned until
124+
//! that *its memory will not get invalidated from the moment it gets pinned until
123125
//! when `drop` is called*. Memory can be invalidated by deallocation, but also by
124126
//! replacing a `Some(v)` by `None`, or calling `Vec::set_len` to "kill" some elements
125127
//! off of a vector.
@@ -318,13 +320,13 @@ impl<P: Deref> Pin<P> {
318320
/// # Safety
319321
///
320322
/// This constructor is unsafe because we cannot guarantee that the data
321-
/// pointed to by `pointer` is pinned forever. If the constructed `Pin<P>` does
323+
/// pointed to by `pointer` is pinned, meaning that the data will not be moved or
324+
/// its storage invalidated until it gets dropped. If the constructed `Pin<P>` does
322325
/// not guarantee that the data `P` points to is pinned, constructing a
323326
/// `Pin<P>` is unsafe. In particular, calling `Pin::new_unchecked`
324327
/// on an `&'a mut T` is unsafe because while you are able to pin it for the given
325328
/// lifetime `'a`, you have no control over whether it is kept pinned once `'a`
326-
/// ends. A value, once pinned, must remain pinned forever
327-
/// (unless its type implements `Unpin`).
329+
/// ends. A value, once pinned, must remain pinned forever (unless its type implements `Unpin`).
328330
///
329331
/// By using this method, you are making a promise about the `P::Deref` and
330332
/// `P::DerefMut` implementations, if they exist. Most importantly, they

0 commit comments

Comments
 (0)