|
10 | 10 |
|
11 | 11 | //! Types which pin data to its location in memory
|
12 | 12 | //!
|
13 |
| -//! see the [standard library module] for more information |
| 13 | +//! It is sometimes useful to have objects that are guaranteed to not move, |
| 14 | +//! in the sense that their placement in memory in consistent, and can thus be relied upon. |
14 | 15 | //!
|
15 |
| -//! [standard library module]: ../../std/pin/index.html |
| 16 | +//! A prime example of such a scenario would be building self-referencial structs, |
| 17 | +//! since moving an object with pointers to itself will invalidate them, |
| 18 | +//! which could cause undefined behavior. |
| 19 | +//! |
| 20 | +//! In order to prevent objects from moving, they must be *pinned*, |
| 21 | +//! by wrapping the data in special pointer types, such as [`PinMut`] and [`PinBox`]. |
| 22 | +//! These restrict access to the underlying data to only be immutable by implementing [`Deref`], |
| 23 | +//! unless the type implements the [`Unpin`] trait, |
| 24 | +//! which indicates that it doesn't need these restrictions and can be safely mutated, |
| 25 | +//! by implementing [`DerefMut`]. |
| 26 | +//! |
| 27 | +//! This is done because, while modifying an object can be done in-place, |
| 28 | +//! it might also relocate a buffer when its at full capacity, |
| 29 | +//! or it might replace one object with another without logically "moving" them with [`swap`]. |
| 30 | +//! |
| 31 | +//! [`PinMut`]: struct.PinMut.html |
| 32 | +//! [`PinBox`]: struct.PinBox.html |
| 33 | +//! [`Unpin`]: ../../core/marker/trait.Unpin.html |
| 34 | +//! [`DerefMut`]: ../../core/ops/trait.DerefMut.html |
| 35 | +//! [`Deref`]: ../../core/ops/trait.Deref.html |
| 36 | +//! [`swap`]: ../../core/mem/fn.swap.html |
| 37 | +//! |
| 38 | +//! # Examples |
| 39 | +//! |
| 40 | +//! ```rust |
| 41 | +//! #![feature(pin)] |
| 42 | +//! |
| 43 | +//! use std::pin::PinBox; |
| 44 | +//! use std::marker::Pinned; |
| 45 | +//! use std::ptr::NonNull; |
| 46 | +//! |
| 47 | +//! // This is a self referencial struct since the slice field points to the data field. |
| 48 | +//! // We cannot inform the compiler about that with a normal reference, |
| 49 | +//! // since this pattern cannot be described with the usual borrowing rules. |
| 50 | +//! // Instead we use a raw pointer, though one which is known to not be null, |
| 51 | +//! // since we know it's pointing at the string. |
| 52 | +//! struct Unmovable { |
| 53 | +//! data: String, |
| 54 | +//! slice: NonNull<String>, |
| 55 | +//! _pin: Pinned, |
| 56 | +//! } |
| 57 | +//! |
| 58 | +//! impl Unmovable { |
| 59 | +//! // To ensure the data doesn't move when the function returns, |
| 60 | +//! // we place it in the heap where it will stay for the lifetime of the object, |
| 61 | +//! // and the only way to access it would be through a pointer to it. |
| 62 | +//! fn new(data: String) -> PinBox<Self> { |
| 63 | +//! let res = Unmovable { |
| 64 | +//! data, |
| 65 | +//! // we only create the pointer once the data is in place |
| 66 | +//! // otherwise it will have already moved before we even started |
| 67 | +//! slice: NonNull::dangling(), |
| 68 | +//! _pin: Pinned, |
| 69 | +//! }; |
| 70 | +//! let mut boxed = PinBox::new(res); |
| 71 | +//! |
| 72 | +//! let slice = NonNull::from(&boxed.data); |
| 73 | +//! // we know this is safe because modifying a field doesn't move the whole struct |
| 74 | +//! unsafe { PinBox::get_mut(&mut boxed).slice = slice }; |
| 75 | +//! boxed |
| 76 | +//! } |
| 77 | +//! } |
| 78 | +//! |
| 79 | +//! let unmoved = Unmovable::new("hello".to_string()); |
| 80 | +//! // The pointer should point to the correct location, |
| 81 | +//! // so long as the struct hasn't moved. |
| 82 | +//! // Meanwhile, we are free to move the pointer around. |
| 83 | +//! let mut still_unmoved = unmoved; |
| 84 | +//! assert_eq!(still_unmoved.slice, NonNull::from(&still_unmoved.data)); |
| 85 | +//! |
| 86 | +//! // Now the only way to access to data (safely) is immutably, |
| 87 | +//! // so this will fail to compile: |
| 88 | +//! // still_unmoved.data.push_str(" world"); |
| 89 | +//! |
| 90 | +//! ``` |
16 | 91 |
|
17 | 92 | #![unstable(feature = "pin", issue = "49150")]
|
18 | 93 |
|
| 94 | +pub use core::pin::*; |
| 95 | + |
19 | 96 | use core::convert::From;
|
20 | 97 | use core::fmt;
|
21 | 98 | use core::future::{Future, FutureObj, LocalFutureObj, UnsafeFutureObj};
|
22 | 99 | use core::marker::{Unpin, Unsize};
|
23 |
| -use core::pin::PinMut; |
24 | 100 | use core::ops::{CoerceUnsized, Deref, DerefMut};
|
25 | 101 | use core::task::{Context, Poll};
|
26 | 102 |
|
|
0 commit comments