我正在尝试制作一个帮助程序,允许异步链接副作用,但我无法正确地得到通用约束条件,以便编译器理解future的输出超过了用于构建它的引用。
这主要是由于以下代码导致的: Playground链接
问题的核心在于:
如果我们修复
我们得到了一个新的编译器错误,关于在借用
这主要是由于以下代码导致的: Playground链接
问题的核心在于:
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
约束条件中以证明借用和最终移动位于不相交的生命周期上的约束条件?
Fn*
类型(闭包->FnHelper
->FnOnce
),则其并不真正起作用,但对于函数来说却可以!这个可以工作并编译。我将不得不重新考虑和修订我的答案。 - kmdreko