|
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