Closed ids1024 closed 3 years ago
Looking at how the macro expands, it seems the for<'_>
part is present with g1
, but not g2
:
fn g1<'life0>(&'life0 self);
fn g2<'life0, 'async_trait>(&'life0 self)
where 'life0: 'async_trait;
I guess Rust introduces this for<'_>
depending on the lifetimes involved in the function, but since this crate is partially bypassing Rust's lifetime inference with explicit lifetime bounds, it can't do that here.
In particular, it seems it's the 'life0: 'async_trait
bound that's responsible, though I don't know if there's a good alternative that will work...
Edit: This may be a limitation of the compiler.
I guess the reason this works without async-trait
is based on how lifetime elision works:
If there is exactly one lifetime used in the parameters (elided or not), that lifetime is assigned to all elided output lifetimes.
So with the async fn
outside the trait, the return value's lifetime is inferred to be the same as the parameters.
I guess the "correct" solution would be for async-trait
to apply all the lifetime elision rules the compiler does, but that isn't likely to be simple, I guess...
It seems this is just an inconsistency in how Rustc prints the types. There was a real issue I was having, but as far as I can tell it's ultimately due to limits in Rustc.
I don't understand the sorcery of HRTBs and async well enough to know if there's a major difficulty with this, but it seems to be relevant when trying to accept the function as an argument.
Consider this:
This tells us
Struct::f
has typefor<'_> fn(&Struct) -> impl Future {Struct::f}
.Struct::h
has typefor<'r> fn(&'r Struct) {<Struct as Trait>::h}
.But
Struct::g
isfn(&Struct) -> Pin<Box<dyn Future<Output = ()> + Send>> {<Struct as Trait>::g::<'_, '_>}
.If this can't be changed to have a
for<'_>
bound, I guess that should be documented as one of the crate's limitations...