Crate ergo_pin

Source
Expand description

Immobilis ergo pin

Ergonomic stack pinning for Rust.

ergo-pin exports a single proc-macro-attribute #[ergo_pin] that can be applied to a item/block/tt-accepting-macro-invocation to provide the “magical” pin! within the scope. You can consider this pin! macro equivalent to a function with the signature:

extern "bla̴ck̀ mag̸ic͘" fn pin!<T>(t: T) -> Pin<&'local mut T>;

it will take in any value and return a Pin<&mut _> of the value, with the correct local stack lifetime.

§Examples

§Pin values inside functions

use core::pin::Pin;
use ergo_pin::ergo_pin;

struct Foo;

impl Foo {
    fn foo(self: Pin<&mut Self>) -> usize {
        5
    }
}

#[ergo_pin]
fn foo() -> usize {
    pin!(Foo).foo()
}

assert_eq!(foo(), 5);

§Pin values in blocks (requires unstable features)

#![feature(stmt_expr_attributes, proc_macro_hygiene)]

use core::pin::Pin;
use ergo_pin::ergo_pin;

struct Foo;

impl Foo {
    fn foo(self: Pin<&mut Self>) -> usize {
        5
    }
}

fn foo() -> usize {
    #[ergo_pin] {
        pin!(Foo).foo()
    }
}

assert_eq!(foo(), 5);

§Pin values in other macros that accept normal Rust code (requires unstable features)

#![feature(proc_macro_hygiene)]

use core::pin::Pin;
use ergo_pin::ergo_pin;

struct Foo;

impl Foo {
    fn foo(self: Pin<&mut Self>) -> usize {
        5
    }
}

macro_rules! bar {
    ($($tokens:tt)+) => { $($tokens)+ };
}

fn foo() -> usize {
    #[ergo_pin]
    bar! {
        pin!(Foo).foo()
    }
}

assert_eq!(foo(), 5);

§Pin values inside any function of an impl

(Note: this does not descend into macros of the inner code as they may not be using normal Rust code syntax.)

use core::pin::Pin;
use ergo_pin::ergo_pin;

struct Foo;

impl Foo {
    fn foo(self: Pin<&mut Self>) -> usize {
        5
    }
}

struct Bar;

#[ergo_pin]
impl Bar {
    fn bar() -> usize {
        pin!(Foo).foo()
    }
}

assert_eq!(Bar::bar(), 5);

Attribute Macros§

  • The main attribute, see crate level docs for details.