-
Notifications
You must be signed in to change notification settings - Fork 13.4k
Expand std::pin module docs and rename std::pin::Pinned to PhantomPinned #55992
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,23 +7,33 @@ | |
//! since moving an object with pointers to itself will invalidate them, | ||
//! which could cause undefined behavior. | ||
//! | ||
//! In order to prevent objects from moving, they must be pinned | ||
//! by wrapping a pointer to the data in the [`Pin`] type. A pointer wrapped | ||
//! in a `Pin` is otherwise equivalent to its normal version, e.g., `Pin<Box<T>>` | ||
//! and `Box<T>` work the same way except that the first is pinning the value | ||
//! of `T` in place. | ||
//! By default, all types in Rust are movable. Rust allows passing all types by-value, | ||
//! and common smart-pointer types such as `Box`, `Rc`, and `&mut` allow replacing and | ||
//! moving the values they contain. In order to prevent objects from moving, they must | ||
//! be pinned by wrapping a pointer to the data in the [`Pin`] type. | ||
//! Doing this prohibits moving the value behind the pointer. | ||
//! For example, `Pin<Box<T>>` functions much like a regular `Box<T>`, | ||
//! but doesn't allow moving `T`. The pointer value itself (the `Box`) can still be moved, | ||
//! but the value behind it cannot. | ||
//! | ||
//! First of all, these are pointer types because pinned data mustn't be passed around by value | ||
//! (that would change its location in memory). | ||
//! Secondly, since data can be moved out of `&mut` and `Box` with functions such as [`swap`], | ||
//! which causes their contents to swap places in memory, | ||
//! we need dedicated types that prohibit such operations. | ||
//! Since data can be moved out of `&mut` and `Box` with functions such as [`swap`], | ||
//! changing the location of the underlying data, [`Pin`] prohibits accessing the | ||
//! underlying pointer type (the `&mut` or `Box`) directly, and provides its own set of | ||
//! APIs for accessing and using the value. [`Pin`] also guarantees that no other | ||
//! functions will move the pointed-to value. This allows for the creation of | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we may want to say "no later code", or something along those lines, instead of "other functions". The contract around |
||
//! self-references and other special behaviors that are only possible for unmovable | ||
//! values. | ||
//! | ||
//! However, these restrictions are usually not necessary, | ||
//! so most types implement the [`Unpin`] auto-trait, | ||
//! which indicates that the type can be moved out safely. | ||
//! Doing so removes the limitations of pinning types, | ||
//! making them the same as their non-pinning counterparts. | ||
//! However, these restrictions are usually not necessary. Many types are always freely | ||
//! movable. These types implement the [`Unpin`] auto-trait, which nullifies the affect | ||
//! of [`Pin`]. For `T: Unpin`, `Pin<Box<T>>` and `Box<T>` function identically, as do | ||
//! `Pin<&mut T>` and `&mut T`. | ||
//! | ||
//! Note that pinning and `Unpin` only affect the pointed-to type. For example, whether | ||
//! or not `Box<T>` is `Unpin` has no affect on the behavior of `Pin<Box<T>>`. Similarly, | ||
//! `Pin<Box<T>>` and `Pin<&mut T>` are always `Unpin` themselves, even though the | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Shouldn't this be There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Those are also |
||
//! `T` underneath them isn't, because the pointers in `Pin<Box<_>>` and `Pin<&mut _>` | ||
//! are always freely movable, even if the data they point to isn't. | ||
//! | ||
//! [`Pin`]: struct.Pin.html | ||
//! [`Unpin`]: trait.Unpin.html | ||
|
@@ -36,7 +46,7 @@ | |
//! #![feature(pin)] | ||
//! | ||
//! use std::pin::Pin; | ||
//! use std::marker::Pinned; | ||
//! use std::marker::PhantomPinned; | ||
//! use std::ptr::NonNull; | ||
//! | ||
//! // This is a self-referential struct since the slice field points to the data field. | ||
|
@@ -47,7 +57,7 @@ | |
//! struct Unmovable { | ||
//! data: String, | ||
//! slice: NonNull<String>, | ||
//! _pin: Pinned, | ||
//! _pin: PhantomPinned, | ||
//! } | ||
//! | ||
//! impl Unmovable { | ||
|
@@ -60,7 +70,7 @@ | |
//! // we only create the pointer once the data is in place | ||
//! // otherwise it will have already moved before we even started | ||
//! slice: NonNull::dangling(), | ||
//! _pin: Pinned, | ||
//! _pin: PhantomPinned, | ||
//! }; | ||
//! let mut boxed = Box::pinned(res); | ||
//! | ||
|
Uh oh!
There was an error while loading. Please reload this page.