Skip to content

Commit c9ade6a

Browse files
committed
more pin projections tweaking
1 parent 1b556f1 commit c9ade6a

File tree

1 file changed

+17
-10
lines changed

1 file changed

+17
-10
lines changed

src/libcore/pin.rs

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -177,23 +177,30 @@
177177
//! In a similar vein, when can a generic wrapper type (such as `Vec`, `Box`, or `RefCell`)
178178
//! have an operation with type `fn(Pin<&[mut] Wrapper<T>>) -> Pin<&[mut] T>`?
179179
//!
180-
//! This question is closely related to the question of whether pinning is "structural":
181-
//! when you have pinned a wrapper type, have you pinned its contents? Deciding this
182-
//! is entirely up to the author of any given type. For many types, both answers are reasonable
183-
//! (e.g., there could be a version of `Vec` with structural pinning and another
184-
//! version where the contents remain movable even when the `Vec` is pinned).
185-
//! If the type should have pinning projections, pinning must be structural.
180+
//! This question is closely related to the question of whether pinning is "structural".
181+
//! Structural pinning means that when you have pinned a wrapper type, the contents are
182+
//! also pinned. Structural pinning thus explains why pinning projections are correct. This means
183+
//! that if the type should have pinning projections for some fields, pinning must be structural
184+
//! for those fields.
185+
//!
186+
//! In general, deciding for which fields pinning is structural (and thus for which fields
187+
//! pinning projections could be offered) is entirely up to the author of any given type.
188+
//! For many types, both answers are reasonable. For example, there could be a version
189+
//! of `Vec` with structural pinning and `get_pin`/`get_pin_mut` projections to access
190+
//! the `Vec` elements, and another version where the contents remain movable even when
191+
//! the `Vec` is pinned.
192+
//!
186193
//! However, structural pinning comes with a few extra requirements:
187194
//!
188-
//! 1. The wrapper must only be [`Unpin`] if all the fields one can project to are
195+
//! 1. The wrapper must only be [`Unpin`] if all the structural fields are
189196
//! `Unpin`. This is the default, but `Unpin` is a safe trait, so as the author of
190197
//! the wrapper it is your responsibility *not* to add something like
191198
//! `impl<T> Unpin for Wrapper<T>`. (Notice that adding a projection operation
192199
//! requires unsafe code, so the fact that `Unpin` is a safe trait does not break
193200
//! the principle that you only have to worry about any of this if you use `unsafe`.)
194-
//! 2. The destructor of the wrapper must not move out of its argument. This is the exact
195-
//! point that was raised in the [previous section][drop-impl]: `drop` takes `&mut self`,
196-
//! but the wrapper (and hence its fields) might have been pinned before.
201+
//! 2. The destructor of the wrapper must not move structural fields out of its argument. This
202+
//! is the exact point that was raised in the [previous section][drop-impl]: `drop` takes
203+
//! `&mut self`, but the wrapper (and hence its fields) might have been pinned before.
197204
//! You have to guarantee that you do not move a field inside your `Drop` implementation.
198205
//! In particular, as explained previously, this means that your wrapper type must *not*
199206
//! be `#[repr(packed)]`.

0 commit comments

Comments
 (0)