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