Mismatched Type while returning generic Struct


#1

I am trying to create Connection Pool and hold it in struct DBPool but getting mismatch error during compilation. Stuck on this for last one day and unable to figure out.

Thanks in advance.

 extern crate r2d2;
 extern crate r2d2_postgres;

 use std::thread;
 use r2d2:: {Pool, ManageConnection};
 use r2d2_postgres::{TlsMode, PostgresConnectionManager};

fn main() {

    let pool = DBPool::<PostgresConnectionManager>::new();
    println!("{:?}", pool.pool);
}

struct DBPool <M: ManageConnection>{
    pool: Pool<M>
}

impl<M: ManageConnection> DBPool<M> {
    fn new()-> DBPool<M>  {
        let config = r2d2::Config::default();
        let manager = PostgresConnectionManager::new("postgresql://root@localhost:26257/db?sslmode=disable", TlsMode::None).unwrap();
        let p =  r2d2::Pool::new(config, manager).unwrap() ;
    
        println!("Pool p: {:?}", p);
        DBPool { pool: p}
    }
}

Compilation error:

➜  dbcon git:(master) ✗ cargo run
   Compiling dbcon v0.1.0 (file:///Users/arvindbir/projects/rust/dbcon)
error[E0308]: mismatched types
  --> src/main.rs:42:9
   |
42 |         DBPool { pool: p}
   |         ^^^^^^^^^^^^^^^^^ expected type parameter, found struct `r2d2_postgres::PostgresConnectionManager`
   |
   = note: expected type `DBPool<M>`
              found type `DBPool<r2d2_postgres::PostgresConnectionManager>`

error: aborting due to previous error

error: Could not compile `dbcon`.

#2

The caller of new gets to decide what M is, not the implementation. If you only support PostgresConnectionManager, you’d have to adjust the definition of new to indicate that:

impl DBPool<PostgresConnectionManager> {
    fn new() -> DBPool<PostgresConnectionManager> {
        ...
    }
}

#3

And if I want to keep it generic then how will it look from caller side?


#4

They’d need to pass the initialized ConnectionManager in via your constructor.

That’s usually how dependency injection (what you’re effectively doing by making DBPool generic) works. If you’re making it generic that’s like saying “the user can use this with any type they want as long as it satisfies these trait bounds”.


#5

Ah, got it.

Thank you so much sfackler and Michael.