【问题标题】:Lifetime issues with FuturesUnorderedFuturesUnordered 的终身问题
【发布时间】:2021-06-28 00:52:10
【问题描述】:

我正在尝试将这些 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 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),但我不完全理解这是否相关。

【问题讨论】:

    标签: rust lifetime self-reference


    【解决方案1】:

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

    fn read<'a>(&'a mut self) -> impl Future<Output = Result<Bytes, ()>> + 'a 
    

    如您所见,'a 已在返回的 Future 类型中捕获了生命周期,此 'a 是一个匿名生命周期,因为可以从任何位置调用此 read 函数。

    这导致了我们的问题;从编译器的角度来看,您的 schedule 函数创建了一个具有匿名生命周期的未来,并尝试将其存储在 self 中。它与FuturesUnordered不相关,即使您将未来存储为self.futures = f,编译器仍会抛出相同的错误。

    一种解决方案可以使用专用生命周期来告诉编译器这是安全的,但我并不真正建议这样做,因为最终它可能会导致任何其他问题,因为它会强制在特定生命周期中借用 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 不借用任何东西,其他解决方案会容易得多,您可以将 async 函数定义为没有生命周期的未来构建器。

    impl Readable {
        fn read(&mut self) -> impl Future<Output = Result<Bytes, ()>> {
            //produce bytes from self 
            futures::future::err(())
        }
    }
    

    Playground

    另请参阅:

    【讨论】:

      猜你喜欢
      • 2019-04-27
      • 1970-01-01
      • 1970-01-01
      • 2017-05-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多