Future で Unpin が必要なときは pin してねって書いてある。
Pinning - Asynchronous Programming in Rust
To use a Future or Stream that isn't Unpin with a function that requires Unpin types, you'll first have to pin the value
Box も Unpin なので、 Pin する必要ないのではと一瞬考える。
impl<T: ?Sized> Unpin for Box
{}
しかし、残念ながらそれでは駄目で、理由は Box<F> が Future になってくれないから。
impl<F: ?Sized + Future + Unpin> Future for Box<F>
なぜ Box<F> を Future にするのに F: Unpin がいるのかというと、 poll を呼び出すにはポインタ先の値を Pin する必要があるが、 Unpin じゃなければそれはできないから。
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { F::poll(Pin::new(&mut *self), cx) }
実際、 Pin::new には Unpin の制限が入っている。
impl<P: Deref<Target: Unpin>> Pin
pub fn new(pointer: P) -> Pin
Box して Unpin にしてしまえば、さらにそれを Pin することで Future にできる。 Deref で Future を参照してるだけで十分なのがポイント。
impl<P> Future for Pin<P> where P: Unpin + ops::DerefMut<Target: Future>
元々 Pin されてるので、内側の poll を呼ぶのに苦労はない。
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { Pin::get_mut(self).as_mut().poll(cx) }
DerefMut であれば as_mut が使えるので、ここで &mut (dyn Future) に変換でき、 poll が呼べる。
pub fn as_mut(&mut self) -> Pin<&mut P::Target>
めでたしめでたし。