|
24 | 24 | //! self-references and other special behaviors that are only possible for unmovable
|
25 | 25 | //! values.
|
26 | 26 | //!
|
27 |
| -//! It is worth reiterating that [`Pin`] does *not* change the fact that the Rust compiler |
| 27 | +//! It is worth reiterating that [`Pin`] does *not* change the fact that a Rust compiler |
28 | 28 | //! considers all types movable. [`mem::swap`] remains callable for any `T`. Instead, `Pin`
|
29 | 29 | //! prevents certain *values* (pointed to by pointers wrapped in `Pin`) from being
|
30 | 30 | //! moved by making it impossible to call methods like [`mem::swap`] on them.
|
|
39 | 39 | //!
|
40 | 40 | //! Note that pinning and `Unpin` only affect the pointed-to type, not the pointer
|
41 | 41 | //! type itself that got wrapped in `Pin`. For example, whether or not `Box<T>` is
|
42 |
| -//! `Unpin` has no affect on the behavior of `Pin<Box<T>>` (here, `T` is the |
| 42 | +//! `Unpin` has no effect on the behavior of `Pin<Box<T>>` (here, `T` is the |
43 | 43 | //! pointed-to type).
|
44 | 44 | //!
|
45 | 45 | //! # Examples
|
|
110 | 110 | //!
|
111 | 111 | //! The purpose of this guarantee is to allow data structures that store pointers
|
112 | 112 | //! to pinned data. For example, in an intrusive doubly-linked list, every element
|
113 |
| -//! will have pointers to its predecessor and successor in the list. Every element |
114 |
| -//! will be pinned, because moving the elements around would invalidate the pointers. |
| 113 | +//! has pointers to its predecessor and successor in the list. Every element |
| 114 | +//! must also be pinned, because moving the elements around would invalidate the pointers. |
115 | 115 | //! Moreover, the `Drop` implementation of a linked list element will patch the pointers
|
116 | 116 | //! of its predecessor and successor to remove itself from the list. Clearly, if an element
|
117 | 117 | //! could be deallocated or overwritten without calling `drop`, the pointers into it
|
118 | 118 | //! from its neighbouring elements would become invalid, which would break the data structure.
|
119 | 119 | //!
|
120 | 120 | //! Notice that this guarantee does *not* mean that memory does not leak! It is still
|
121 | 121 | //! completely okay not to ever call `drop` on a pinned element (e.g., you can still
|
122 |
| -//! call [`mem::forget`] on a `Pin<Box<T>>`). What you may not do is free or reuse the storage |
| 122 | +//! call [`mem::forget`] on a `Pin<Box<T>>`). However you may *not* then free or reuse the storage |
123 | 123 | //! without calling `drop`.
|
124 | 124 | //!
|
125 | 125 | //! # `Drop` implementation
|
126 | 126 | //!
|
127 | 127 | //! If your type relies on pinning (for example, because it contains internal
|
128 | 128 | //! references, or because you are implementing something like the intrusive
|
129 | 129 | //! doubly-linked list mentioned in the previous section), you have to be careful
|
130 |
| -//! when implementing `Drop`: notice that `drop` takes `&mut self`, but this |
131 |
| -//! will be called even if your type was previously pinned! It is as if the |
| 130 | +//! when implementing `Drop`. The `drop` function takes `&mut self`, but this |
| 131 | +//! is called *even if your type was previously pinned*! It is as if the |
132 | 132 | //! compiler automatically called `get_unchecked_mut`. This can never cause
|
133 | 133 | //! a problem in safe code because implementing a type that relies on pinning
|
134 | 134 | //! requires unsafe code, but be aware that deciding to make use of pinning
|
|
140 | 140 | //! # Projections and Structural Pinning
|
141 | 141 | //!
|
142 | 142 | //! One interesting question arises when considering pinning and "container types" --
|
143 |
| -//! types such as `Vec` or `Box` but also `RefCell`; types that serve as wrappers |
| 143 | +//! types such as `Vec`, `Box`, or `RefCell`; types that serve as wrappers |
144 | 144 | //! around other types. When can such a type have a "projection" operation, an
|
145 | 145 | //! operation with type `fn(Pin<&[mut] Container<T>>) -> Pin<&[mut] T>`?
|
146 | 146 | //! This does not just apply to generic container types, even for normal structs
|
|
170 | 170 | //! moved around when they are dropped to properly align them, which is in conflict with
|
171 | 171 | //! claiming that the fields are pinned when your struct is.
|
172 | 172 | //! 4. You must make sure that you uphold the [`Drop` guarantee][drop-guarantee]:
|
173 |
| -//! you must make sure that, once your container is pinned, the memory containing the |
| 173 | +//! once your container is pinned, the memory that contains the |
174 | 174 | //! content is not overwritten or deallocated without calling the content's destructors.
|
175 | 175 | //! This can be tricky, as witnessed by `VecDeque`: the destructor of `VecDeque` can fail
|
176 | 176 | //! to call `drop` on all elements if one of the destructors panics. This violates the
|
|
186 | 186 | //! which can be used with [`mem::swap`].
|
187 | 187 | //!
|
188 | 188 | //! On the other hand, if you decide *not* to offer any pinning projections, you
|
189 |
| -//! are free to do `impl<T> Unpin for Container<T>`. In the standard library, |
190 |
| -//! we do this for all pointer types: `Box<T>: Unpin` holds for all `T`. |
191 |
| -//! It makes a lot of sense to do this for pointer types, because moving the `Box<T>` |
| 189 | +//! are free to `impl<T> Unpin for Container<T>`. In the standard library, |
| 190 | +//! this is done for all pointer types: `Box<T>: Unpin` holds for all `T`. |
| 191 | +//! It makes sense to do this for pointer types, because moving the `Box<T>` |
192 | 192 | //! does not actually move the `T`: the `Box<T>` can be freely movable even if the `T`
|
193 | 193 | //! is not. In fact, even `Pin<Box<T>>` and `Pin<&mut T>` are always `Unpin` themselves,
|
194 | 194 | //! for the same reason.
|
|
0 commit comments