|
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