【发布时间】:2021-12-31 01:20:14
【问题描述】:
我正在尝试创建一个允许异步链接副作用的帮助程序,但我无法正确获取通用边界,以便编译器理解未来的输出比用于构建它的引用更有效。
它的要点归结为:
struct Chain<T> {
data: T
}
impl<T> Chain<T> {
pub async fn chain<E, Fut, F>(self, effect: F) -> Result<T, E>
where
Fut: Future<Output=Result<(), E>>,
F: FnOnce(&T) -> Fut
{
todo!()
}
}
给出一个编译器错误
error: lifetime may not live long enough
--> src/main.rs:39:32
|
39 | let r = chain.chain(|this| this.good("bar")).await;
| ----- ^^^^^^^^^^^^^^^^ returning this value requires that `'1` must outlive `'2`
| | |
| | return type of closure `impl Future` contains a lifetime `'2`
| has type `&'1 MyData`
如果我们修复 chain 以便它可以推断出引用在与未来相同的生命周期内可用:
impl<T> Chain<T> {
pub async fn chain<'a, E, Fut, F>(self, effect: F) -> Result<T, E>
where
T: 'a,
Fut: 'a + Future<Output=Result<(), E>>,
F: FnOnce(&'a T) -> Fut
{
effect(&self.data).await?;
Ok(self.data)
}
}
我们收到一个关于移动 self.data 的新编译器错误,而它仍然被借用。
error[E0505]: cannot move out of `self.data` because it is borrowed
--> src/main.rs:30:12
|
23 | pub async fn chain<'a, E, Fut, F>(self, effect: F) -> Result<T, E>
| -- lifetime `'a` defined here
...
29 | effect(&self.data).await?;
| ------------------
| | |
| | borrow of `self.data` occurs here
| argument requires that `self.data` is borrowed for `'a`
30 | Ok(self.data)
| ^^^^^^^^^ move out of `self.data` occurs here
我猜想有一个类似于|this| futures::future::ready(Err(this)) 的病态关闭,这将导致借用仍然“活着”而提前返回。
问题
我们怎样才能让chain 工作?我正常的块作用域技巧似乎没有帮助。是否可以添加一组 where 约束来证明借用和最终移动的生命周期不相交?
【问题讨论】:
标签: asynchronous rust borrow-checker generic-constraints