Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions src/part-reference/pinning.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ Although moving and not moving is how we introduced pinning and is somewhat sugg

What? Sigh.

Pinning is actually a contract about validity, not about moving. It guarantees that *if an object is address-sensitive, then* its address will not change (and thus addresses derived from it, such as the addresses of its fields, will not change either). Most data in Rust is not address-sensitive. It can be moved around and everything will be ok. `Pin` guarantees that the pointee will be valid with respect to it's address. If the pointee is address-sensitive, then it can't be moved; if it's not address-sensitive, then it doesn't matter whether it is moved.
Pinning is actually a contract about validity, not about moving. It guarantees that *if an object is address-sensitive, then* its address will not change (and thus addresses derived from it, such as the addresses of its fields, will not change either). Most data in Rust is not address-sensitive. It can be moved around and everything will be ok. `Pin` guarantees that the pointee will be valid with respect to its address. If the pointee is address-sensitive, then it can't be moved; if it's not address-sensitive, then it doesn't matter whether it is moved.

`Unpin` is a trait which expresses whether objects are address-sensitive. If an object implements `Unpin`, then it is *not* address-sensitive. If an object is `!Unpin` then it is address-sensitive. Alternatively, if we think of pinning as the act of holding an object in its place, then `Unpin` means it is safe to undo that action and allow the object to be moved.

Expand All @@ -97,7 +97,7 @@ The practical implication of the above is that working with `Unpin` types and pi

Objects are not created pinned. An object starts unpinned (and may be freely moved), it becomes pinned when a pinning pointer is created which points to the object. If the object is `Unpin`, then this is trivial using `Pin::new`, however, if the object is not `Unpin`, then pinning it must ensure that it cannot be moved or invalidated via an alias.

To pin an object on the heap, you can create a new pinning `Box` by using [`Box::pin`](https://doc.rust-lang.org/std/boxed/struct.Box.html#method.pin), or convert an existing `Box` into a pinning `Box` using [`Box::into_pin`](https://doc.rust-lang.org/std/boxed/struct.Box.html#method.into_pin). In either case, you'll end up with `Pin<Box<T>>`. Some other pointers (such as `Arc` and `Rc`) have similar mechanisms. For pointers which don't, or for your own pointer types, you'll need to use [`Pin::new_unchecked`](https://doc.rust-lang.org/std/pin/struct.Pin.html#method.new_unchecked) to create a pinned pointer[^box-pin]. This is an unsafe function and so the programmer must ensure that `Pin`'s invariants are maintained. That is, that the pointee will, under every circumstance, remain valid until it's destructor is called. There are some subtle details to ensuring this, refer to the function's [docs](https://doc.rust-lang.org/std/pin/struct.Pin.html#method.new_unchecked) or the below section [how pinning works](#how-pinning-works) for more.
To pin an object on the heap, you can create a new pinning `Box` by using [`Box::pin`](https://doc.rust-lang.org/std/boxed/struct.Box.html#method.pin), or convert an existing `Box` into a pinning `Box` using [`Box::into_pin`](https://doc.rust-lang.org/std/boxed/struct.Box.html#method.into_pin). In either case, you'll end up with `Pin<Box<T>>`. Some other pointers (such as `Arc` and `Rc`) have similar mechanisms. For pointers which don't, or for your own pointer types, you'll need to use [`Pin::new_unchecked`](https://doc.rust-lang.org/std/pin/struct.Pin.html#method.new_unchecked) to create a pinned pointer[^box-pin]. This is an unsafe function and so the programmer must ensure that `Pin`'s invariants are maintained. That is, that the pointee will, under every circumstance, remain valid until its destructor is called. There are some subtle details to ensuring this, refer to the function's [docs](https://doc.rust-lang.org/std/pin/struct.Pin.html#method.new_unchecked) or the below section [how pinning works](#how-pinning-works) for more.

`Box::pin` pins an object to a place in the heap. To pin an object on the stack, you can use the [`pin`](https://doc.rust-lang.org/std/pin/macro.pin.html) macro to create and pin a mutable reference (`Pin<&mut T>`)[^not-stack].

Expand Down Expand Up @@ -154,7 +154,7 @@ This implementation is incredibly simple! To summarize: `Pin` is a wrapper struc
- Properly implementing `Drop`, see [the drop guarantee](https://doc.rust-lang.org/std/pin/index.html#subtle-details-and-the-drop-guarantee).
- Opting out of `Unpin` (by using [`PhantomPinned`](https://doc.rust-lang.org/std/marker/struct.PhantomPinned.html)) if you require the pinning guarantees.
- The pointee may not be `#[repr(packed)]`.
- Accessing the pinned value [`into_inner_unchecked`](https://doc.rust-lang.org/std/pin/struct.Pin.html#method.into_inner_unchecked), [`get_unchecked_mut`](https://doc.rust-lang.org/std/pin/struct.Pin.html#method.get_unchecked_mut), [`map_unchecked`](https://doc.rust-lang.org/std/pin/struct.Pin.html#method.map_unchecked), and [`map_unchecked_mut`](https://doc.rust-lang.org/std/pin/struct.Pin.html#method.map_unchecked_mut). It becomes the programmer's responsibility to enforce the pinning guarantees (including not moving the data) from the moment data is accessed until it's destructor runs (note that this scope of responsibility extends beyond the unsafe call and applies whatever happens to the underlying data).
- Accessing the pinned value [`into_inner_unchecked`](https://doc.rust-lang.org/std/pin/struct.Pin.html#method.into_inner_unchecked), [`get_unchecked_mut`](https://doc.rust-lang.org/std/pin/struct.Pin.html#method.get_unchecked_mut), [`map_unchecked`](https://doc.rust-lang.org/std/pin/struct.Pin.html#method.map_unchecked), and [`map_unchecked_mut`](https://doc.rust-lang.org/std/pin/struct.Pin.html#method.map_unchecked_mut). It becomes the programmer's responsibility to enforce the pinning guarantees (including not moving the data) from the moment data is accessed until its destructor runs (note that this scope of responsibility extends beyond the unsafe call and applies whatever happens to the underlying data).
- Not providing any other way to move data out of a pinned type (which would need an unsafe implementation).


Expand Down
Loading