|
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