async-task icon indicating copy to clipboard operation
async-task copied to clipboard

`Builder::spawn` should encode the metadata lifetime contract

Open jstarks opened this issue 9 months ago • 3 comments

Considering this from Builder:

pub fn spawn<F, Fut, S>(self, future: F, schedule: S) -> (Runnable<M>, Task<Fut::Output, M>)
where
    F: FnOnce(&M) -> Fut,
    Fut: Future + Send + 'static,
    Fut::Output: Send + 'static,
    S: Schedule<M> + Send + Sync + 'static,
{
    ...
}

My understanding of the contract around metadata is that it is allocated and pinned as part of task allocation, it is guaranteed to remain valid at least as long as the task's future, and it will not be deallocated without being dropped. If these were not intended to be guarantees, it would be strange to have this extra F wrapper at all, because the caller already had access to the metadata in its old location before it was moved into the task.

However, spawn does not reflect these guarantees in the type system.

I don't think the lifetime guarantee can be encoded with Rust today. You need something like:

F: for<'a> FnOnce(&'a M) -> Fut + 'a

But that doesn't work. Maybe something similar could be done with an explicit trait with GAT and RPITIT, though.

But you can encode the fact that the metadata is effectively pinned for its lifetime. And I think this would be a useful thing to do at the next breaking change:

F: FnOnce(Pin<&M>)

jstarks avatar May 20 '24 18:05 jstarks