I am trying to get the following simple apply function to compile (simlified for example):
struct Context(i32);
pub async fn apply<F, Fut>(ctx: &mut Context, f: F)
where
F: Fn(&mut Context) -> Fut,
Fut: Future<Output = ()>,
{
for _ in 0..10 {
f(ctx).await;
}
}
async fn example() {
let mut ctx = Context(0);
apply(
&mut ctx,
|ctx| async {
ctx.0 += 1;
}
).await;
assert_eq!(ctx.0, 10);
}
Unfortunately, I am getting the following error in my example function:
error: lifetime may not live long enough
--> src/lib.rs:20:15
|
20 | |ctx| async {
| __________----_^
| | | |
| | | return type of closure `{async block@src/lib.rs:20:15: 20:20}` contains a lifetime `'2`
| | has type `&'1 mut Context`
21 | | ctx.0 += 1;
22 | | }
| |_________^ returning this value requires that `'1` must outlive `'2`
My attempt at fixing this was as follows:
pub async fn apply<'a: 'b, 'b, F, Fut>(ctx: &'a mut Context, f: F)
where
F: Fn(&'b mut Context) -> Fut,
Fut: Future<Output = ()>,
{
for _ in 0..10 {
f(ctx).await;
}
}
Now example is happy, but I'm unfortunately getting an new error in apply:
error[E0499]: cannot borrow `*ctx` as mutable more than once at a time
--> src/lib.rs:10:11
|
3 | pub async fn apply<'a: 'b, 'b, F, Fut>(ctx: &'a mut Context, f: F)
| -- lifetime `'b` defined here
...
10 | f(ctx).await;
| --^^^-
| | |
| | `*ctx` was mutably borrowed here in the previous iteration of the loop
| argument requires that `*ctx` is borrowed for `'b`
How can I get the semantics of apply to compile?
I looked at some similar questions about async functions as parameters but couldn't seem to find one where the closure requires a context parameter and is also called multiple times.
async Fn(&mut Context)works but doesn't have quite the same semantics as prescribing&'b mut Contextas the parameter.AsyncFnis stable since 1.85