|
1 | 1 | //! Types that pin data to a location in memory. |
2 | 2 | //! |
3 | 3 | //! It is sometimes useful to be able to rely upon a certain value not being able to *move*, |
4 | | -//! in the sense that its address in memory cannot change. This is useful specifically when there |
5 | | -//! are one or more *pointers* pointing at that value. The ability to rely on this guarantee that |
6 | | -//! the value a pointer is pointing at (its **pointee**) will |
| 4 | +//! in the sense that its address in memory cannot change. This is useful especially when there |
| 5 | +//! are one or more [*pointers*][pointer] pointing at that value. The ability to rely on this |
| 6 | +//! guarantee that the value a [pointer] is pointing at (its **pointee**) will |
7 | 7 | //! |
8 | 8 | //! 1. Not be *moved* out of its memory location |
9 | 9 | //! 2. More generally, remain *valid* at that same memory location |
10 | 10 | //! |
11 | | -//! is necessary to implement things like self-referential structs and intrusive data structures. |
12 | | -//! |
13 | | -//! "Pinning" allows us to put a value *which is being pointed at* by some pointer `Ptr` into a |
14 | | -//! state that prevents safe code from *moving* or otherwise invalidating the *pointee* value at |
15 | | -//! its location in memory (unless the pointee type implements [`Unpin`], which we'll |
16 | | -//! [discuss more below][self#unpin]). In this way, we can allow [`unsafe`] code to rely on the |
17 | | -//! pointer to be valid to dereference. |
| 11 | +//! is called "pinning." We would say that a value which satisfies these guarantees has been |
| 12 | +//! "pinned," in that it has been permanently (until the end of its lifetime) attached to its |
| 13 | +//! location in memory. Pinning a value is incredibly useful in that it provides the necessary |
| 14 | +//! guarantees[^guarantees] for [`unsafe`] code to be able to dereference raw pointers to the pinned |
| 15 | +//! value for the duration it is pinned (which, [as we'll see later][drop-guarantee], is necessarily |
| 16 | +//! from the time the value is first pinned until the end of its lifetime). This concept of |
| 17 | +//! "pinning" is necessary to implement safe interfaces on top of things like self-referential types |
| 18 | +//! and intrusive data structures which cannot currently be modeled in fully safe Rust using only |
| 19 | +//! borrow-checked [references][reference]. |
| 20 | +//! |
| 21 | +//! "Pinning" allows us to put a *value* which exists at some location in memory into a state where |
| 22 | +//! safe code cannot *move* that value to a different location in memory or otherwise invalidate it |
| 23 | +//! at its current location (unless it implements [`Unpin`], which we will |
| 24 | +//! [talk about below][unpin]). Anything that wants to interact with the pinned value in a way that |
| 25 | +//! has the potential to violate these guarantees must promise that it will not actually violate |
| 26 | +//! them, using the [`unsafe`] keyword to mark that such a promise is upheld by the user and not |
| 27 | +//! the compiler. In this way, we can allow other [`unsafe`] code to rely on any pointers that |
| 28 | +//! point to the pinned value to be valid to dereference while it is pinned. |
| 29 | +//! |
| 30 | +//! [^guarantees]: Pinning on its own does not provide *all* the invariants necessary here. However, |
| 31 | +//! in order to validly pin a value in the first place, it must already satisfy the other invariants |
| 32 | +//! for it to be valid to dereference a pointer to that value while it is pinned, and using the |
| 33 | +//! [`Drop` guarantee][drop-guarantee], we can ensure that any interested parties are notified |
| 34 | +//! before the value becomes no longer pinned, i.e. when the value goes out of scope and is |
| 35 | +//! invalidated. |
| 36 | +//! |
| 37 | +//! Note that as long as you don't use [`unsafe`], it's impossible to create or misuse a pinned |
| 38 | +//! value in a way that will produce unsoundness. See the documentation of [`Pin<Ptr>`] for more |
| 39 | +//! information on the practicalities of how to pin a value and how to use that pinned value from a |
| 40 | +//! user's perspective without using [`unsafe`]. |
18 | 41 | //! |
19 | 42 | //! The rest of this documentation is intended to be the source of truth for users of [`Pin<Ptr>`] |
20 | | -//! in unsafe code; users of [`Pin<Ptr>`] in safe code do not need to read it in detail. |
| 43 | +//! that are implementing the [`unsafe`] pieces of an interface that relies on pinning for validity; |
| 44 | +//! users of [`Pin<Ptr>`] in safe code do not need to read it in detail. |
21 | 45 | //! |
22 | 46 | //! There are several sections to this documentation: |
23 | 47 | //! |
24 | 48 | //! * [What is "*moving*"?][what-is-moving] |
25 | 49 | //! * [What is "pinning"?][what-is-pinning] |
| 50 | +//! * [Address sensitivity, AKA "when do we need pinning?"][address-sensitive-values] |
26 | 51 | //! * [Examples of types with address-sensitive states][address-sensitive-examples] |
27 | 52 | //! * [Self-referential struct][self-ref] |
28 | 53 | //! * [Intrusive, doubly-linked list][linked-list] |
|
90 | 115 | //! to remain *valid* and *located at the same place in memory* from the time it is pinned until its |
91 | 116 | //! [`drop`] is called. |
92 | 117 | //! |
93 | | -//! ## Address-sensitive values, AKA "why we need pinning" |
94 | | -//! [address-sensitive-values]: self#address-sensitive-values |
| 118 | +//! ## Address-sensitive values, AKA "when we need pinning" |
| 119 | +//! [address-sensitive-values]: self#address-sensitive-values-aka-when-we-need-pinning |
95 | 120 | //! |
96 | 121 | //! Most values in Rust are entirely okay with being *moved* around at-will. |
97 | 122 | //! Types for which it is *always* the case that *any* value of that type can be |
|
105 | 130 | //! |
106 | 131 | //! As a motivating example of a type which may become address-sensitive, consider a type which |
107 | 132 | //! contains a pointer to another piece of its own data, *i.e.* a "self-referential" type. In order |
108 | | -//! such a type to be implemented soundly, the pointer which points into `self`'s data must be |
| 133 | +//! for such a type to be implemented soundly, the pointer which points into `self`'s data must be |
109 | 134 | //! proven valid whenever it is accessed. But if that value is *moved*, the pointer will still |
110 | | -//! point to the old location that the value was located and not into the new location of `self`, |
| 135 | +//! point to the old address where the value was located and not into the new location of `self`, |
111 | 136 | //! thus becoming invalid. A key example of such self-referrential types are the state machines |
112 | 137 | //! generated by the compiler to implement [`Future`] for `async fn`s. |
113 | 138 | //! |
|
122 | 147 | //! assume that the address of the value is stable |
123 | 148 | //! * e.g. subsequent calls to [`poll`] |
124 | 149 | //! 4. Before the value is invalidated (e.g. deallocated), it is *dropped*, giving it a chance to |
125 | | -//! "unregister"/clear outstanding pointers to itself |
| 150 | +//! notify anything with pointers to itself that those pointers will be invalidated |
126 | 151 | //! * e.g. [`drop`]ping the [`Future`] |
127 | 152 | //! |
128 | 153 | //! There are two possible ways to ensure the invariants required for 2. and 3. above (which |
|
229 | 254 | //! #[derive(Default)] |
230 | 255 | //! struct AddrTracker { |
231 | 256 | //! prev_addr: Option<usize>, |
232 | | -//! // remove auto-implemented Unpin bound to mark this type as having some |
233 | | -//! // address-sensitive state. This is discussed more below. |
| 257 | +//! // remove auto-implemented `Unpin` bound to mark this type as having some |
| 258 | +//! // address-sensitive state. This is essential for our expected pinning |
| 259 | +//! // guarantees to work, and is discussed more below. |
234 | 260 | //! _pin: PhantomPinned, |
235 | 261 | //! } |
236 | 262 | //! |
|
273 | 299 | //! |
274 | 300 | //! The vast majority of Rust types have no address-sensitive states; these types |
275 | 301 | //! implement the [`Unpin`] auto-trait, which cancels the restrictive effects of |
276 | | -//! [`Pin<P>`]. When [`T: Unpin`][Unpin], <code>[Pin]<[Box]\<T>></code> and |
277 | | -//! [`Box<T>`] function identically, as do <code>[Pin]<[&mut] T></code> and |
278 | | -//! [`&mut T`]. |
| 302 | +//! [`Pin`] when the *pointee* type `T` is [`Unpin`]. When [`T: Unpin`][Unpin], |
| 303 | +//! <code>[Pin]<[Box]\<T>></code> functions identically to a non-pinning [`Box<T>`]; similarly, |
| 304 | +//! <code>[Pin]<[&mut] T></code> would impose no additional restrictions above a regular [`&mut T`]. |
| 305 | +//! |
| 306 | +//! Note that the interaction between a [`Pin<Ptr>`] and [`Unpin`] is through the type of the |
| 307 | +//! **pointee** value, [`<Ptr as Deref>::Target`][Target]. Whether the `Ptr` type itself |
| 308 | +//! implements [`Unpin`] does not affect the behavior of a [`Pin<Ptr>`]. For example, whether or not |
| 309 | +//! [`Box`] is [`Unpin`] has no effect on the behavior of <code>[Pin]<[Box]\<T>></code>, because |
| 310 | +//! `T` is the type of the pointee value, not [`Box`]. So, whether `T` implements [`Unpin`] is |
| 311 | +//! the thing that will affect the behavior of the <code>[Pin]<[Box]\<T>></code>. |
279 | 312 | //! |
280 | | -//! This includes all of the primitive types, like [`bool`], [`i32`], and <code>[&]T</code>, |
281 | | -//! as well as any other type consisting only of those types. |
| 313 | +//! Builtin types that are [`Unpin`] include all of the primitive types, like [`bool`], [`i32`], |
| 314 | +//! and [`f32`], references (<code>[&]T</code> and <code>[&mut] T</code>), etc., as well as many |
| 315 | +//! core and standard library types like [`Box<T>`], [`String`], and more. |
| 316 | +//! These types are marked [`Unpin`] because they do not have an ddress-sensitive state like the |
| 317 | +//! ones we discussed above. If they did have such a state, those parts of their interface would be |
| 318 | +//! unsound without being expressed through pinning, and they would then need to not |
| 319 | +//! implement [`Unpin`]. |
| 320 | +//! |
| 321 | +//! The compiler (and users!) is free to take the conservative stance of marking types as [`Unpin`] |
| 322 | +//! by default. This is because if a type implements [`Unpin`], then it is unsound for [`unsafe`] |
| 323 | +//! code to assume that type is truly pinned, *even* when viewed through a "pinning" pointer! It is |
| 324 | +//! the responsibility of *the implementor of [`unsafe`] code that relies upon pinning for |
| 325 | +//! soundness* (you, in this case!) to ensure that all the types which that code expects to be truly |
| 326 | +//! pinned do not implement [`Unpin`]. |
282 | 327 | //! |
283 | 328 | //! Like other auto-traits, the compiler will automatically determine that a type implements |
284 | | -//! [`Unpin`] if all its fields also implement [`Unpin`]. If you are building a type which is built |
| 329 | +//! [`Unpin`] if all its fields also implement [`Unpin`]. If you are building a type which consists |
285 | 330 | //! of only [`Unpin`] types but has an address-sensistive state and thus should not itself |
286 | | -//! implement [`Unpin`], you can opt out of [`Unpin`] via adding a field with the |
287 | | -//! [`PhantomPinned`] marker type, as we did with our latest `AddrTracker` example above. |
288 | | -//! |
289 | | -//! Note that the interaction between a [`Pin<Ptr>`] and [`Unpin`] is through the **pointee type** |
290 | | -//! of the value behind the `Ptr`, [`<Ptr as Deref>::Target`][Target]. Whether the `Ptr` type itself |
291 | | -//! implements [`Unpin`] does not affect the behavior of a [`Pin<Ptr>`]. For example, whether or not |
292 | | -//! [`Box<T>`] is [`Unpin`] has no effect on the behavior of <code>[Pin]<[Box]\<T>></code> because |
293 | | -//! `T` is the type of the pointee value, not [`Box<T>`]. So, whether `T` implements [`Unpin`] is |
294 | | -//! the thing that will affect the behavior of the <code>[Pin]<[Box]\<T>></code>. |
| 331 | +//! implement [`Unpin`], you must opt out of [`Unpin`] via adding a field with the |
| 332 | +//! [`PhantomPinned`] marker type, as we did with our latest `AddrTracker` example above. Without |
| 333 | +//! doing this, you must not rely on the pinning guarantees to apply to your type! |
| 334 | +//! |
| 335 | +//! If you have reason to pin a value of a type that implements [`Unpin`] such that pinning-related |
| 336 | +//! guarantees actually are respected, you'll need to create your own wrapper type which itself |
| 337 | +//! opts out of implementing [`Unpin`] and contains a sub-field with the [`Unpin`] type that you |
| 338 | +//! want to pin. |
| 339 | +//! |
| 340 | +//! Exposing access to the inner field which you want to remain pinned must then be carefully |
| 341 | +//! considered as well! Remember, exposing a method that gives access to a |
| 342 | +//! <code>[Pin]<[&mut] InnerT>></code> where `InnerT: [Unpin]` would allow safe code to trivially |
| 343 | +//! move the inner value out of that pinning pointer, which is precisely what you're seeking to |
| 344 | +//! prevent! Exposing a field of a pinned value through a pinning pointer is called "projecting" |
| 345 | +//! a pin, and the more general case of deciding in which cases a pin should be able to be |
| 346 | +//! projected or not is called "structural pinning." We will go into more detail about this |
| 347 | +//! [below][structural-pinning]. |
295 | 348 | //! |
296 | 349 | //! # Examples of address-sensitive types |
297 | 350 | //! [address-sensitive-examples]: #examples-of-address-sensitive-types |
|
308 | 361 | //! we could imagine being used to track a sliding window of `data` in parser |
309 | 362 | //! code. |
310 | 363 | //! |
311 | | -//! As mentioned before, this pattern is used extensively by compiler-generated |
| 364 | +//! As mentioned before, this pattern is also used extensively by compiler-generated |
312 | 365 | //! [`Future`]s. |
313 | 366 | //! |
314 | 367 | //! ```rust |
|
379 | 432 | //! ## An intrusive, doubly-linked list |
380 | 433 | //! [linked-list]: #an-intrusive-doubly-linked-list |
381 | 434 | //! |
382 | | -//! In an intrusive doubly-linked list, the collection does not actually allocate the memory for the |
383 | | -//! nodes itself. Allocation is controlled by the clients, and nodes can live on a stack frame |
384 | | -//! that lives shorter than the collection does provided the nodes are removed from the |
385 | | -//! collection before returning. |
| 435 | +//! In an intrusive doubly-linked list, the collection itself does not own the memory in which |
| 436 | +//! each of its elements is stored. Instead, each client is free to allocate space for elements it |
| 437 | +//! adds to the list in whichever manner it likes, including on the stack! Elements can live on a |
| 438 | +//! stack frame that lives shorter than the collection does provided the elements that live in a |
| 439 | +//! given stack frame are removed from the list before going out of scope. |
| 440 | +//! |
| 441 | +//! To make such an intrusive data structure work, every element stores pointers to its predecessor |
| 442 | +//! and successor within its own data, rather than having the list structure itself managing those |
| 443 | +//! pointers. It is in this sense that the structure is "intrusive": the details of how an |
| 444 | +//! element is stored within the larger structure "intrudes" on the implementation of the element |
| 445 | +//! type itself! |
386 | 446 | //! |
387 | 447 | //! The full implementation details of such a data structure are outside the scope of this |
388 | 448 | //! documentation, but we will discuss how [`Pin`] can help to do so. |
389 | 449 | //! |
390 | | -//! To make such an intrusive data structure work, every element stores pointers to its predecessor |
391 | | -//! and successor within its own data, rather than having the list structure itself manage those |
392 | | -//! pointers. Elements can only be added when they are pinned, because moving the elements |
393 | | -//! around would invalidate the pointers to it which are contained in the element ahead and behind |
394 | | -//! it. Moreover, the [`Drop`][Drop] implementation of the element types themselves will in some |
395 | | -//! way patch the pointers of its predecessor and successor elements to remove itself from the list. |
| 450 | +//! Using such an intrusive pattern, elements may only be added when they are pinned. If we think |
| 451 | +//! about the consequences of adding non-pinned values to such a list, this becomes clear: |
| 452 | +//! |
| 453 | +//! *Moving* or otherwise invalidating an element's data would invalidate the pointers back to it |
| 454 | +//! which are stored in the elements ahead and behind it. Thus, in order to soundly dereference |
| 455 | +//! the pointers stored to the next and previous elements, we must satisfy the guarantee that |
| 456 | +//! nothing has invalidated those pointers (which point to data which we do not own). |
| 457 | +//! |
| 458 | +//! Moreover, the [`Drop`][Drop] implementation of each element must in some way notify its |
| 459 | +//! predecessor and successor elements that it should be removed from the list before it is fully |
| 460 | +//! destroyed, otherwise the pointers back to it would again become invalidated. |
396 | 461 | //! |
397 | | -//! Crucially, this means we have to be able to rely on [`drop`] always being called before that |
| 462 | +//! Crucially, this means we have to be able to rely on [`drop`] always being called before an |
398 | 463 | //! element is invalidated. If an element could be deallocated or otherwise invalidated without |
399 | | -//! calling [`drop`], the pointers into it which are stored in its neighboring elements would |
| 464 | +//! calling [`drop`], the pointers to it which are stored in its neighboring elements would |
400 | 465 | //! become invalid, which would break the data structure. |
401 | 466 | //! |
402 | | -//! Therefore, we rely on [the `Drop` guarantee][drop-guarantee] which comes with pinning data, |
| 467 | +//! Therefore, pinning data also comes with [the "`Drop` guarantee"][drop-guarantee]. |
403 | 468 | //! |
404 | 469 | //! # Subtle details and the `Drop` guarantee |
405 | 470 | //! [subtle-details]: self#subtle-details-and-the-drop-guarantee |
|
586 | 651 | //! the new value. |
587 | 652 | //! |
588 | 653 | //! ## Projections and Structural Pinning |
| 654 | +//! [structural-pinning]: self#projections-and-structural-pinning |
589 | 655 | //! |
590 | 656 | //! With ordinary structs, it is natural that we want to add *projection* methods |
591 | 657 | //! that select one of the fields: |
|
0 commit comments