I was able to create a minimal reproduction on the playground.
use async_trait::async_trait;
// stubbed out types to make things compile
type Result<T> = std::result::Result<T, ()>;
trait Executor<'a>: Send + Sync {}
struct PgPool;
struct CustomerInput;
struct CustomerResponse;
#[async_trait]
pub trait CreateCustomer<DB> {
async fn create(pool: DB, input: &CustomerInput);
}
pub struct Customer {
name: String,
}
pub struct CustomerRepository;
#[async_trait]
impl<DB: Executor<'_>> CreateCustomer<DB> for CustomerRepository {
async fn create(pool: &DB, input: CustomerInput) -> Result<CustomerResponse> {
todo!()
}
}
When I try to compile it, these are the errors I get:
Compiling playground v0.0.1 (/playground)
error[E0637]: `'_` cannot be used here
--> src/lib.rs:22:19
|
22 | impl<DB: Executor<'_>> CreateCustomer<DB> for CustomerRepository {
| ^^ `'_` is a reserved lifetime name
error[E0053]: method `create` has an incompatible type for trait
--> src/lib.rs:23:27
|
12 | async fn create(pool: DB, input: &CustomerInput);
| -- type in trait
...
22 | impl<DB: Executor<'_>> CreateCustomer<DB> for CustomerRepository {
| -- this type parameter
23 | async fn create(pool: &DB, input: CustomerInput) -> Result<CustomerResponse> {
| ^^^ expected type parameter `DB`, found `&DB`
|
= note: expected fn pointer `fn(DB, &'life0 CustomerInput) -> Pin<Box<(dyn Future<Output = ()> + Send + 'async_trait)>>`
found fn pointer `fn(&'life0 DB, CustomerInput) -> Pin<Box<(dyn Future<Output = std::result::Result<CustomerResponse, ()>> + Send + 'async_trait)>>`
error: aborting due to 2 previous errors
Some errors have detailed explanations: E0053, E0637.
For more information about an error, try `rustc --explain E0053`.
error: could not compile `playground`
To learn more, run the command again with --verbose.
The first error is saying you can't use '_
in the impl<DB: Executor<'_>> CreateCustomer<DB> for ...
, instead you should give the lifetime a name (e.g. impl<'a, DB: Executor<'a>>
).
The second error says your trait's create()
method signature is fn(DB, &CustomerInput)
but when you tried to implement it, you wrote a method with the signature fn(&DB, CustomerInput) -> Result<CustomerResponse>
.
Note how DB
is taken by value in one and reference in the other, CustomerInput
is taken by reference in one and value in the other, and one implementation returns Result<CustomerResponse>
while the other doesn't return anything.