如何轮询 Pin<Option<Box<dyn Future>>?

hol*_*ava 1 asynchronous rust

Option<Box<dyn Future>当在异步函数递归生成的流中实现时。如何投票Pin<Option<Box<dyn Future>>?谢谢。

use std::{
    future::Future,
    pin::Pin,
    task::{Context, Poll},
};

use futures_util::Stream;

#[pin_project::pin_project]
struct BoxedStream<T, F> {
    #[pin]
    next: Option<String>,
    #[pin]
    inner: Option<Box<dyn Future<Output = T>>>,
    //             ^--- Future generated by async function, it is an opaque type.
    generate: F,
}

impl<T, F> Stream for BoxedStream<T, F>
where
    F: Fn(String) -> (Option<String>, Box<dyn Future<Output = T>>),
{
    type Item = T;

    fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
        let mut p = self.as_mut().project();
        if let Some(s) = p.inner.as_mut().as_pin_mut() {
            return match todo!("how to do it here? s.poll(cx)?") {
                result @ Poll::Ready(_) => {
                    p.inner.take();
                    result
                }
                _ => Poll::Pending,
            };
        }

        if let Some(next) = p.next.take() {
            let (next, future) = (p.generate)(next);
            p.inner.set(Some(future));
            p.next.set(next);
            return self.poll_next(cx);
        }

        Poll::Ready(None) // end
    }
}
Run Code Online (Sandbox Code Playgroud)

s.poll(cx)当我代替待办事项时报告的错误:

error[E0599]: the method `poll` exists for struct `Pin<&mut Box<dyn Future<Output = T>>>`, but its trait bounds were not satisfied
  --> src/lib.rs:28:28
   |
28 |               return match s.poll(cx)? {
   |                              ^^^^ method cannot be called on `Pin<&mut Box<dyn Future<Output = T>>>` due to unsatisfied trait bounds
  --> /rustc/5680fa18feaa87f3ff04063800aec256c3d4b4be/library/core/src/future/future.rs:37:1
   |
   = note: doesn't satisfy `_: Unpin`
  --> /rustc/5680fa18feaa87f3ff04063800aec256c3d4b4be/library/alloc/src/boxed.rs:195:1
  ::: /rustc/5680fa18feaa87f3ff04063800aec256c3d4b4be/library/alloc/src/boxed.rs:198:1
   |
   = note: doesn't satisfy `_: Future`
   |
   = note: the following trait bounds were not satisfied:
           `(dyn futures_util::Future<Output = T> + 'static): Unpin`
           which is required by `Box<(dyn futures_util::Future<Output = T> + 'static)>: futures_util::Future`
Run Code Online (Sandbox Code Playgroud)

kmd*_*eko 6

Pin<Option<...>>没有任何意义;Pin仅当它包装的类型是一种指针时才有效。

您应该存储inner为 aOption<Pin<Box<dyn Future>>>并跳过 的结构固定#[pin]。没有理由Option<Box<...>>需要固定其本身(这意味着#[pin]通过制作 a ,只需要固定inner: Pin<&mut Option<Box<...>>>内部,这就是 a 的含义。dyn FuturePin<Box<...>>

同样,你也不需要或不想next被结构性地固定。因此,只需删除所有#[pin]注释并从那里开始:

#[pin_project::pin_project]
struct BoxedStream<T, F> {
    next: Option<String>,
    inner: Option<Pin<Box<dyn Future<Output = T>>>>,
    generate: F,
}

impl<T, F> Stream for BoxedStream<T, F>
where
    F: Fn(String) -> (Option<String>, Pin<Box<dyn Future<Output = T>>>),
{
    type Item = T;

    fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
        let p = self.as_mut().project();
        if let Some(s) = p.inner {
            return match s.as_mut().poll(cx) {
                Poll::Ready(result) => {
                    p.inner.take();
                    Poll::Ready(Some(result))
                }
                _ => Poll::Pending,
            };
        }

        if let Some(next) = p.next.take() {
            let (next, future) = (p.generate)(next);
            *p.inner = Some(future);
            *p.next = next;
            return self.poll_next(cx);
        }

        Poll::Ready(None)
    }
}
Run Code Online (Sandbox Code Playgroud)

我还让你的函数类型返回Pin<Box<...>>,它可以很容易地通过Box::pin.