It seems borrow checker cannot overcome cases below:
use std::future::Future;
#[derive(Debug, Default)]
pub struct Container {
v: Vec<u8>,
}
impl Container {
async fn mutation(&mut self) {
self.v.push(42);
}
async fn mutations(&mut self) {
let n = self.v.len() + 1;
for _ in 0..n {
self.mutation().await;
}
}
async fn generic_mutations<F, Fut>(&mut self, f: F)
where
F: Fn(&mut Self) -> Fut,
Fut: Future<Output = ()>,
{
let n = self.v.len() + 1;
for _ in 0..n {
f(self).await;
}
}
async fn generic_mutations_with_lifetime<'a, F, Fut>(&'a mut self, f: F)
where
F: Fn(&'a mut Self) -> Fut,
Fut: Future<Output = ()>,
{
let n = self.v.len() + 1;
for _ in 0..n {
f(self).await;
}
}
}
#[tokio::main]
async fn main() {
// compiled
{
let mut c = Container::default();
c.mutations().await;
c.mutations().await;
println!("{:?}", c);
}
// error: lifetime may not live long enough
// --> src/main.rs:54:35
// |
// 54 | c.generic_mutations(|con| con.mutation()).await;
// | ---- ^^^^^^^^^^^^^^ returning this value requires that `'1` must outlive `'2`
// | | |
// | | return type of closure `impl Future<Output = ()>` contains a lifetime `'2`
// | has type `&'1 mut Container`
{
let mut c = Container::default();
c.generic_mutations(|con| con.mutation()).await;
c.generic_mutations(|con| con.mutation()).await;
println!("{:?}", c);
}
// error[E0499]: cannot borrow `*self` as mutable more than once at a time
// --> src/main.rs:38:15
// |
// 31 | async fn generic_mutations_with_lifetime<'a, F, Fut>(&'a mut self, f: F)
// | -- lifetime `'a` defined here
// ...
// 38 | f(self).await;
// | --^^^^-
// | | |
// | | `*self` was mutably borrowed here in the previous iteration of the loop
// | argument requires that `*self` is borrowed for `'a`
{
let mut c = Container::default();
c.generic_mutations_with_lifetime(|con| con.mutation())
.await;
c.generic_mutations_with_lifetime(|con| con.mutation())
.await;
println!("{:?}", c);
}
}
How can I make use of the generic while still tell the borrow checker that I'm doing things right?