From b66dcb98af7c0785ace170a074640388d24e8536 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 15 Jun 2019 23:51:42 +0200 Subject: [PATCH 1/7] explain better that structural pinning is a per-field choice --- src/libcore/pin.rs | 131 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 102 insertions(+), 29 deletions(-) diff --git a/src/libcore/pin.rs b/src/libcore/pin.rs index c5247e134c86a..e6fdfb8af5ff3 100644 --- a/src/libcore/pin.rs +++ b/src/libcore/pin.rs @@ -166,43 +166,106 @@ //! implementation as well: if an element of your type could have been pinned, //! you must treat Drop as implicitly taking `Pin<&mut Self>`. //! -//! In particular, if your type is `#[repr(packed)]`, the compiler will automatically +//! For example, you could implement `Drop` as follows: +//! ```rust,ignore +//! impl Drop for Type { +//! fn drop(&mut self) { +//! // `new_unchecked` is okay because we know this value is never used +//! // again after being dropped. +//! inner_drop(unsafe { Pin::new_unchecked(self)}); +//! fn inner_drop(this: Pin<&mut Type>) { +//! // Actual drop code goes here. +//! } +//! } +//! } +//! ``` +//! `inner_drop` has the type that `drop` *should* have, so this makes sure that +//! you do not accidentally use `self`/`this` in a way that is in conflict with pinning. +//! +//! Moreover, if your type is `#[repr(packed)]`, the compiler will automatically //! move fields around to be able to drop them. As a consequence, you cannot use //! pinning with a `#[repr(packed)]` type. //! //! # Projections and Structural Pinning //! -//! One interesting question arises when considering the interaction of pinning -//! and the fields of a struct. When can a struct have a "pinning projection", -//! i.e., an operation with type `fn(Pin<&Struct>) -> Pin<&Field>`? In a -//! similar vein, when can a generic wrapper type (such as `Vec`, `Box`, -//! or `RefCell`) have an operation with type `fn(Pin<&Wrapper>) -> -//! Pin<&T>`? +//! When working with pinned structs, the question arises how one can access the +//! fields of that struct in a method that takes just `Pin<&mut Struct>`. +//! The usual approach is to write helper methods (so called *projections*) +//! that turn `Pin<&mut Struct>` into a reference to the field, but what +//! type should that reference have? Is it `Pin<&mut Field>` or `&mut Field`? +//! The same question arises with the fields of an enum, and also when considering +//! container/wrapper types such as `Vec`, `Box`, or `RefCell`. +//! Also, this question arises for both mutable and shared references, we just +//! use the more common case of mutable references here for illustration. +//! +//! It turns out that it is actually up to the author of the data structure +//! to decide whether the pinned projection for a particular field turns +//! `Pin<&mut Struct>` into `Pin<&mut Field>` or `&mut Field`. There are some +//! constraints though, and the most important constraint is *consistency*: +//! every field can be *either* projected to a pinned reference, *or* have +//! pinning removed as part of the projection. If both are done for the same field, +//! that will likely be unsound! +//! +//! Basically, as the author of a data structure you get to decide for each field whether pinning +//! "propagates" to this field or not. Pinning that propagates is also called "structural", +//! because it follows the structure of the type. +//! In the following, we describe the considerations that have to be made for either choice. +//! +//! ## Pinning *is not* structural for `field` +//! +//! It may seem counter-intuitive that the field of a pinned struct is not pinned, +//! but that is actually the easiest choice: if a `Pin<&mut Field>` is never created, +//! nothing can go wrong! So, if you decide that some field does not have structural pinning, +//! all you have to ensure is that you never create a pinned reference to that field. +//! +//! Then you may add a projection method that turns `Pin<&mut Struct>` into `Pin<&mut Field>`: +//! ```rust,ignore +//! impl Struct { +//! fn get_field<'a>(self: Pin<&'a mut Self>) -> &'a mut Field { +//! // This is okay because `field` is never considered pinned. +//! unsafe { &mut self.get_unchecked_mut().field } +//! } +//! } +//! ``` //! -//! Note: For the entirety of this discussion, the same applies for mutable references as it -//! does for shared references. +//! You may also make make `Struct: Unpin` *even if* the type of `field` +//! is not `Unpin`. What that type thinks about pinning is just not relevant +//! when no `Pin<&mut Field>` is ever created. //! -//! Having a pinning projection for some field means that pinning is "structural": -//! when the wrapper is pinned, the field must be considered pinned, too. -//! After all, the pinning projection lets us get a `Pin<&Field>`. +//! ## Pinning *is* structural for `field` //! -//! However, structural pinning comes with a few extra requirements, so not all -//! wrappers can be structural and hence not all wrappers can offer pinning projections: +//! The other option is to decide that pinning is "structural" for `field`, +//! meaning that if the struct is pinned then so is the field. //! -//! 1. The wrapper must only be [`Unpin`] if all the structural fields are -//! `Unpin`. This is the default, but `Unpin` is a safe trait, so as the author of -//! the wrapper it is your responsibility *not* to add something like -//! `impl Unpin for Wrapper`. (Notice that adding a projection operation +//! This allows writing a projection that creates a `Pin<&mut Field>`, thus +//! witnessing that the field is pinned: +//! ```rust,ignore +//! impl Struct { +//! fn get_field<'a>(self: Pin<&'a mut Self>) -> Pin<&'a mut Field> { +//! // This is okay because `field` is pinned when `self` is. +//! unsafe { self.map_unchecked_mut(|s| &mut s.field) } +//! } +//! } +//! ``` +//! +//! However, structural pinning comes with a few extra requirements: +//! +//! 1. The struct must only be [`Unpin`] if all the structural fields are +//! `Unpin`. This is the default, but `Unpin` is a safe trait, so it is your +//! responsibility as the author of the struct *not* to add something like +//! `impl Unpin for Struct`. (Notice that adding a projection operation //! requires unsafe code, so the fact that `Unpin` is a safe trait does not break //! the principle that you only have to worry about any of this if you use `unsafe`.) -//! 2. The destructor of the wrapper must not move structural fields out of its argument. This +//! 2. The destructor of the struct must not move structural fields out of its argument. This //! is the exact point that was raised in the [previous section][drop-impl]: `drop` takes -//! `&mut self`, but the wrapper (and hence its fields) might have been pinned before. +//! `&mut self`, but the struct (and hence its fields) might have been pinned before. //! You have to guarantee that you do not move a field inside your `Drop` implementation. -//! In particular, as explained previously, this means that your wrapper type must *not* +//! In particular, as explained previously, this means that your struct must *not* //! be `#[repr(packed)]`. +//! See that section for how to write `drop` in a way that the compiler can help you +//! not accidentally break pinning. //! 3. You must make sure that you uphold the [`Drop` guarantee][drop-guarantee]: -//! once your wrapper is pinned, the memory that contains the +//! once your struct is pinned, the memory that contains the //! content is not overwritten or deallocated without calling the content's destructors. //! This can be tricky, as witnessed by `VecDeque`: the destructor of `VecDeque` can fail //! to call `drop` on all elements if one of the destructors panics. This violates the @@ -210,11 +273,11 @@ //! their destructor being called. (`VecDeque` has no pinning projections, so this //! does not cause unsoundness.) //! 4. You must not offer any other operations that could lead to data being moved out of -//! the fields when your type is pinned. For example, if the wrapper contains an +//! the structural fields when your type is pinned. For example, if the struct contains an //! `Option` and there is a `take`-like operation with type -//! `fn(Pin<&mut Wrapper>) -> Option`, -//! that operation can be used to move a `T` out of a pinned `Wrapper` -- which means -//! pinning cannot be structural. +//! `fn(Pin<&mut Struct>) -> Option`, +//! that operation can be used to move a `T` out of a pinned `Struct` -- which means +//! pinning cannot be structural for the field holding this data. //! //! For a more complex example of moving data out of a pinned type, imagine if `RefCell` //! had a method `fn get_pin_mut(self: Pin<&mut Self>) -> Pin<&mut T>`. @@ -231,13 +294,16 @@ //! (using `RefCell::get_pin_mut`) and then move that content using the mutable //! reference we got later. //! -//! For a type like `Vec`, both possibilites (structural pinning or not) make sense, -//! and the choice is up to the author. A `Vec` with structural pinning could -//! have `get_pin`/`get_pin_mut` projections. However, it could *not* allow calling +//! ## Examples +//! +//! For a type like `Vec`, both possibilites (structural pinning or not) make sense. +//! A `Vec` with structural pinning could have `get_pin`/`get_pin_mut` methods to get +//! pinned references to elements. However, it could *not* allow calling //! `pop` on a pinned `Vec` because that would move the (structurally pinned) contents! //! Nor could it allow `push`, which might reallocate and thus also move the contents. //! A `Vec` without structural pinning could `impl Unpin for Vec`, because the contents //! are never pinned and the `Vec` itself is fine with being moved as well. +//! At that point pinning just has no effect on the vector at all. //! //! In the standard library, pointer types generally do not have structural pinning, //! and thus they do not offer pinning projections. This is why `Box: Unpin` holds for all `T`. @@ -249,6 +315,13 @@ //! whether the content is pinned is entirely independent of whether the pointer is //! pinned, meaning pinning is *not* structural. //! +//! When implementing a `Future` combinator, you will usually need structural pinning +//! for the nested futures, as you need to get pinned references to them to call `poll`. +//! But if your combinator contains any other data that does not need to be pinned, +//! you can make those fields not structural and hence freely access them with a +//! mutable reference even when you just have `Pin<&mut Self>` (such as in your own +//! `poll` implementation). +//! //! [`Pin

`]: struct.Pin.html //! [`Unpin`]: ../../std/marker/trait.Unpin.html //! [`Deref`]: ../../std/ops/trait.Deref.html From c489636ce1236f0ff3f9b88d212f8f374e600c19 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 15 Jun 2019 23:56:42 +0200 Subject: [PATCH 2/7] mention that overwrite-without-drop also violates the drop guarantee, and link some more stuff --- src/libcore/pin.rs | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/src/libcore/pin.rs b/src/libcore/pin.rs index e6fdfb8af5ff3..5a9f9a42071c6 100644 --- a/src/libcore/pin.rs +++ b/src/libcore/pin.rs @@ -138,10 +138,11 @@ //! To make this work, not just moving the data is restricted; deallocating, repurposing, or //! otherwise invalidating the memory used to store the data is restricted, too. //! Concretely, for pinned data you have to maintain the invariant -//! that *its memory will not get invalidated from the moment it gets pinned until +//! that *its memory will not get invalidated or repurposed from the moment it gets pinned until //! when `drop` is called*. Memory can be invalidated by deallocation, but also by //! replacing a [`Some(v)`] by [`None`], or calling [`Vec::set_len`] to "kill" some elements -//! off of a vector. +//! off of a vector. It can be repurposed by using [`ptr::write`] to overwrite it without +//! calling the destructor first. //! //! This is exactly the kind of guarantee that the intrusive linked list from the previous //! section needs to function correctly. @@ -194,7 +195,7 @@ //! that turn `Pin<&mut Struct>` into a reference to the field, but what //! type should that reference have? Is it `Pin<&mut Field>` or `&mut Field`? //! The same question arises with the fields of an enum, and also when considering -//! container/wrapper types such as `Vec`, `Box`, or `RefCell`. +//! container/wrapper types such as [`Vec`], [`Box`], or [`RefCell`]. //! Also, this question arises for both mutable and shared references, we just //! use the more common case of mutable references here for illustration. //! @@ -267,8 +268,8 @@ //! 3. You must make sure that you uphold the [`Drop` guarantee][drop-guarantee]: //! once your struct is pinned, the memory that contains the //! content is not overwritten or deallocated without calling the content's destructors. -//! This can be tricky, as witnessed by `VecDeque`: the destructor of `VecDeque` can fail -//! to call `drop` on all elements if one of the destructors panics. This violates the +//! This can be tricky, as witnessed by [`VecDeque`]: the destructor of `VecDeque` +//! can fail to call `drop` on all elements if one of the destructors panics. This violates the //! `Drop` guarantee, because it can lead to elements being deallocated without //! their destructor being called. (`VecDeque` has no pinning projections, so this //! does not cause unsoundness.) @@ -279,7 +280,7 @@ //! that operation can be used to move a `T` out of a pinned `Struct` -- which means //! pinning cannot be structural for the field holding this data. //! -//! For a more complex example of moving data out of a pinned type, imagine if `RefCell` +//! For a more complex example of moving data out of a pinned type, imagine if [`RefCell`] //! had a method `fn get_pin_mut(self: Pin<&mut Self>) -> Pin<&mut T>`. //! Then we could do the following: //! ```compile_fail @@ -296,7 +297,7 @@ //! //! ## Examples //! -//! For a type like `Vec`, both possibilites (structural pinning or not) make sense. +//! For a type like [`Vec`], both possibilites (structural pinning or not) make sense. //! A `Vec` with structural pinning could have `get_pin`/`get_pin_mut` methods to get //! pinned references to elements. However, it could *not* allow calling //! `pop` on a pinned `Vec` because that would move the (structurally pinned) contents! @@ -315,7 +316,7 @@ //! whether the content is pinned is entirely independent of whether the pointer is //! pinned, meaning pinning is *not* structural. //! -//! When implementing a `Future` combinator, you will usually need structural pinning +//! When implementing a [`Future`] combinator, you will usually need structural pinning //! for the nested futures, as you need to get pinned references to them to call `poll`. //! But if your combinator contains any other data that does not need to be pinned, //! you can make those fields not structural and hence freely access them with a @@ -329,9 +330,14 @@ //! [`mem::swap`]: ../../std/mem/fn.swap.html //! [`mem::forget`]: ../../std/mem/fn.forget.html //! [`Box`]: ../../std/boxed/struct.Box.html +//! [`Vec`]: ../../std/vec/struct.Vec.html //! [`Vec::set_len`]: ../../std/vec/struct.Vec.html#method.set_len +//! [`VecDeque`]: ../../std/collections/struct.VecDeque.html +//! [`RefCell`]: ../../std/cell/struct.RefCell.html //! [`None`]: ../../std/option/enum.Option.html#variant.None //! [`Some(v)`]: ../../std/option/enum.Option.html#variant.Some +//! [`ptr::write`]: ../ptr/fn.write.html +//! [`Future`]: ../../std/future/trait.Future.html //! [drop-impl]: #drop-implementation //! [drop-guarantee]: #drop-guarantee From 665aa3e5bb77d13d641c1663aab78cfcc77707e5 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 16 Jun 2019 00:05:17 +0200 Subject: [PATCH 3/7] minor edits --- src/libcore/pin.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/libcore/pin.rs b/src/libcore/pin.rs index 5a9f9a42071c6..66da7c3fb3203 100644 --- a/src/libcore/pin.rs +++ b/src/libcore/pin.rs @@ -196,8 +196,8 @@ //! type should that reference have? Is it `Pin<&mut Field>` or `&mut Field`? //! The same question arises with the fields of an enum, and also when considering //! container/wrapper types such as [`Vec`], [`Box`], or [`RefCell`]. -//! Also, this question arises for both mutable and shared references, we just -//! use the more common case of mutable references here for illustration. +//! (This question applies to both mutable and shared references, we just +//! use the more common case of mutable references here for illustration.) //! //! It turns out that it is actually up to the author of the data structure //! to decide whether the pinned projection for a particular field turns @@ -214,22 +214,22 @@ //! //! ## Pinning *is not* structural for `field` //! -//! It may seem counter-intuitive that the field of a pinned struct is not pinned, +//! It may seem counter-intuitive that the field of a pinned struct might not be pinned, //! but that is actually the easiest choice: if a `Pin<&mut Field>` is never created, //! nothing can go wrong! So, if you decide that some field does not have structural pinning, //! all you have to ensure is that you never create a pinned reference to that field. //! -//! Then you may add a projection method that turns `Pin<&mut Struct>` into `Pin<&mut Field>`: +//! Then you may add a projection method that turns `Pin<&mut Struct>` into `&mut Field`: //! ```rust,ignore //! impl Struct { -//! fn get_field<'a>(self: Pin<&'a mut Self>) -> &'a mut Field { +//! fn pin_get_field<'a>(self: Pin<&'a mut Self>) -> &'a mut Field { //! // This is okay because `field` is never considered pinned. //! unsafe { &mut self.get_unchecked_mut().field } //! } //! } //! ``` //! -//! You may also make make `Struct: Unpin` *even if* the type of `field` +//! You may also `impl Unpin for Struct` *even if* the type of `field` //! is not `Unpin`. What that type thinks about pinning is just not relevant //! when no `Pin<&mut Field>` is ever created. //! @@ -242,7 +242,7 @@ //! witnessing that the field is pinned: //! ```rust,ignore //! impl Struct { -//! fn get_field<'a>(self: Pin<&'a mut Self>) -> Pin<&'a mut Field> { +//! fn pin_get_field<'a>(self: Pin<&'a mut Self>) -> Pin<&'a mut Field> { //! // This is okay because `field` is pinned when `self` is. //! unsafe { self.map_unchecked_mut(|s| &mut s.field) } //! } @@ -252,8 +252,8 @@ //! However, structural pinning comes with a few extra requirements: //! //! 1. The struct must only be [`Unpin`] if all the structural fields are -//! `Unpin`. This is the default, but `Unpin` is a safe trait, so it is your -//! responsibility as the author of the struct *not* to add something like +//! `Unpin`. This is the default, but `Unpin` is a safe trait, so as the author of +//! the struct it is your responsibility *not* to add something like //! `impl Unpin for Struct`. (Notice that adding a projection operation //! requires unsafe code, so the fact that `Unpin` is a safe trait does not break //! the principle that you only have to worry about any of this if you use `unsafe`.) From 86e283a1b70005e7d0f31131fe17ffe1fb1dcd79 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 16 Jun 2019 10:15:30 +0200 Subject: [PATCH 4/7] keep links in local crate where possible --- src/libcore/pin.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/libcore/pin.rs b/src/libcore/pin.rs index 66da7c3fb3203..302e40a954ffa 100644 --- a/src/libcore/pin.rs +++ b/src/libcore/pin.rs @@ -324,20 +324,20 @@ //! `poll` implementation). //! //! [`Pin

`]: struct.Pin.html -//! [`Unpin`]: ../../std/marker/trait.Unpin.html -//! [`Deref`]: ../../std/ops/trait.Deref.html -//! [`DerefMut`]: ../../std/ops/trait.DerefMut.html -//! [`mem::swap`]: ../../std/mem/fn.swap.html -//! [`mem::forget`]: ../../std/mem/fn.forget.html +//! [`Unpin`]: ../marker/trait.Unpin.html +//! [`Deref`]: ../ops/trait.Deref.html +//! [`DerefMut`]: ../ops/trait.DerefMut.html +//! [`mem::swap`]: ../mem/fn.swap.html +//! [`mem::forget`]: ../mem/fn.forget.html //! [`Box`]: ../../std/boxed/struct.Box.html //! [`Vec`]: ../../std/vec/struct.Vec.html //! [`Vec::set_len`]: ../../std/vec/struct.Vec.html#method.set_len //! [`VecDeque`]: ../../std/collections/struct.VecDeque.html -//! [`RefCell`]: ../../std/cell/struct.RefCell.html -//! [`None`]: ../../std/option/enum.Option.html#variant.None -//! [`Some(v)`]: ../../std/option/enum.Option.html#variant.Some +//! [`RefCell`]: ../cell/struct.RefCell.html +//! [`None`]: ../option/enum.Option.html#variant.None +//! [`Some(v)`]: ../option/enum.Option.html#variant.Some //! [`ptr::write`]: ../ptr/fn.write.html -//! [`Future`]: ../../std/future/trait.Future.html +//! [`Future`]: ../future/trait.Future.html //! [drop-impl]: #drop-implementation //! [drop-guarantee]: #drop-guarantee From 2eb074dff180743336b022144fae7e88ea849c4b Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 16 Jun 2019 10:19:22 +0200 Subject: [PATCH 5/7] make example code typecheck at least --- src/libcore/pin.rs | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/libcore/pin.rs b/src/libcore/pin.rs index 302e40a954ffa..ffea5cbf3318c 100644 --- a/src/libcore/pin.rs +++ b/src/libcore/pin.rs @@ -168,7 +168,9 @@ //! you must treat Drop as implicitly taking `Pin<&mut Self>`. //! //! For example, you could implement `Drop` as follows: -//! ```rust,ignore +//! ```rust,no_run +//! # use std::pin::Pin; +//! # struct Type { } //! impl Drop for Type { //! fn drop(&mut self) { //! // `new_unchecked` is okay because we know this value is never used @@ -220,7 +222,10 @@ //! all you have to ensure is that you never create a pinned reference to that field. //! //! Then you may add a projection method that turns `Pin<&mut Struct>` into `&mut Field`: -//! ```rust,ignore +//! ```rust,no_run +//! # use std::pin::Pin; +//! # type Field = i32; +//! # struct Struct { field: Field } //! impl Struct { //! fn pin_get_field<'a>(self: Pin<&'a mut Self>) -> &'a mut Field { //! // This is okay because `field` is never considered pinned. @@ -240,7 +245,10 @@ //! //! This allows writing a projection that creates a `Pin<&mut Field>`, thus //! witnessing that the field is pinned: -//! ```rust,ignore +//! ```rust,no_run +//! # use std::pin::Pin; +//! # type Field = i32; +//! # struct Struct { field: Field } //! impl Struct { //! fn pin_get_field<'a>(self: Pin<&'a mut Self>) -> Pin<&'a mut Field> { //! // This is okay because `field` is pinned when `self` is. From f25095170251c102c32f6bb0705d1feabbd6fe04 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 19 Jun 2019 15:02:50 +0200 Subject: [PATCH 6/7] Apply suggestions from code review Co-Authored-By: Mazdak Farrokhzad --- src/libcore/pin.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libcore/pin.rs b/src/libcore/pin.rs index ffea5cbf3318c..15e28f4f9ae94 100644 --- a/src/libcore/pin.rs +++ b/src/libcore/pin.rs @@ -182,7 +182,7 @@ //! } //! } //! ``` -//! `inner_drop` has the type that `drop` *should* have, so this makes sure that +//! The function `inner_drop` has the type that `drop` *should* have, so this makes sure that //! you do not accidentally use `self`/`this` in a way that is in conflict with pinning. //! //! Moreover, if your type is `#[repr(packed)]`, the compiler will automatically @@ -196,7 +196,7 @@ //! The usual approach is to write helper methods (so called *projections*) //! that turn `Pin<&mut Struct>` into a reference to the field, but what //! type should that reference have? Is it `Pin<&mut Field>` or `&mut Field`? -//! The same question arises with the fields of an enum, and also when considering +//! The same question arises with the fields of an `enum`, and also when considering //! container/wrapper types such as [`Vec`], [`Box`], or [`RefCell`]. //! (This question applies to both mutable and shared references, we just //! use the more common case of mutable references here for illustration.) @@ -209,7 +209,7 @@ //! pinning removed as part of the projection. If both are done for the same field, //! that will likely be unsound! //! -//! Basically, as the author of a data structure you get to decide for each field whether pinning +//! As the author of a data structure you get to decide for each field whether pinning //! "propagates" to this field or not. Pinning that propagates is also called "structural", //! because it follows the structure of the type. //! In the following, we describe the considerations that have to be made for either choice. @@ -235,7 +235,7 @@ //! ``` //! //! You may also `impl Unpin for Struct` *even if* the type of `field` -//! is not `Unpin`. What that type thinks about pinning is just not relevant +//! is not `Unpin`. What that type thinks about pinning is not relevant //! when no `Pin<&mut Field>` is ever created. //! //! ## Pinning *is* structural for `field` From bf03a3c539c30f518ca66dcd8ad3890a8b414d15 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 19 Jun 2019 15:11:54 +0200 Subject: [PATCH 7/7] nits --- src/libcore/pin.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/libcore/pin.rs b/src/libcore/pin.rs index 15e28f4f9ae94..c063cee52270e 100644 --- a/src/libcore/pin.rs +++ b/src/libcore/pin.rs @@ -212,7 +212,8 @@ //! As the author of a data structure you get to decide for each field whether pinning //! "propagates" to this field or not. Pinning that propagates is also called "structural", //! because it follows the structure of the type. -//! In the following, we describe the considerations that have to be made for either choice. +//! In the following subsections, we describe the considerations that have to be made +//! for either choice. //! //! ## Pinning *is not* structural for `field` //! @@ -221,7 +222,8 @@ //! nothing can go wrong! So, if you decide that some field does not have structural pinning, //! all you have to ensure is that you never create a pinned reference to that field. //! -//! Then you may add a projection method that turns `Pin<&mut Struct>` into `&mut Field`: +//! Fields without structural pinning may have a projection method that turns +//! `Pin<&mut Struct>` into `&mut Field`: //! ```rust,no_run //! # use std::pin::Pin; //! # type Field = i32;