Future returning self Pin

Looking at how Future trait is defined, it doesn't look that it allow something like:

impl Future for Lolka {
    type Output = Pin<&mut Self>;

    fn poll(self: Pin<&mut Self>, ctx: &mut task::Context) -> task::Poll<Self::Output> {
        task::Poll::Ready(self)
     }
}

As long as type Output = Pin<&mut Self> requires lifetime I do not see being able to return reference to itself on future completion.
But in fact wouldn't such use case to be useful?
Rust should probably be able to automatically infer lifetime in associated types... but I'm not sure if there were any attempts to allow something like that?

As work-around you can do something like:

    pub async fn next(mut self) -> Self {
        Pin::new(&mut self).await;
        self
    }

I'll share some of my code to see if this might help you. I don't return self; instead, I return a Result with an explicit lifetime:

impl<'visit, T> Future for &WriteVisitor<'visit, T> {
    type Output = InformationResult<'visit, ()>;

    #[inline]
    fn poll(self: Pin<&mut Self>, _: &mut Context) -> Poll<Self::Output> {
        if self.is_ready() {
            Poll::Ready(Ok(()))
        } else {
            Poll::Pending
        }
    }
}

And, like you, I make sure that the calling function consumes self, and upon calling the future, inputs a reference to self

    #[inline]
    pub unsafe fn try_visit<Fx>(self, pre_alloc: Option<usize>, subroutine: Fx) -> InformationResult<'visit, ()>
        where Fx: Fn(Option<&Self>) -> Option<usize> {
        if self.is_ready() {
                let initial_size = (*(self).ptr).len;
                let pre_alloc_amt = pre_alloc.unwrap_or(0);

                match subroutine(Some(&self)) {
                    Some(bytes_added) => {
                        if bytes_added > initial_size + pre_alloc_amt {
                            (*(self).ptr).corrupt = true;
                            let bytes = (*self.ptr).get_full_bytes_mut();
                            Err(MemError::CORRUPT(bytes))
                        } else {
                            Ok(())
                        }
                    }

                    None => {
                        Ok(())
                    }
                }
        } else {
            Err(MemError::NOT_READY)
        }
    }

This is not possible for the same reason that an Iterator cannot return a reference to something inside the iterator. There is an RFC that would enable this: generic associated types.

1 Like

Ah I see, I should check it out, but I imagine the level of difficulty for the implementation is like GAT so gonna take forever.

Thanks for link