|
1 | 1 | //! Types that pin data to its location in memory.
|
2 | 2 | //!
|
3 |
| -//! It is sometimes useful to have objects that are guaranteed to not move, |
| 3 | +//! It is sometimes useful to have objects that are guaranteed not to move, |
4 | 4 | //! in the sense that their placement in memory does not change, and can thus be relied upon.
|
5 | 5 | //! A prime example of such a scenario would be building self-referential structs,
|
6 |
| -//! since moving an object with pointers to itself will invalidate them, |
7 |
| -//! which could cause undefined behavior. |
| 6 | +//! as moving an object with pointers to itself will invalidate them, which could cause undefined |
| 7 | +//! behavior. |
8 | 8 | //!
|
9 | 9 | //! A [`Pin<P>`] ensures that the pointee of any pointer type `P` has a stable location in memory,
|
10 | 10 | //! meaning it cannot be moved elsewhere and its memory cannot be deallocated
|
|
15 | 15 | //! moving the values they contain: you can move out of a `Box<T>`, or you can use [`mem::swap`].
|
16 | 16 | //! [`Pin<P>`] wraps a pointer type `P`, so `Pin<Box<T>>` functions much like a regular `Box<T>`:
|
17 | 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<P>`] does not let clients |
| 18 | +//! Similarly, `Pin<&mut T>` is a lot like `&mut T`. However, [`Pin<P>`] does not let clients |
19 | 19 | //! actually obtain a `Box<T>` or `&mut T` to pinned data, which implies that you cannot use
|
20 | 20 | //! operations such as [`mem::swap`]:
|
| 21 | +//! |
21 | 22 | //! ```
|
22 | 23 | //! use std::pin::Pin;
|
23 | 24 | //! fn swap_pins<T>(x: Pin<&mut T>, y: Pin<&mut T>) {
|
|
39 | 40 | //! as a "`P`-style pointer" to a pinned `P::Target` -- so, a `Pin<Box<T>>` is
|
40 | 41 | //! an owned pointer to a pinned `T`, and a `Pin<Rc<T>>` is a reference-counted
|
41 | 42 | //! pointer to a pinned `T`.
|
42 |
| -//! For correctness, [`Pin<P>`] relies on the [`Deref`] and [`DerefMut`] implementations |
43 |
| -//! to not move out of their `self` parameter, and to only ever return a pointer |
44 |
| -//! to pinned data when they are called on a pinned pointer. |
| 43 | +//! For correctness, [`Pin<P>`] relies on the implementations of [`Deref`] and |
| 44 | +//! [`DerefMut`] not to move out of their `self` parameter, and only ever to |
| 45 | +//! return a pointer to pinned data when they are called on a pinned pointer. |
45 | 46 | //!
|
46 | 47 | //! # `Unpin`
|
47 | 48 | //!
|
48 |
| -//! However, these restrictions are usually not necessary. Many types are always freely |
49 |
| -//! movable, even when pinned, because they do not rely on having a stable address. |
50 |
| -//! This includes all the basic types (like `bool`, `i32`, references) |
51 |
| -//! as well as types consisting solely of these types. |
52 |
| -//! Types that do not care about pinning implement the [`Unpin`] auto-trait, which |
53 |
| -//! cancels the effect of [`Pin<P>`]. For `T: Unpin`, `Pin<Box<T>>` and `Box<T>` function |
54 |
| -//! identically, as do `Pin<&mut T>` and `&mut T`. |
| 49 | +//! Many types are always freely movable, even when pinned, because they do not |
| 50 | +//! rely on having a stable address. This includes all the basic types (like |
| 51 | +//! `bool`, `i32`, and references) as well as types consisting solely of these |
| 52 | +//! types. Types that do not care about pinning implement the [`Unpin`] |
| 53 | +//! auto-trait, which cancels the effect of [`Pin<P>`]. For `T: Unpin`, |
| 54 | +//! `Pin<Box<T>>` and `Box<T>` function identically, as do `Pin<&mut T>` and |
| 55 | +//! `&mut T`. |
55 | 56 | //!
|
56 | 57 | //! Note that pinning and `Unpin` only affect the pointed-to type `P::Target`, not the pointer
|
57 | 58 | //! type `P` itself that got wrapped in `Pin<P>`. For example, whether or not `Box<T>` is
|
|
65 | 66 | //! use std::marker::PhantomPinned;
|
66 | 67 | //! use std::ptr::NonNull;
|
67 | 68 | //!
|
68 |
| -//! // This is a self-referential struct since the slice field points to the data field. |
| 69 | +//! // This is a self-referential struct because the slice field points to the data field. |
69 | 70 | //! // We cannot inform the compiler about that with a normal reference,
|
70 |
| -//! // since this pattern cannot be described with the usual borrowing rules. |
71 |
| -//! // Instead we use a raw pointer, though one which is known to not be null, |
72 |
| -//! // since we know it's pointing at the string. |
| 71 | +//! // as this pattern cannot be described with the usual borrowing rules. |
| 72 | +//! // Instead we use a raw pointer, though one which is known not to be null, |
| 73 | +//! // as we know it's pointing at the string. |
73 | 74 | //! struct Unmovable {
|
74 | 75 | //! data: String,
|
75 | 76 | //! slice: NonNull<String>,
|
|
146 | 147 | //! section needs to function correctly.
|
147 | 148 | //!
|
148 | 149 | //! Notice that this guarantee does *not* mean that memory does not leak! It is still
|
149 |
| -//! completely okay not to ever call `drop` on a pinned element (e.g., you can still |
| 150 | +//! completely okay not ever to call `drop` on a pinned element (e.g., you can still |
150 | 151 | //! call [`mem::forget`] on a `Pin<Box<T>>`). In the example of the doubly-linked
|
151 | 152 | //! list, that element would just stay in the list. However you may not free or reuse the storage
|
152 | 153 | //! *without calling `drop`*.
|
|
192 | 193 | //! `Unpin`. This is the default, but `Unpin` is a safe trait, so as the author of
|
193 | 194 | //! the wrapper it is your responsibility *not* to add something like
|
194 | 195 | //! `impl<T> Unpin for Wrapper<T>`. (Notice that adding a projection operation
|
195 |
| -//! requires unsafe code, so the fact that `Unpin` is a safe trait does not break |
| 196 | +//! requires unsafe code, so the fact that `Unpin` is a safe trait does not break |
196 | 197 | //! the principle that you only have to worry about any of this if you use `unsafe`.)
|
197 | 198 | //! 2. The destructor of the wrapper must not move structural fields out of its argument. This
|
198 | 199 | //! is the exact point that was raised in the [previous section][drop-impl]: `drop` takes
|
|
0 commit comments