Why is an async block on the stack not Unpin?

If got something like:

async fn handle_connection()
{
   let incoming = async move
   {
      // do some work
   };

   let outgoing = async move
   {
      // do some work
   };

   select!
	{
		_ = incoming.fuse() => {}
		_ = outgoing.fuse() => {}
	};
}

The idea is that both run concurrently and that the function ends when either one ends, dropping all data related to the other future.

Select here complains that those futures aren't Unpin. I suppose I'll end up using pin_utils to pin them on the stack (to avoid boxing).

However, I don't understand why they aren't Unpin. I don't really see how they could move, since they will be dropped before the stack frame of this function gets popped.

Note that handle_connection is being used with Box::pin, so generator of this function will be pinned.

1 Like

Using stack pinning is what allows you to guarantee the latter, as it is currently setup there is nothing stopping you from doing something like

async fn handle_connection() {
  let incoming = async move { ... }.fuse();
  let outgoing = async move { ... }.fuse();

  select! {
    _ = &mut incoming => {}
    _ = &mut outgoing => {}
  }

  some_channel.send((incoming, outgoing));
}

By not implementing Unpin on the futures and requiring you to explicitly stack pin them the compiler is forcing you to ensure you can't move them.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.