I'm designing a connection retry function. It retries if the error was ConnectionClosed
. In the full implementation it has other things that justify it being a recursion, but this is off topic. Anyways, since it's a connection, it makes sense to be async. However, async recursives force me to use BoxFuture
, and we know that asyncs capture and return all the arguments.
use std::future::Future;
use futures::future::{BoxFuture, FutureExt};
struct Message{}
struct Client{}
enum Error {
ConnectionClosed
}
impl Client {
async fn send_and_expect<'a>(
&'a mut self,
message: &Message
) -> std::result::Result<(), Error> {
Ok(())
}
//With this function I can wrap any async function f that grabs data from the internet
pub fn connection_retrier<'a, T>(
f: fn(&'a mut Self, &'a Message) -> T,
f_self: &'a mut Self,
f_m: &'a Message,
)-> BoxFuture<'a, std::result::Result<(),Error>>
where
T: Future<Output = std::result::Result<(), Error>> + 'a
{
async move {
//in the original implementation this would have a delay and limited retry count
match Client::connection_retrier(f, f_self, f_m).await {
Ok(r) => Ok(r),
Err(Error::ConnectionClosed) => {
Client::connection_retrier(f, f_self, f_m).await
}
}
}.boxed()
}
}
Error:
error[E0499]: cannot borrow `*f_self` as mutable more than once at a time
--> src/lib.rs:32:51
|
21 | f: fn(&'a mut Self, &'a Message) -> T,
| - lifetime `'1` appears in the type of `f`
...
29 | match Client::connection_retrier(f, f_self, f_m).await {
| ------------------------------------------
| | |
| | first mutable borrow occurs here
| argument requires that `*f_self` is borrowed for `'1`
...
32 | Client::connection_retrier(f, f_self, f_m).await
| ^^^^^^ second mutable borrow occurs here
I understand why the error occurs: Client::connection_retrier(f, f_self, f_m).await
, let's call it r
, holds a mutable reference to f_self
, so I cannot use it again while it's being held. However, after I check that this result r
is Error::ConnectionClosed
, I don't need it anymore, so there should be a way to discard it so I can reborrow it mutably.