Знакомая история, да.
Задать правильные требования к сигнатуре можно с использованием дополнительного трейта примерно так
trait BorrowingFn<'a> {
type Fut: std::future::Future<Output = Something> + 'a;
fn call(self, arg: &'a Runtime) -> Self::Fut;
}
impl<'a, Fu: 'a, F> BorrowingFn<'a> for F
where
F: FnOnce(&'a Runtime) -> Fu,
Fu: std::future::Future<Output = Something> + 'a,
{
type Fut = Fu;
fn call(self, rt: &'a Runtime) -> Fu {
self(rt)
}
}
после чего требуемое условие записывается как for<'a> BorrowingFn<'a>
(playground).
Но внимательный читатель может заметить, что я вызываю start_with_runtime
не с замыканием, а напрямую с async-функцией. Заставить компилятор выводить правильный тип для замыкания в этом контексте у меня пока не получилось (rust-lang/rust#70263).