[][src]Attribute Macro pin_project::project

#[project]

An attribute to support pattern matching.

This attribute is available if pin-project is built with the "project_attr" feature (it is enabled by default).

Examples

let bindings

use pin_project::{project, unsafe_project};

#[unsafe_project(Unpin)]
struct Foo<T, U> {
    #[pin]
    future: T,
    field: U,
}

impl<T, U> Foo<T, U> {
    #[project] // Nightly does not need a dummy attribute to the function.
    fn baz(self: Pin<&mut Self>) {
        #[project]
        let Foo { future, field } = self.project();

        let _: Pin<&mut T> = future;
        let _: &mut U = field;
    }
}

match expressions

use pin_project::{project, unsafe_project};

#[unsafe_project(Unpin)]
enum Foo<A, B, C> {
    Tuple(#[pin] A, B),
    Struct { field: C },
    Unit,
}

impl<A, B, C> Foo<A, B, C> {
    #[project] // Nightly does not need a dummy attribute to the function.
    fn baz(self: Pin<&mut Self>) {
        #[project]
        match self.project() {
            Foo::Tuple(x, y) => {
                let _: Pin<&mut A> = x;
                let _: &mut B = y;
            }
            Foo::Struct { field } => {
                let _: &mut C = field;
            }
            Foo::Unit => {}
        }
    }
}

if let expressions

When used against if let expressions, the #[project] attribute records the name of the structure destructed with the first if let. Destructing different structures in the after second times will not generate wrong code.

use pin_project::{project, unsafe_project};

#[unsafe_project(Unpin)]
enum Foo<A, B, C> {
    Tuple(#[pin] A, B),
    Struct { field: C },
    Unit,
}

impl<A, B, C> Foo<A, B, C> {
    #[project] // Nightly does not need a dummy attribute to the function.
    fn baz(self: Pin<&mut Self>) {
        #[project]
        {
            if let Foo::Tuple(x, y) = self.project() {
                let _: Pin<&mut A> = x;
                let _: &mut B = y;
            }
        }
    }
}