【问题标题】:Problems with lifetimes and async fn's生命周期和异步 fn 的问题
【发布时间】:2021-03-10 10:52:15
【问题描述】:

我在下面创建了一些伪代码来演示我的问题。我想用 &mut self 和异步 fn 执行一个 Fn。我尝试了有和没有生命周期,都给出了不同的问题。这就是我想要的:

  • 我有某种类型,我想在其中调用一个方法,我们称之为 A 型
  • 在类型 A 的该方法中,我想调用闭包,它采用 &mut self 并且调用者应该能够在其上调用异步方法
  • 我想在调用闭包之后修改一个属性(仍然使用相同的方法)。
  • 我想返回一些东西(调用者决定的东西) 代码如下所示:

有生命周期

use std::future::Future;

struct LineWriter {
    state: String
}

impl LineWriter {
    async fn start_writing_lines<'a, Return, F: Future<Output=Return>, M: FnOnce(&'a mut Self) -> F>(&'a mut self, f: M) -> Return {
        let r = f(self).await;

        self.state = "written".to_string();

        r
    }

    async fn write_newline(&mut self) {
        // do something
    }
}

#[tokio::main]
async fn main() {
    let mut lw = LineWriter { state: "".to_string() };

    lw.start_writing_lines(|l| l.write_newline()).await;
}

错误:

error[E0506]: cannot assign to `self.state` because it is borrowed
  --> src\main.rs:11:9
   |
8  |     async fn start_writing_lines<'a, Return, F: Future<Output=Return>, M: Fn(&'a mut Self) -> F>(&'a mut self, f: M) -> Return {
   |                                  -- lifetime `'a` defined here
9  |         let r = f(self).await;
   |                 -------
   |                 | |
   |                 | borrow of `self.state` occurs here
   |                 argument requires that `*self` is borrowed for `'a`
10 | 
11 |         self.state = "written".to_string();
   |         ^^^^^^^^^^ assignment to borrowed `self.state` occurs here

为什么 self 仍然被借用?我无法理解。

没有生命周期:

use std::future::Future;

struct LineWriter {
    state: String
}

impl LineWriter {
    async fn start_writing_lines<Return, F: Future<Output=Return>, M: FnOnce(&mut Self) -> F>(&mut self, f: M) -> Return {
        let r = f(self).await;

        self.state = "written".to_string();

        r
    }

    async fn write_newline(&mut self) {
        // do something
    }
}

#[tokio::main]
async fn main() {
    let mut lw = LineWriter { state: "".to_string() };

    lw.start_writing_lines(|l| l.write_newline()).await;
}

错误:

error: lifetime may not live long enough
  --> src\main.rs:25:32
   |
25 |     lw.start_writing_lines(|l| l.write_newline()).await;
   |                             -- ^^^^^^^^^^^^^^^^^ returning this value requires that `'1` must outlive `'2`
   |                             ||
   |                             |return type of closure `impl Future` contains a lifetime `'2`
   |                             has type `&'1 mut LineWriter`

【问题讨论】:

  • Here's the example with all explicit lifetimes on start_writing_lines。它抱怨的生命周期('1'2)分别是 'd'b。但正如所写,这是错误的,因为write_newline 的返回值从self 借用,并且用'b 替换'd 也是错误的,因为它强制f(self)'b 重新借用*self(即整个通话期间start_writing_lines)。我没有解决方案,只是观察。

标签: rust


【解决方案1】:

这是一个棘手的问题。我认为从闭包创建的未来将在 start_writing_lines 函数的持续时间内借用引用,其中包括对 self.state 的赋值。在非异步函数中,这是正确的,但异步生命周期规则有点不同。我认为可能无法完成这项工作。您可能必须单独解决闭包的未来,允许删除引用,然后在另一个函数中修改状态,但我可能错了。

这篇文章解释了更多的异步生命周期和借用http://aturon.github.io/tech/2018/04/24/async-borrowing/

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多