没有为实现“Future”的类型找到名为“poll”的方法

jhp*_*ING 15 future rust

我正在尝试创建一个结构,允许某人调用.shutdown(),这将解决未来(否则待定)。它只能被调用一次。在Futuretrait的实现中,我收到一个poll未定义的错误,尽管它存在于文档中(在 下impl Future)。

虽然我使用std::future::Futureas impl,但我尝试添加use futures::prelude::*,这会将预览特征带入范围。RLS 和 rustc 都通知我导入未使用,所以这不是问题。

请注意,我没有使用简单的布尔标志,因为我打算让它能够从任何线程调用——这是一个与此处无关的实现细节。

use futures::channel::oneshot; // futures-preview@0.3.0-alpha.17
use std::{
    future::Future,
    pin::Pin,
    task::{Context, Poll},
};

pub struct ShutdownHandle {
    sender: oneshot::Sender<()>,
    receiver: oneshot::Receiver<()>,
}

impl ShutdownHandle {
    pub fn new() -> Self {
        let (sender, receiver) = oneshot::channel();
        Self { sender, receiver }
    }

    pub fn shutdown(self) -> Result<(), ()> {
        self.sender.send(())
    }
}

impl Future for ShutdownHandle {
    type Output = ();

    fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
        self.receiver.poll(&mut cx).map(|_| ())
    }
}

fn main() {
    let runner = ShutdownHandle::new();
    assert!(runner.shutdown().is_ok());
}
Run Code Online (Sandbox Code Playgroud)

我收到以下错误:

error[E0599]: no method named `poll` found for type `futures_channel::oneshot::Receiver<()>` in the current scope
  --> src/main.rs:28:23
   |
28 |         self.receiver.poll(&mut cx).map(|_| ())
   |                       ^^^^
Run Code Online (Sandbox Code Playgroud)

我错过了什么?当然有一些方法可以“通过”投票。我每晚都在使用(2019-07-18)。

She*_*ter 10

是的,Receiver没有实现Future;只做Pin<&mut Receiver>。您需要将固定从您的类型投影到该字段。

当底层类型可能无法实现时 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(|_| ())
    }
}
Run Code Online (Sandbox Code Playgroud)

您必须阅读该pin模块以彻底了解unsafe此处使用的要求。

更清洁的解决方案

我喜欢使用辅助库(例如pin_project)来处理更复杂的投影类型:

#[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(|_| ())
    }
}
Run Code Online (Sandbox Code Playgroud)

当底层类型实现 Unpin

Ömer Erden 指出,期货预览板条箱提供了FutureExt::poll_unpin. 此方法采用对实现Unpin并创建全新类型的类型的可变引用Pin

由于oneshot::Receiver不实现Unpin,这可以在这里使用:

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(|_| ())
    }
}
Run Code Online (Sandbox Code Playgroud)

也可以看看