Home > OS >  How to use rust async_trait generic to a lifetime parameter?
How to use rust async_trait generic to a lifetime parameter?

Time:10-14

I'm trying to make an async_trait where some implementations are generic to types with lifetime parameters:

use async_trait::async_trait;

struct MyLifetimeType<'a> {
  s: &'a mut String,
}

#[async_trait]
trait MyTrait<T> {
  async fn handle(t: T);
}

struct MyImpl;

#[async_trait]
impl<'a> MyTrait<MyLifetimeType<'a>> for MyImpl {
  async fn handle(t: MyLifetimeType<'a>) {
    t.s.push_str("hi");
  }
}

When I try to compile this, I get

error[E0276]: impl has stricter requirements than trait
  --> ...
   |
18 |   async fn handle(t: T);
   |   ---------------------- definition of `handle` from trait
...
25 |   async fn handle(t: MyLifetimeType<'a>) {
   |   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `'a: 'async_trait`

It seems that the issue is related to async_trait somehow using the lifetime parameter 'a under the hood. When I get rid of all the async and async_trait, the code compiles fine. How can I avoid this extra requirement error?

For more context, to explain why have handlers implementing MyTrait that can operate on structs containing mutable pointers: I have a function that obtains RwLockReadGuards and RwLockWriteGuards for a couple different locks, then passes the contents to a handler. For the write guards, I need some way for the handler to mutate contents, so I pass a mutable pointer.

CodePudding user response:

This is a known issue. The author recommends adding an explicit lifetime bound when that error occurs:

use async_trait::async_trait;

struct MyLifetimeType<'a> {
  s: &'a mut String,
}

#[async_trait]
trait MyTrait<T> {
  async fn handle(&self, t: T) where T: 'async_trait;
}

struct MyImpl;

#[async_trait]
impl<'a> MyTrait<MyLifetimeType<'a>> for MyImpl {

  async fn handle(&self, t: MyLifetimeType<'a>) {
    t.s.push_str("hi");
  }
  
}
  • Related