BeGo
BeGo

Reputation: 175

Generic Trait for SQLx and reference

I have created a generic trait, and I am implementing it in a sqlx query, but I get an error

what am I doing wrong?

#[async_trait]
pub trait ITodoRepo<P> {
    async fn list(pool:&P) -> Result<Vec<TodoType>>;
   
}
pub struct TodoRepo;
#[async_trait]
impl<P: sqlx::Executor<'static, Database = sqlx::Postgres>> ITodoRepo<P> for TodoRepo {
    async fn list(pool: &P) -> Result<Vec<TodoType>> {
        let rowset = sqlx::query_as!(
            TodoSchema, 
            r#"SELECT * FROM todo"#)
            .fetch_all(pool)
            .await?
            .iter()
            .map(|row| hydrate(row))
            .collect();

        Ok(rowset)
    }
}

How can I implement the Executor?

error[E0637]: `'_` cannot be used here
 --> src/todo.rs:21:24
   |
21 |             .fetch_all(pool)
   |                        ^^^^ the trait `sqlx::Executor<'_>` is not implemented for `&P`

Upvotes: 1

Views: 1040

Answers (1)

Mihir Luthra
Mihir Luthra

Reputation: 6779

In you question, as per fn list(pool: &P), the type of pool is &P. But the fetch_all() method seems to require an argument that implement trait sqlx::Executor<'_>. P implements that trait as per your impl but &P doesn't.

Here is a minimal reproducible code for your question:

trait MyTrait {}

struct MyStruct;

impl MyTrait for MyStruct {}

fn func<T: MyTrait>(arg: T) {
    todo!()
}

fn main() {
    let var = MyStruct;
    let ref_to_var = &var;
    func(ref_to_var);
}

Playground

Basically your function is expecting a type T that implements some trait MyTrait but you are passing &T.

To fix this, you can either change to function to accept a reference. Like in the above example:

fn func<T: MyTrait>(arg: &T) {
    todo!()
}

Playground

Or you could implement the trait for the reference itself:

impl MyTrait for &MyStruct {}

Playground

Upvotes: 2

Related Questions