Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Struggling to make lifetimes happy for async with temporary borrow of other data during build #112

Open
vlovich opened this issue May 1, 2024 · 1 comment

Comments

@vlovich
Copy link

vlovich commented May 1, 2024

I'm trying to do something that looks something like this:

#[self_referencing]
struct MyStructInner {
      owned: SomeStruct,
      #[borrows(owned)]
      #[not_covariant]
      referencing: SomeStructRef<'this>,
}

struct MyStruct(MyStructInner);
  
impl MyStruct {
      async fn new(owned: SomeStruct, helper: &SomeOtherStruct) -> Result<Self> {
            Ok(MyStruct(
               MyStructInnerAsyncTryBuilder {
                  owned,
                  referencing_builder: move |owned| Box::pin(async move { SomeStructRef::try_new(owned, helper).await? } )
               }.try_build().await?
            ))
      }
} 

This throws a compiler error saying that the lifetime of helper may outlive the future because of the pinned box. I typed this in GitHub's text editor so apologies if there's bugs in the above code (tried to distill down my actual code).

Is this a scenario that ouroboros doesn't handle well yet? I'm a little surprised the borrow lifetime is thought to extend past the await of the build.

@vlovich vlovich changed the title Struggling to make lifetimes happy for async Struggling to make lifetimes happy for async with temporary borrow May 1, 2024
@vlovich vlovich changed the title Struggling to make lifetimes happy for async with temporary borrow Struggling to make lifetimes happy for async with temporary borrow of other data during build May 1, 2024
@someguynamedjosh
Copy link
Owner

Unfortunately ouroboros internally requires that the future returned by the builder lives for at least the 'this lifetime. I went in and tried playing around with it to get it to accept any other lifetime bound, but it would always throw borrow check errors on simple test cases. If you would like to try looking for a possible solution yourself, the code ouroboros generates for constructing asynchronously looks like this:

async fn new_async(
    data: i32,
    dref_builder: impl for<'this> ::core::ops::FnOnce(
        &'this i32,
    ) -> ::core::pin::Pin<
        ::ouroboros::macro_help::alloc::boxed::Box<
            dyn ::core::future::Future<Output = &'this i32> + 'this,
        >,
    >,
) -> () {
    todo!()
}

A simple test case which breaks if I do things like replace + 'this with some lifetime parameter on the async fn itself is as follows:

async fn example() {
    new_async(12, |data| Box::pin(async move { data })).await;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants