Struct Holder

Source
pub struct Holder<'k, T>
where T: Opaque + 'k,
{ /* private fields */ }
Expand description

Holds an “opaqueified” T::Kind.

Note the lifetime, 'k. This can be anything, as long as T outlives it.

§Examples

use core::cell::Cell;
 
use selfref::Holder;
use selfref::opaque;

#[derive(Default)]
struct Foo<'a> {
    foo: Cell<Option<&'a Foo<'a>>>,
}

struct FooKey;
opaque! {
    impl Opaque for FooKey {
        type Kind<'a> = Foo<'a>;
    }
}

fn main() {
    // We can use a closure here, but we need to give the compiler a hint.
    let holder = Holder::<'_, FooKey>::new_with(
        |foo| foo.build(Foo::default())
    );
}

Implementations§

Source§

impl<'k, T> Holder<'k, T>
where T: Opaque,

Source

pub fn new_with<F>(f: F) -> Self
where F: for<'a> FnOnce(&mut Builder<'a, T>), T::Kind<'k>: Sized,

Creates a new holder.

§Examples

Simple example:

use core::cell::Cell;
 
use selfref::Holder;
use selfref::opaque;

#[derive(Default)]
struct Foo<'a> {
    foo: Cell<Option<&'a Foo<'a>>>,
}

struct FooKey;
opaque! {
    impl Opaque for FooKey {
        type Kind<'a> = Foo<'a>;
    }
}

fn main() {
    // We can use a closure here, but we need to help the compiler.
    let holder = Holder::<'_, FooKey>::new_with(
        |foo| foo.build(Foo::default())
    );
}

Lifetime parameters:

use core::cell::Cell;
use core::marker::PhantomData;
 
use selfref::Holder;
use selfref::opaque;

struct Foo<'a, 'b: 'a> {
    foo: Cell<Option<&'a Foo<'a, 'b>>>,
    t: &'b str,
}

struct FooKey<'b>(PhantomData<&'b str>);
opaque! {
    impl['b] Opaque for FooKey<'b> {
        type Kind<'a> = Foo<'a, 'b>;
    }
}

fn main() {
    let stack_array: [u8; 5] = *b"hello";
    // a non-'static &str
    let stack_str = core::str::from_utf8(&stack_array).unwrap();
    let holder = Holder::<'_, FooKey<'_>>::new_with(|foo| {
        foo.build(Foo {
            foo: Default::default(),
            t: stack_str,
        });
    });
}
Source§

impl<'k, T> Holder<'k, T>
where T: Opaque,

Source

pub fn operate_in<'i, F, R>(self: Pin<&'i Self>, f: F) -> R
where F: for<'x> FnOnce(OperateIn<'x, T>) -> R,

Operates in this (pinned) holder.

This “unwraps” the value in this holder, and binds its lifetime to a new stack frame.

§Examples

Simple example:

use core::cell::Cell;
 
use selfref::Holder;
use selfref::opaque;

#[derive(Default)]
struct Foo<'a> {
    foo: Cell<Option<&'a Foo<'a>>>,
}

struct FooKey;
opaque! {
    impl Opaque for FooKey {
        type Kind<'a> = Foo<'a>;
    }
}

fn main() {
    let holder = Box::pin(Holder::<'_, FooKey>::new_with(
        |foo| foo.build(Foo::default())
    ));
    // Actually making our Foo refer to itself.
    holder.as_ref().operate_in(
        |foo| {
            foo.foo.set(Some(foo.get_ref()));
        }
    );
}

With lifetime parameters:

use core::cell::Cell;
use core::marker::PhantomData;
use core::pin::Pin;
 
use selfref::Holder;
use selfref::opaque;

struct Foo<'a, 'b: 'a> {
    foo: Cell<Option<&'a Foo<'a, 'b>>>,
    t: &'b str,
}

struct FooKey<'b>(PhantomData<&'b str>);
opaque! {
    impl['b] Opaque for FooKey<'b> {
        type Kind<'a> = Foo<'a, 'b>;
    }
}

fn main() {
    let stack_array: [u8; 5] = *b"hello";
    // a non-'static &str
    let stack_str = core::str::from_utf8(&stack_array).unwrap();
    let holder = Box::pin(Holder::<'_, FooKey<'_>>::new_with(|foo| {
        foo.build(Foo {
            foo: Default::default(),
            t: stack_str,
        });
    }));
    // Actually making our Foo refer to itself.
    holder.as_ref().operate_in(|foo| {
        foo.foo.set(Some(foo.get_ref()));
    });
}

Auto Trait Implementations§

§

impl<'k, T> Freeze for Holder<'k, T>
where <T as Opaque>::Kind<'k>: Freeze,

§

impl<'k, T> RefUnwindSafe for Holder<'k, T>
where <T as Opaque>::Kind<'k>: RefUnwindSafe,

§

impl<'k, T> Send for Holder<'k, T>
where <T as Opaque>::Kind<'k>: Send,

§

impl<'k, T> Sync for Holder<'k, T>
where <T as Opaque>::Kind<'k>: Sync,

§

impl<'k, T> !Unpin for Holder<'k, T>

§

impl<'k, T> UnwindSafe for Holder<'k, T>
where <T as Opaque>::Kind<'k>: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.