When we elide a lifetime in the impl block but not in the trait definition block, async-trait produces different lifetime requirements, which make the code not compile.
Example (Playground):
use async_trait::async_trait; // 0.1.89
struct MyStruct<'a>(&'a ());
#[async_trait]
trait MyTrait {
async fn foo(&self, s: &MyStruct);
}
struct TypeA;
// this works
#[async_trait]
impl MyTrait for TypeA {
async fn foo(&self, _s: &MyStruct) {}
}
struct TypeB;
// this doesn't
#[async_trait]
impl MyTrait for TypeB {
async fn foo(&self, _s: &MyStruct<'_>) {}
}
This code produces the following compiler error:
error[E0195]: lifetime parameters do not match the trait definition
--> src/lib.rs:23:39
|
23 | async fn foo(&self, _s: &MyStruct<'_>) {}
| ^^
|
= note: lifetime parameters differ in whether they are early- or late-bound
note: `'life2` differs between the trait and impl
--> src/lib.rs:7:29
|
6 | trait MyTrait {
| ------------- in this trait...
7 | async fn foo(&self, s: &MyStruct);
| ^^^^^^^^ `'_` is late-bound
...
22 | impl MyTrait for TypeB {
| ---------------------- in this impl...
23 | async fn foo(&self, _s: &MyStruct<'_>) {}
| ^^
| |
| `'life2` is early-bound
| this lifetime bound makes `'life2` early-bound
For more information about this error, try `rustc --explain E0195`.
This code would be accepted by the compiler if async-trait was not used. Since async-trait obviously cannot guess whether lifetimes were elided or not, I think non-elided lifetimes should be treated like elided lifetimes.
When we elide a lifetime in the impl block but not in the trait definition block, async-trait produces different lifetime requirements, which make the code not compile.
Example (Playground):
This code produces the following compiler error:
This code would be accepted by the compiler if async-trait was not used. Since async-trait obviously cannot guess whether lifetimes were elided or not, I think non-elided lifetimes should be treated like elided lifetimes.