I created some pseudo code below to demonstrate my problems. I want to execute a Fn with &mut self with async fn's. I tried it with and without lifetimes, both give different problems. This is what I want:
- I have some type in which I want to call a method on, lets call it type A
- In that method in type A, I want to call closure which takes a &mut self and the caller should be able to call async methods on it
- I want to modify a property AFTER calling the closure (still in the same method).
- I want to return something (something that the caller decides) The code looks something like this:
With lifetimes
use std::future::Future;
struct LineWriter {
state: String
}
impl LineWriter {
async fn start_writing_lines<'a, Return, F: Future<Output=Return>, M: FnOnce(&'a mut Self) -> F>(&'a mut self, f: M) -> Return {
let r = f(self).await;
self.state = "written".to_string();
r
}
async fn write_newline(&mut self) {
// do something
}
}
#[tokio::main]
async fn main() {
let mut lw = LineWriter { state: "".to_string() };
lw.start_writing_lines(|l| l.write_newline()).await;
}
Error:
error[E0506]: cannot assign to `self.state` because it is borrowed
--> src\main.rs:11:9
|
8 | async fn start_writing_lines<'a, Return, F: Future<Output=Return>, M: Fn(&'a mut Self) -> F>(&'a mut self, f: M) -> Return {
| -- lifetime `'a` defined here
9 | let r = f(self).await;
| -------
| | |
| | borrow of `self.state` occurs here
| argument requires that `*self` is borrowed for `'a`
10 |
11 | self.state = "written".to_string();
| ^^^^^^^^^^ assignment to borrowed `self.state` occurs here
Why is self still borrowed? I can not understand that.
Without lifetimes:
use std::future::Future;
struct LineWriter {
state: String
}
impl LineWriter {
async fn start_writing_lines<Return, F: Future<Output=Return>, M: FnOnce(&mut Self) -> F>(&mut self, f: M) -> Return {
let r = f(self).await;
self.state = "written".to_string();
r
}
async fn write_newline(&mut self) {
// do something
}
}
#[tokio::main]
async fn main() {
let mut lw = LineWriter { state: "".to_string() };
lw.start_writing_lines(|l| l.write_newline()).await;
}
Error:
error: lifetime may not live long enough
--> src\main.rs:25:32
|
25 | lw.start_writing_lines(|l| l.write_newline()).await;
| -- ^^^^^^^^^^^^^^^^^ returning this value requires that `'1` must outlive `'2`
| ||
| |return type of closure `impl Future` contains a lifetime `'2`
| has type `&'1 mut LineWriter`