I've found a similar question in Issue with FnOnce and async function with a &reference type argument, and managed to apply it to this simplified example, using the nightly type_alias_impl_trait
feature.
#![feature(type_alias_impl_trait)]
use std::future::Future;
struct Foo {}
type FutBool<'a> = impl 'a + Future<Output = bool>;
impl Foo {
// Operation that may fail and should be retried.
async fn operation(&mut self) -> bool {
unimplemented!()
}
async fn indirect(&mut self) {
self.retry_loop(|this| this.operation()).await
}
async fn retry_loop<F>(&mut self, mut f: F)
where
for<'any> F: FnMut(&'any mut Foo) -> FutBool<'any>,
{
loop {
if f(self).await {
return;
}
}
}
}
However, one thing to note (which is however non-blocking) is that I couldn't make a type alias generic over the future's Output
.
type Fut<'a, T> = impl 'a + Future<Output = T>;
type FutBool<'a> = Fut<'a, bool>;
error[E0271]: type mismatch resolving `<impl futures::Future as futures::Future>::Output == T`
--> src/foo.rs:5:19
|
5 | type Fut<'a, T> = impl 'a + Future<Output = T>;
| - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found type parameter `T`
| |
| this type parameter
|
= note: expected type `bool`
found type parameter `T`
Now, this was a simplified example, in reality the type Foo
is rather a Bar<'a>
which contains a reference. I'm now blocked at the following stage.
struct Bar<'a> {
data: &'a str,
}
type FutBool<'x> = impl 'x + Future<Output = bool>;
impl<'a> Bar<'a> {
async fn indirect_4(&mut self) {
self.retry_loop_4(|this| this.operation()).await
}
async fn retry_loop_4<F>(&mut self, mut f: F)
where
for<'any> F: FnMut(&'any mut Bar) -> FutBool<'any>,
{
loop {
if f(self).await {
return;
}
}
}
async fn operation(&mut self) -> bool {
unimplemented!()
}
}
error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
--> src/bar.rs:11:34
|
11 | self.retry_loop_4(|this| this.operation()).await
| ^
|
note: hidden type `impl futures::Future` captures the anonymous lifetime #2 defined on the body at 11:27
--> src/bar.rs:11:27
|
11 | self.retry_loop_4(|this| this.operation()).await
| ^^^^^^^^^^^^^^^^^^^^^^^
error[E0477]: the type `impl futures::Future` does not fulfill the required lifetime
--> src/bar.rs:7:20
|
7 | type FutBool<'x> = impl 'x + Future<Output = bool>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: type must outlive the lifetime `'x` as defined on the item at 7:14
--> src/bar.rs:7:14
|
7 | type FutBool<'x> = impl 'x + Future<Output = bool>;