|
2 | 2 | //!
|
3 | 3 | //! It is sometimes useful to have objects that are guaranteed to not move,
|
4 | 4 | //! in the sense that their placement in memory does not change, and can thus be relied upon.
|
5 |
| -//! |
6 | 5 | //! A prime example of such a scenario would be building self-referential structs,
|
7 | 6 | //! since moving an object with pointers to itself will invalidate them,
|
8 | 7 | //! which could cause undefined behavior.
|
9 | 8 | //!
|
| 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 | +//! |
10 | 13 | //! 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 | +//! ``` |
26 | 29 | //!
|
27 | 30 | //! It is worth reiterating that [`Pin`] does *not* change the fact that a Rust compiler
|
28 | 31 | //! considers all types movable. [`mem::swap`] remains callable for any `T`. Instead, `Pin`
|
29 | 32 | //! 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. |
32 | 34 | //!
|
33 | 35 | //! # `Unpin`
|
34 | 36 | //!
|
|
43 | 45 | //! `Unpin` has no effect on the behavior of `Pin<Box<T>>` (here, `T` is the
|
44 | 46 | //! pointed-to type).
|
45 | 47 | //!
|
46 |
| -//! # Example: Self-referential struct |
| 48 | +//! # Example: self-referential struct |
47 | 49 | //!
|
48 | 50 | //! ```rust
|
49 | 51 | //! use std::pin::Pin;
|
|
119 | 121 | //! To make this work, not just moving the data is restricted; deallocating, repurposing or
|
120 | 122 | //! otherwise invalidating the memory used to store the data is restricted, too.
|
121 | 123 | //! 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 |
123 | 125 | //! when `drop` is called*. Memory can be invalidated by deallocation, but also by
|
124 | 126 | //! replacing a `Some(v)` by `None`, or calling `Vec::set_len` to "kill" some elements
|
125 | 127 | //! off of a vector.
|
@@ -318,13 +320,13 @@ impl<P: Deref> Pin<P> {
|
318 | 320 | /// # Safety
|
319 | 321 | ///
|
320 | 322 | /// 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 |
322 | 325 | /// not guarantee that the data `P` points to is pinned, constructing a
|
323 | 326 | /// `Pin<P>` is unsafe. In particular, calling `Pin::new_unchecked`
|
324 | 327 | /// on an `&'a mut T` is unsafe because while you are able to pin it for the given
|
325 | 328 | /// 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`). |
328 | 330 | ///
|
329 | 331 | /// By using this method, you are making a promise about the `P::Deref` and
|
330 | 332 | /// `P::DerefMut` implementations, if they exist. Most importantly, they
|
|
0 commit comments