Skip to content

Commit 353066e

Browse files
committed
Document the project_replace() method.
1 parent 1db85fa commit 353066e

File tree

1 file changed

+59
-0
lines changed
  • pin-project-internal/src

1 file changed

+59
-0
lines changed

pin-project-internal/src/lib.rs

+59
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,64 @@ use utils::{Immutable, Mutable, Owned};
226226
///
227227
/// See also [`pinned_drop`] attribute.
228228
///
229+
/// ### `project_replace()`
230+
///
231+
/// In addition to the `project()` and `project_ref()` methods which are always
232+
/// provided when you use the `#[pin_project]` attribute, there is a third method,
233+
/// `project_replace()` which can be useful in some situations. It is equivalent
234+
/// to [`Pin::set`], except that the unpinned fields are moved and returned,
235+
/// instead of being dropped in-place.
236+
///
237+
/// ```
238+
/// # #[rustversion::since(1.36)]
239+
/// # fn dox() {
240+
/// # use std::pin::Pin;
241+
/// # type ProjectionOwned = ();
242+
/// # trait Dox {
243+
/// fn project_replace(self: Pin<&mut Self>, other: Self) -> ProjectionOwned;
244+
/// # }
245+
/// # }
246+
/// ```
247+
///
248+
/// The `ProjectionOwned` type is identical to the `Self` type, except that
249+
/// all pinned fields have been replaced by equivalent `PhantomData` types.
250+
///
251+
/// This method is opt-in, because it is only supported for `Sized` types, and
252+
/// because it is incompatible with the `#[pinned_drop]` attribute described
253+
/// above. It can be enabled by using `#[pin_project(Replace)]`.
254+
///
255+
/// For example:
256+
///
257+
/// ```rust
258+
/// use pin_project::{pin_project, pinned_drop};
259+
/// use std::{fmt::Debug, pin::Pin};
260+
///
261+
/// #[pin_project(Replace)]
262+
/// pub enum Foo<T> {
263+
/// A {
264+
/// #[pin] pinned_field: i32,
265+
/// unpinned_field: T,
266+
/// },
267+
/// B,
268+
/// }
269+
///
270+
/// #[project_replace]
271+
/// fn main() {
272+
/// let mut x = Box::pin(Foo::A { pinned_field: 42, unpinned_field: "hello" });
273+
///
274+
/// #[project_replace]
275+
/// if let Foo::A { unpinned_field, .. } = x.as_mut().project_replace(Foo::B) {
276+
/// assert_eq!(unpinned_field, "hello");
277+
/// } else {
278+
/// unreachable!();
279+
/// }
280+
/// }
281+
/// ```
282+
///
283+
/// The [`project_replace`] attributes are necessary whenever destructuring the return
284+
/// type of `project_replace()`, and work in exactly the same way as the
285+
/// [`project`] and [`project_ref`] attributes.
286+
///
229287
/// ## Supported Items
230288
///
231289
/// The current pin-project supports the following types of items.
@@ -320,6 +378,7 @@ use utils::{Immutable, Mutable, Owned};
320378
/// [`UnsafeUnpin`]: https://docs.rs/pin-project/0.4/pin_project/trait.UnsafeUnpin.html
321379
/// [`project`]: ./attr.project.html
322380
/// [`project_ref`]: ./attr.project_ref.html
381+
/// [`project_replace`]: ./attr.project_replace.html
323382
/// [`pinned_drop`]: ./attr.pinned_drop.html
324383
#[proc_macro_attribute]
325384
pub fn pin_project(args: TokenStream, input: TokenStream) -> TokenStream {

0 commit comments

Comments
 (0)