|
7 | 7 | //! since moving an object with pointers to itself will invalidate them,
|
8 | 8 | //! which could cause undefined behavior.
|
9 | 9 | //!
|
10 |
| -//! In order to prevent objects from moving, they must be pinned |
11 |
| -//! by wrapping a pointer to the data in the [`Pin`] type. A pointer wrapped |
12 |
| -//! in a `Pin` is otherwise equivalent to its normal version, e.g., `Pin<Box<T>>` |
13 |
| -//! and `Box<T>` work the same way except that the first is pinning the value |
14 |
| -//! of `T` in place. |
| 10 | +//! By default, all types in Rust are movable. Rust allows passing all types by-value, |
| 11 | +//! and common smart-pointer types such as `Box`, `Rc`, and `&mut` allow replacing and |
| 12 | +//! moving the values they contain. In order to prevent objects from moving, they must |
| 13 | +//! be pinned by wrapping a pointer to the data in the [`Pin`] type. |
| 14 | +//! Doing this prohibits moving the value behind the pointer. |
| 15 | +//! For example, `Pin<Box<T>>` functions much like a regular `Box<T>`, |
| 16 | +//! but doesn't allow moving `T`. The pointer value itself (the `Box`) can still be moved, |
| 17 | +//! but the value behind it cannot. |
15 | 18 | //!
|
16 |
| -//! First of all, these are pointer types because pinned data mustn't be passed around by value |
17 |
| -//! (that would change its location in memory). |
18 |
| -//! Secondly, since data can be moved out of `&mut` and `Box` with functions such as [`swap`], |
19 |
| -//! which causes their contents to swap places in memory, |
20 |
| -//! we need dedicated types that prohibit such operations. |
| 19 | +//! Since data can be moved out of `&mut` and `Box` with functions such as [`swap`], |
| 20 | +//! changing the location of the underlying data, [`Pin`] prohibits accessing the |
| 21 | +//! underlying pointer type (the `&mut` or `Box`) directly, and provides its own set of |
| 22 | +//! APIs for accessing and using the value. [`Pin`] also guarantees that no other |
| 23 | +//! functions will move the pointed-to value. This allows for the creation of |
| 24 | +//! self-references and other special behaviors that are only possible for unmovable |
| 25 | +//! values. |
21 | 26 | //!
|
22 |
| -//! However, these restrictions are usually not necessary, |
23 |
| -//! so most types implement the [`Unpin`] auto-trait, |
24 |
| -//! which indicates that the type can be moved out safely. |
25 |
| -//! Doing so removes the limitations of pinning types, |
26 |
| -//! making them the same as their non-pinning counterparts. |
| 27 | +//! However, these restrictions are usually not necessary. Many types are always freely |
| 28 | +//! movable. These types implement the [`Unpin`] auto-trait, which nullifies the affect |
| 29 | +//! of [`Pin`]. For `T: Unpin`, `Pin<Box<T>>` and `Box<T>` function identically, as do |
| 30 | +//! `Pin<&mut T>` and `&mut T`. |
| 31 | +//! |
| 32 | +//! Note that pinning and `Unpin` only affect the pointed-to type. For example, whether |
| 33 | +//! or not `Box<T>` is `Unpin` has no affect on the behavior of `Pin<Box<T>>`. Similarly, |
| 34 | +//! `Pin<Box<T>>` and `Pin<&mut T>` are always `Unpin` themselves, even though the |
| 35 | +//! `T` underneath them isn't, because the pointers in `Pin<Box<_>>` and `Pin<&mut _>` |
| 36 | +//! are always freely movable, even if the data they point to isn't. |
27 | 37 | //!
|
28 | 38 | //! [`Pin`]: struct.Pin.html
|
29 | 39 | //! [`Unpin`]: trait.Unpin.html
|
|
36 | 46 | //! #![feature(pin)]
|
37 | 47 | //!
|
38 | 48 | //! use std::pin::Pin;
|
39 |
| -//! use std::marker::Pinned; |
| 49 | +//! use std::marker::PhantomPinned; |
40 | 50 | //! use std::ptr::NonNull;
|
41 | 51 | //!
|
42 | 52 | //! // This is a self-referential struct since the slice field points to the data field.
|
|
47 | 57 | //! struct Unmovable {
|
48 | 58 | //! data: String,
|
49 | 59 | //! slice: NonNull<String>,
|
50 |
| -//! _pin: Pinned, |
| 60 | +//! _pin: PhantomPinned, |
51 | 61 | //! }
|
52 | 62 | //!
|
53 | 63 | //! impl Unmovable {
|
|
60 | 70 | //! // we only create the pointer once the data is in place
|
61 | 71 | //! // otherwise it will have already moved before we even started
|
62 | 72 | //! slice: NonNull::dangling(),
|
63 |
| -//! _pin: Pinned, |
| 73 | +//! _pin: PhantomPinned, |
64 | 74 | //! };
|
65 | 75 | //! let mut boxed = Box::pinned(res);
|
66 | 76 | //!
|
|
0 commit comments