dtolnay / dtolnay/async-trait

Elided or placeholdered generic lifetimes are not properly respected in trait implementation

Open
#64 1 comment 1 reaction 0 assignees View on GitHub
help wanted
Dominant language
Rust
Stars
2.2k
Forks
101
PR merge metrics
No merged PRs in 30d

Description

Consider the following, where the lifetime for `&` is elided in the trait implementation and a placeholder is used for the generic in the trait:

```rust
#[async_trait::async_trait]
trait Foo<'a>: Sized {
async fn f(bar: &'a usize) -> Self;
}

#[async_trait::async_trait]
impl Foo<'_> for usize {
async fn f(bar: &usize) -> Self {
10
}
}
```

This generates the following implementation:

```rust
impl Foo<'_> for usize {
fn f<'y, 'life0>(bar: &'life0 usize) -> BoxFuture<'y, Self>
where 'life0: 'y, Self: 'y
{
async fn __f(bar: &usize) -> usize { 10 }
Box::pin(__f::<>(bar))
}
}
```

This, of course, does not match the generated trait definition which has only a single lifetime generic in `f`. The "correct" implementation would look like:

```rust
impl<'f> Foo<'f> for usize {
fn f<'y>(bar: &'f usize) -> BoxFuture<'y, Self>
where 'f: 'y, Self: 'y
{
async fn __f(bar: &usize) -> usize { 10 }
Box::pin(__f::<>(bar))
}
}
```

This, of course, would require `async-trait` to know that the placeholdered generic lifetime in the trait corresponds to the elided lifetime in the implementation. In general, it's clear that `async-trait` can't do this as it doesn't have type information nor access to the AST of the definition.

I believe that `async-trait` should likely error when trait generics are placeholdered. At least then the user gets a nice error message as opposed to incorrect code being generated.

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.