|
138 | 138 | //! To make this work, not just moving the data is restricted; deallocating, repurposing, or
|
139 | 139 | //! otherwise invalidating the memory used to store the data is restricted, too.
|
140 | 140 | //! Concretely, for pinned data you have to maintain the invariant
|
141 |
| -//! that *its memory will not get invalidated from the moment it gets pinned until |
| 141 | +//! that *its memory will not get invalidated or repurposed from the moment it gets pinned until |
142 | 142 | //! when `drop` is called*. Memory can be invalidated by deallocation, but also by
|
143 | 143 | //! replacing a [`Some(v)`] by [`None`], or calling [`Vec::set_len`] to "kill" some elements
|
144 |
| -//! off of a vector. |
| 144 | +//! off of a vector. It can be repurposed by using [`ptr::write`] to overwrite it without |
| 145 | +//! calling the destructor first. |
145 | 146 | //!
|
146 | 147 | //! This is exactly the kind of guarantee that the intrusive linked list from the previous
|
147 | 148 | //! section needs to function correctly.
|
|
166 | 167 | //! implementation as well: if an element of your type could have been pinned,
|
167 | 168 | //! you must treat Drop as implicitly taking `Pin<&mut Self>`.
|
168 | 169 | //!
|
169 |
| -//! In particular, if your type is `#[repr(packed)]`, the compiler will automatically |
| 170 | +//! For example, you could implement `Drop` as follows: |
| 171 | +//! ```rust,no_run |
| 172 | +//! # use std::pin::Pin; |
| 173 | +//! # struct Type { } |
| 174 | +//! impl Drop for Type { |
| 175 | +//! fn drop(&mut self) { |
| 176 | +//! // `new_unchecked` is okay because we know this value is never used |
| 177 | +//! // again after being dropped. |
| 178 | +//! inner_drop(unsafe { Pin::new_unchecked(self)}); |
| 179 | +//! fn inner_drop(this: Pin<&mut Type>) { |
| 180 | +//! // Actual drop code goes here. |
| 181 | +//! } |
| 182 | +//! } |
| 183 | +//! } |
| 184 | +//! ``` |
| 185 | +//! The function `inner_drop` has the type that `drop` *should* have, so this makes sure that |
| 186 | +//! you do not accidentally use `self`/`this` in a way that is in conflict with pinning. |
| 187 | +//! |
| 188 | +//! Moreover, if your type is `#[repr(packed)]`, the compiler will automatically |
170 | 189 | //! move fields around to be able to drop them. As a consequence, you cannot use
|
171 | 190 | //! pinning with a `#[repr(packed)]` type.
|
172 | 191 | //!
|
173 | 192 | //! # Projections and Structural Pinning
|
174 | 193 | //!
|
175 |
| -//! One interesting question arises when considering the interaction of pinning |
176 |
| -//! and the fields of a struct. When can a struct have a "pinning projection", |
177 |
| -//! i.e., an operation with type `fn(Pin<&Struct>) -> Pin<&Field>`? In a |
178 |
| -//! similar vein, when can a generic wrapper type (such as `Vec<T>`, `Box<T>`, |
179 |
| -//! or `RefCell<T>`) have an operation with type `fn(Pin<&Wrapper<T>>) -> |
180 |
| -//! Pin<&T>`? |
181 |
| -//! |
182 |
| -//! Note: For the entirety of this discussion, the same applies for mutable references as it |
183 |
| -//! does for shared references. |
| 194 | +//! When working with pinned structs, the question arises how one can access the |
| 195 | +//! fields of that struct in a method that takes just `Pin<&mut Struct>`. |
| 196 | +//! The usual approach is to write helper methods (so called *projections*) |
| 197 | +//! that turn `Pin<&mut Struct>` into a reference to the field, but what |
| 198 | +//! type should that reference have? Is it `Pin<&mut Field>` or `&mut Field`? |
| 199 | +//! The same question arises with the fields of an `enum`, and also when considering |
| 200 | +//! container/wrapper types such as [`Vec<T>`], [`Box<T>`], or [`RefCell<T>`]. |
| 201 | +//! (This question applies to both mutable and shared references, we just |
| 202 | +//! use the more common case of mutable references here for illustration.) |
| 203 | +//! |
| 204 | +//! It turns out that it is actually up to the author of the data structure |
| 205 | +//! to decide whether the pinned projection for a particular field turns |
| 206 | +//! `Pin<&mut Struct>` into `Pin<&mut Field>` or `&mut Field`. There are some |
| 207 | +//! constraints though, and the most important constraint is *consistency*: |
| 208 | +//! every field can be *either* projected to a pinned reference, *or* have |
| 209 | +//! pinning removed as part of the projection. If both are done for the same field, |
| 210 | +//! that will likely be unsound! |
| 211 | +//! |
| 212 | +//! As the author of a data structure you get to decide for each field whether pinning |
| 213 | +//! "propagates" to this field or not. Pinning that propagates is also called "structural", |
| 214 | +//! because it follows the structure of the type. |
| 215 | +//! In the following subsections, we describe the considerations that have to be made |
| 216 | +//! for either choice. |
| 217 | +//! |
| 218 | +//! ## Pinning *is not* structural for `field` |
| 219 | +//! |
| 220 | +//! It may seem counter-intuitive that the field of a pinned struct might not be pinned, |
| 221 | +//! but that is actually the easiest choice: if a `Pin<&mut Field>` is never created, |
| 222 | +//! nothing can go wrong! So, if you decide that some field does not have structural pinning, |
| 223 | +//! all you have to ensure is that you never create a pinned reference to that field. |
| 224 | +//! |
| 225 | +//! Fields without structural pinning may have a projection method that turns |
| 226 | +//! `Pin<&mut Struct>` into `&mut Field`: |
| 227 | +//! ```rust,no_run |
| 228 | +//! # use std::pin::Pin; |
| 229 | +//! # type Field = i32; |
| 230 | +//! # struct Struct { field: Field } |
| 231 | +//! impl Struct { |
| 232 | +//! fn pin_get_field<'a>(self: Pin<&'a mut Self>) -> &'a mut Field { |
| 233 | +//! // This is okay because `field` is never considered pinned. |
| 234 | +//! unsafe { &mut self.get_unchecked_mut().field } |
| 235 | +//! } |
| 236 | +//! } |
| 237 | +//! ``` |
184 | 238 | //!
|
185 |
| -//! Having a pinning projection for some field means that pinning is "structural": |
186 |
| -//! when the wrapper is pinned, the field must be considered pinned, too. |
187 |
| -//! After all, the pinning projection lets us get a `Pin<&Field>`. |
| 239 | +//! You may also `impl Unpin for Struct` *even if* the type of `field` |
| 240 | +//! is not `Unpin`. What that type thinks about pinning is not relevant |
| 241 | +//! when no `Pin<&mut Field>` is ever created. |
| 242 | +//! |
| 243 | +//! ## Pinning *is* structural for `field` |
| 244 | +//! |
| 245 | +//! The other option is to decide that pinning is "structural" for `field`, |
| 246 | +//! meaning that if the struct is pinned then so is the field. |
| 247 | +//! |
| 248 | +//! This allows writing a projection that creates a `Pin<&mut Field>`, thus |
| 249 | +//! witnessing that the field is pinned: |
| 250 | +//! ```rust,no_run |
| 251 | +//! # use std::pin::Pin; |
| 252 | +//! # type Field = i32; |
| 253 | +//! # struct Struct { field: Field } |
| 254 | +//! impl Struct { |
| 255 | +//! fn pin_get_field<'a>(self: Pin<&'a mut Self>) -> Pin<&'a mut Field> { |
| 256 | +//! // This is okay because `field` is pinned when `self` is. |
| 257 | +//! unsafe { self.map_unchecked_mut(|s| &mut s.field) } |
| 258 | +//! } |
| 259 | +//! } |
| 260 | +//! ``` |
188 | 261 | //!
|
189 |
| -//! However, structural pinning comes with a few extra requirements, so not all |
190 |
| -//! wrappers can be structural and hence not all wrappers can offer pinning projections: |
| 262 | +//! However, structural pinning comes with a few extra requirements: |
191 | 263 | //!
|
192 |
| -//! 1. The wrapper must only be [`Unpin`] if all the structural fields are |
| 264 | +//! 1. The struct must only be [`Unpin`] if all the structural fields are |
193 | 265 | //! `Unpin`. This is the default, but `Unpin` is a safe trait, so as the author of
|
194 |
| -//! the wrapper it is your responsibility *not* to add something like |
195 |
| -//! `impl<T> Unpin for Wrapper<T>`. (Notice that adding a projection operation |
| 266 | +//! the struct it is your responsibility *not* to add something like |
| 267 | +//! `impl<T> Unpin for Struct<T>`. (Notice that adding a projection operation |
196 | 268 | //! requires unsafe code, so the fact that `Unpin` is a safe trait does not break
|
197 | 269 | //! the principle that you only have to worry about any of this if you use `unsafe`.)
|
198 |
| -//! 2. The destructor of the wrapper must not move structural fields out of its argument. This |
| 270 | +//! 2. The destructor of the struct must not move structural fields out of its argument. This |
199 | 271 | //! is the exact point that was raised in the [previous section][drop-impl]: `drop` takes
|
200 |
| -//! `&mut self`, but the wrapper (and hence its fields) might have been pinned before. |
| 272 | +//! `&mut self`, but the struct (and hence its fields) might have been pinned before. |
201 | 273 | //! You have to guarantee that you do not move a field inside your `Drop` implementation.
|
202 |
| -//! In particular, as explained previously, this means that your wrapper type must *not* |
| 274 | +//! In particular, as explained previously, this means that your struct must *not* |
203 | 275 | //! be `#[repr(packed)]`.
|
| 276 | +//! See that section for how to write `drop` in a way that the compiler can help you |
| 277 | +//! not accidentally break pinning. |
204 | 278 | //! 3. You must make sure that you uphold the [`Drop` guarantee][drop-guarantee]:
|
205 |
| -//! once your wrapper is pinned, the memory that contains the |
| 279 | +//! once your struct is pinned, the memory that contains the |
206 | 280 | //! content is not overwritten or deallocated without calling the content's destructors.
|
207 |
| -//! This can be tricky, as witnessed by `VecDeque<T>`: the destructor of `VecDeque<T>` can fail |
208 |
| -//! to call `drop` on all elements if one of the destructors panics. This violates the |
| 281 | +//! This can be tricky, as witnessed by [`VecDeque<T>`]: the destructor of `VecDeque<T>` |
| 282 | +//! can fail to call `drop` on all elements if one of the destructors panics. This violates the |
209 | 283 | //! `Drop` guarantee, because it can lead to elements being deallocated without
|
210 | 284 | //! their destructor being called. (`VecDeque` has no pinning projections, so this
|
211 | 285 | //! does not cause unsoundness.)
|
212 | 286 | //! 4. You must not offer any other operations that could lead to data being moved out of
|
213 |
| -//! the fields when your type is pinned. For example, if the wrapper contains an |
| 287 | +//! the structural fields when your type is pinned. For example, if the struct contains an |
214 | 288 | //! `Option<T>` and there is a `take`-like operation with type
|
215 |
| -//! `fn(Pin<&mut Wrapper<T>>) -> Option<T>`, |
216 |
| -//! that operation can be used to move a `T` out of a pinned `Wrapper<T>` -- which means |
217 |
| -//! pinning cannot be structural. |
| 289 | +//! `fn(Pin<&mut Struct<T>>) -> Option<T>`, |
| 290 | +//! that operation can be used to move a `T` out of a pinned `Struct<T>` -- which means |
| 291 | +//! pinning cannot be structural for the field holding this data. |
218 | 292 | //!
|
219 |
| -//! For a more complex example of moving data out of a pinned type, imagine if `RefCell<T>` |
| 293 | +//! For a more complex example of moving data out of a pinned type, imagine if [`RefCell<T>`] |
220 | 294 | //! had a method `fn get_pin_mut(self: Pin<&mut Self>) -> Pin<&mut T>`.
|
221 | 295 | //! Then we could do the following:
|
222 | 296 | //! ```compile_fail
|
|
231 | 305 | //! (using `RefCell::get_pin_mut`) and then move that content using the mutable
|
232 | 306 | //! reference we got later.
|
233 | 307 | //!
|
234 |
| -//! For a type like `Vec<T>`, both possibilites (structural pinning or not) make sense, |
235 |
| -//! and the choice is up to the author. A `Vec<T>` with structural pinning could |
236 |
| -//! have `get_pin`/`get_pin_mut` projections. However, it could *not* allow calling |
| 308 | +//! ## Examples |
| 309 | +//! |
| 310 | +//! For a type like [`Vec<T>`], both possibilites (structural pinning or not) make sense. |
| 311 | +//! A `Vec<T>` with structural pinning could have `get_pin`/`get_pin_mut` methods to get |
| 312 | +//! pinned references to elements. However, it could *not* allow calling |
237 | 313 | //! `pop` on a pinned `Vec<T>` because that would move the (structurally pinned) contents!
|
238 | 314 | //! Nor could it allow `push`, which might reallocate and thus also move the contents.
|
239 | 315 | //! A `Vec<T>` without structural pinning could `impl<T> Unpin for Vec<T>`, because the contents
|
240 | 316 | //! are never pinned and the `Vec<T>` itself is fine with being moved as well.
|
| 317 | +//! At that point pinning just has no effect on the vector at all. |
241 | 318 | //!
|
242 | 319 | //! In the standard library, pointer types generally do not have structural pinning,
|
243 | 320 | //! and thus they do not offer pinning projections. This is why `Box<T>: Unpin` holds for all `T`.
|
|
249 | 326 | //! whether the content is pinned is entirely independent of whether the pointer is
|
250 | 327 | //! pinned, meaning pinning is *not* structural.
|
251 | 328 | //!
|
| 329 | +//! When implementing a [`Future`] combinator, you will usually need structural pinning |
| 330 | +//! for the nested futures, as you need to get pinned references to them to call `poll`. |
| 331 | +//! But if your combinator contains any other data that does not need to be pinned, |
| 332 | +//! you can make those fields not structural and hence freely access them with a |
| 333 | +//! mutable reference even when you just have `Pin<&mut Self>` (such as in your own |
| 334 | +//! `poll` implementation). |
| 335 | +//! |
252 | 336 | //! [`Pin<P>`]: struct.Pin.html
|
253 |
| -//! [`Unpin`]: ../../std/marker/trait.Unpin.html |
254 |
| -//! [`Deref`]: ../../std/ops/trait.Deref.html |
255 |
| -//! [`DerefMut`]: ../../std/ops/trait.DerefMut.html |
256 |
| -//! [`mem::swap`]: ../../std/mem/fn.swap.html |
257 |
| -//! [`mem::forget`]: ../../std/mem/fn.forget.html |
| 337 | +//! [`Unpin`]: ../marker/trait.Unpin.html |
| 338 | +//! [`Deref`]: ../ops/trait.Deref.html |
| 339 | +//! [`DerefMut`]: ../ops/trait.DerefMut.html |
| 340 | +//! [`mem::swap`]: ../mem/fn.swap.html |
| 341 | +//! [`mem::forget`]: ../mem/fn.forget.html |
258 | 342 | //! [`Box<T>`]: ../../std/boxed/struct.Box.html
|
| 343 | +//! [`Vec<T>`]: ../../std/vec/struct.Vec.html |
259 | 344 | //! [`Vec::set_len`]: ../../std/vec/struct.Vec.html#method.set_len
|
260 |
| -//! [`None`]: ../../std/option/enum.Option.html#variant.None |
261 |
| -//! [`Some(v)`]: ../../std/option/enum.Option.html#variant.Some |
| 345 | +//! [`VecDeque<T>`]: ../../std/collections/struct.VecDeque.html |
| 346 | +//! [`RefCell<T>`]: ../cell/struct.RefCell.html |
| 347 | +//! [`None`]: ../option/enum.Option.html#variant.None |
| 348 | +//! [`Some(v)`]: ../option/enum.Option.html#variant.Some |
| 349 | +//! [`ptr::write`]: ../ptr/fn.write.html |
| 350 | +//! [`Future`]: ../future/trait.Future.html |
262 | 351 | //! [drop-impl]: #drop-implementation
|
263 | 352 | //! [drop-guarantee]: #drop-guarantee
|
264 | 353 |
|
|
0 commit comments