Given a consistent async function signature, I would like to create another type that is able to implicitly extract the complier-generated Future return type. No heap or dynamic dispatch.
(playground here).
use std::marker::PhantomData;
pub trait Trait {
}
pub struct Struct {}
impl Struct {
pub async fn f(&self, i: u32) -> u32 {
i
}
}
impl Trait for Struct {
}
pub struct RetExtractor<F: Fn(&B, u32) -> Ret, Ret, B> {
f: F,
_p: PhantomData<(Ret, B)>
}
impl<F: Fn(&B, u32) -> Ret, Ret, B> RetExtractor<F, Ret, B> {
pub fn new(f: F) -> Self {
Self {
f,
_p: PhantomData,
}
}
}
fn stuff() {
let s = Struct {};
let e = RetExtractor::new(Struct::f);
}
You will get a peculiar error that says it expects X but is actually getting a matching X:
error[E0308]: mismatched types
--> src/lib.rs:31:13
|
31 | let e = RetExtractor::<_, _, Struct>::new(Struct::f);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
|
= note: expected associated type `<for<'_> fn(&Struct, u32) -> impl Future {Struct::f} as FnOnce<(&Struct, u32)>>::Output`
found associated type `<for<'_> fn(&Struct, u32) -> impl Future {Struct::f} as FnOnce<(&Struct, u32)>>::Output`
If I remove the async keyword, this compiles. If I remove the self parameter from the F signature, it compiles.
If it had something to do with a binding to a specific lifetime, it seems removing the async keyword would still break since &self is still borrowed.
Note, on nightly, the errors are slightly different. Instead of impl Future, you see impl for<'_> Future. Perhaps the future is dragging another lifetime into the picture?
It seems the combination of the future and self parameter causes the problem, not either one taken by itself.
Is there any way to accomplish this?