No method named `poll` found for a type that implements `Future`

前端 未结 1 1933
野趣味
野趣味 2020-12-03 21:50

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

相关标签:
1条回答
  • 2020-12-03 22:34

    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.

    When the underlying type may not implement Unpin

    impl 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.

    A cleaner solution

    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(|_| ())
        }
    }
    

    When the underlying type implements 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(|_| ())
        }
    }
    

    See also

    • When is it safe to move a member value out of a pinned future?
    • Why is a trait not implemented for a type that clearly has it implemented?
    0 讨论(0)
提交回复
热议问题