rust - 对 Rust 的闭包生命周期感到困惑

标签 rust closures lifetime

我遇到了一个令人困惑的情况,即编译器输出的内容在逻辑上没有意义。 这是重现我在项目代码中遇到的相同问题的最小示例。

use std::sync::Arc;

struct A<'a, T> {
    f: Box<dyn Fn(&u32) -> T + 'a>
}

struct B<'a> {
    inner: A<'a, Z<'a>>
}

impl<'a, T> A<'a, T> {
    fn new<F>(f: F) -> Self where F: Fn(&u32) -> T + 'a {
        A { f: Box::new(f) }
    }
}

struct X<'a> {
    _d: &'a std::marker::PhantomData<()>
}

struct Z<'a> {
    _d: &'a std::marker::PhantomData<()>
}

impl<'a> X<'a> {
    fn g(&self, y: u32) -> Z {
        Z { _d: &std::marker::PhantomData }
    }
}

impl<'a> B<'a> {
    fn new(x: Arc<X<'a>>) -> Self {
        B {
            inner: A::new(move |y: &u32| -> Z {
                x.g(*y)
            })
        }
    }
}

fn main() {
}

还有令人困惑的编译错误:

error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in function call due to conflicting requirements
  --> t.rs:35:19
   |
35 |                 x.g(*y)
   |                   ^
   |
note: first, the lifetime cannot outlive the lifetime '_ as defined on the body at 34:27...
  --> t.rs:34:27
   |
34 |             inner: A::new(move |y: &u32| -> Z {
   |                           ^^^^^^^^^^^^^^^^^^^
note: ...so that closure can access `x`
  --> t.rs:35:17
   |
35 |                 x.g(*y)
   |                 ^
note: but, the lifetime must be valid for the lifetime 'a as defined on the impl at 31:6...
  --> t.rs:31:6
   |
31 | impl<'a> B<'a> {
   |      ^^
   = note: ...so that the expression is assignable:
           expected B<'a>
              found B<'_>

error: aborting due to previous error

我不太明白日志中提到的“生命周期”指的是什么,以及匿名生命周期 '_ 究竟代表什么。

最佳答案

您的代码中存在一个小疏忽。应该是:

impl<'a> X<'a> {
    fn g(&self, y: u32) -> Z<'a> {
        Z { _d: &std::marker::PhantomData }
    }
}

然后编译整个过程。这是 Rust 的 lifetime elision rule 的一个例子开始发挥作用。

根据相关省略规则,即:

  • Each elided lifetime in input position becomes a distinct lifetime parameter.
  • If there are multiple input lifetime positions, but one of them is &self or &mut self, the lifetime of self is assigned to all elided output lifetimes.

然后到rustc你原来的代码实际上是这样的:

impl<'a> X<'a> {
    fn g<'b>(&'b self, y: u32) -> Z<'b> {
        Z { _d: &std::marker::PhantomData }
    }
}

省略的生命周期参数 'b 将来自调用站点,这正是您在错误消息中看到的内容。 rustc 无法协调两个生命周期,因此出现错误。

关于rust - 对 Rust 的闭包生命周期感到困惑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58897741/

相关文章:

Rust 生命周期 - 从 Arc 中的 RWLock 中的向量返回值

rust - 我如何为引用类型实现像 Add 这样的运算符,以便我可以一次添加两个以上的值?

function - 如何编写一个接受函数片段的函数?

scheme - 函数中的变量

javascript - 街景 API 回调的 JS 闭包

rust - `array` 生命周期不够长

scala - 为什么 scalac 会生成额外的/包装闭包

rust - 多个结构字段如何成为使用相同更高生命周期的泛型?

rust - 为什么在闭包内克隆数据不能防止错误 "closure may outlive the current function"?

c++ - 对由类型运算符创建的临时引用