rust - FuturesUnordered 的终身问题

标签 rust lifetime self-reference

我正在尝试存储这些 Readable Coordinator 上的实例结构
并有一个 schedule选择 readables 之一的方法并将其插入 FuturesUnordered 实例(也在 Coordinator 内)以供稍后拉取。
问题是:由于生命周期错误而无法编译

use bytes::Bytes;
use futures::prelude::stream::FuturesUnordered;
use std::future::Future;
use std::pin::Pin;

struct Readable {}

impl Readable {
    async fn read(&mut self) -> Result<Bytes, ()> {
        Err(())
    }
}

type Futures = FuturesUnordered<Pin<Box<dyn Future<Output = Result<Bytes, ()>> + Send>>>;

struct Coordinator {
    readers: Vec<Readable>,
    futures: Futures,
}

impl Coordinator {
    fn schedule(&mut self) {
        let reader = self.readers.get_mut(0).unwrap();
        let f = Box::pin(reader.read());
        self.futures.push(f);
    }
}
错误
error[E0759]: `self` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
  --> src/lib.rs:23:22
   |
22 |     fn schedule(&mut self) {
   |                 --------- this data with an anonymous lifetime `'_`...
23 |         let reader = self.readers.get_mut(0).unwrap();
   |                      ^^^^^^^^^^^^ ...is captured here...
24 |         let f = Box::pin(reader.read());
25 |         self.futures.push(f);
   |                           - ...and is required to live as long as `'static` here

error: aborting due to previous error
游乐场链接:https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=2b69f519de1ac60b30bbbfb4a3cc3b7d
任何人都可以帮助我理解为什么这是一个问题?
具体来说,当我尝试进入 FuturesUnordered 时似乎在提示。但我没有看到 push 方法有任何生命周期限制:
    /// Push a future into the set.
    ///
    /// This method adds the given future to the set. This method will not
    /// call [`poll`](core::future::Future::poll) on the submitted future. The caller must
    /// ensure that [`FuturesUnordered::poll_next`](Stream::poll_next) is called
    /// in order to receive wake-up notifications for the given future.
    pub fn push(&self, future: Fut) {...}
我认为它也可能与这个具有自引用的特定结构有关(即: Coordinator::futures 正在引用 Coordinator::readers ),但我不完全明白这是否相关。

最佳答案

如果我们扩展我们的异步函数,它将如下所示:

fn read<'a>(&'a mut self) -> impl Future<Output = Result<Bytes, ()>> + 'a 
正如你所看到的生命周期 'a已在返回 Future 中捕获类型,这个 'a是一个匿名的生命周期,因为这个 read可以从任何位置调用函数。
这导致了我们的问题;从编译器的角度来看,您的 schedule函数创建一个具有匿名生命周期的 future ,并尝试将其存储在 self 中。 .是 无关FuturesUnordered即使你会像 self.futures = f 一样存储你的 future 那么编译器仍然会抛出同样的错误。
一种解决方案可以使用专用生命周期来告诉编译器这是安全的,但我并不真正建议这样做,因为最终它可能会导致任何其他问题,因为它会强制在特定生命周期内借用 self ,如下面的代码所示。
impl<'a> Coordinator<'a> {
    fn schedule(&'a mut self) {//forced
        let reader = self.readers.get_mut(0).unwrap();
        let f = Box::pin(reader.read());
        self.futures = f;
    }
}
Playground
如果您的 future 不借用任何东西,其他解决方案要容易得多,您可以将没有生命周期的异步函数定义为 future builder 。
impl Readable {
    fn read(&mut self) -> impl Future<Output = Result<Bytes, ()>> {
        //produce bytes from self 
        futures::future::err(())
    }
}
Playground
另见:
  • https://rust-lang.github.io/rfcs/2394-async_await.html#lifetime-capture-in-the-anonymous-future
  • What is the concrete type of a future returned from `async fn`?
  • 关于rust - FuturesUnordered 的终身问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66897475/

    相关文章:

    rust - 如何从Rust中的函数返回计算出的字符串?

    python - 模块导入自身

    谁能解释一下在以下情况下如何分配大小?

    ssis - 如何导入具有自关系的表

    string - 为 HashMap<_, String> 返回默认 &str

    rust - 如何在匹配结构中设置所需的返回类型?

    arrays - 有没有一种简单的方法可以从数组中删除重复的元素?

    rust - 如何设置这些结构的生命周期?

    .net - 任何现有的 IoC 容器都可以动态创建惰性代理类吗?

    hashmap - 为什么 csv::Reader 记录中的字符串在插入到 HashMap 中时生命周期不够长?