impl<C, I, O, F> RpcRetryWrapper<C, I, F>
where
I: Clone,
F: for<'a> Fn(&'a mut C, I) -> O,
O: Future,
async fn outputs capture their input lifetimes, and so they cannot be represented by a type parameter like O when there is an input lifetime, as O must resolve to a single concrete type. The returned Futures are not all the same single type; they vary by lifetime.
There are verbose ways to try and get around that restriction in some cases, but last I knew they don't work for the async fn case (the compiler can't yet see through the indirection and too many higher-ranked bounds).