I am attempting to create a struct that will allow someone to call .shutdown(), which will resolve a future (that is otherwise pending). It can only be called o
It's true, Receiver does not implement Future; only Pin<&mut Receiver> does. You need to project the pinning from your type to the field.
Unpinimpl Future for ShutdownHandle {
type Output = ();
fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
// I copied this code from Stack Overflow without reading the text that
// told me how to verify that this code uses `unsafe` correctly.
unsafe { self.map_unchecked_mut(|s| &mut s.receiver) }.poll(cx).map(|_| ())
}
}
You must read the pin module to thoroughly understand the requirements to use unsafe here.
I like to use a helper library, such as pin_project, to handle more complicated types of projection:
#[unsafe_project(Unpin)]
pub struct ShutdownHandle {
#[pin]
sender: oneshot::Sender<()>,
#[pin]
receiver: oneshot::Receiver<()>,
}
impl Future for ShutdownHandle {
type Output = ();
fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
let this = self.project();
this.receiver.poll(cx).map(|_| ())
}
}
UnpinÖmer Erden points out that the futures-preview crate provides FutureExt::poll_unpin. This method takes a mutable reference to a type that implements Unpin and creates a brand new Pin with it.
Since oneshot::Receiver does implement Unpin, this can be used here:
impl Future for ShutdownHandle {
type Output = ();
fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
self.receiver.poll_unpin(cx).map(|_| ())
}
}