Mismatch Type Error

Hi, I'm working on project using actix-web. I'm trying to display database data at the view layer. Here's the struct that bind to the entity:

#[derive(Serialize)]
struct IndexTemplateData {
    project_name: String,
    books: Vec<self::model::Book>,
}

And here is the code of the controller for the index page:

async fn index(
    hb: web::Data<Handlebars<'_>>,
    pool: web::Data<DbPool>,
) -> Result<HttpResponse, std::io::Error> {
    let connection = pool.get().expect("Can't get db connection pool");
    let books_data = web::block(move || books.limit(100).load::<Book>(&mut connection))
        .await
        .map_err(|_| HttpResponse::InternalServerError().finish());

    let data = IndexTemplateData {
        project_name: "Book Store".to_string(),
        books: books_data,
    };

    let body = hb.render("index", &data).unwrap();

    Ok(HttpResponse::Ok().body(body))

    
}

The error lies here:

 let data = IndexTemplateData {
        project_name: "Book Store".to_string(),
        books: books_data,
    };

And this is the error message:

error[E0308]: mismatched types
  --> src/main.rs:33:16
   |
33 |         books: books_data,
   |                ^^^^^^^^^^ expected struct `std::vec::Vec`, found enum `std::result::Result`
   |
   = note: expected struct `std::vec::Vec<model::Book>`
                found enum `std::result::Result<std::result::Result<std::vec::Vec<model::Book>, diesel::result::Error>, actix_web::HttpResponse>`

I can't figure it out despite many effort.

This expression returns a result. You can see this from block's signature (impl Future<Output = Result<R, BlockingError>> means that awaiting the return value results in a Result<R, BlockingError>). The R is the return type of the inner function that you call block with. Afterwards, you've called Result::map_err on it. IndexTemplateData's field books is a Vec, so books: books_data is an error because you can't set the value of books to a Result. I think because actix-web's errors can be turned into std::io::Errors, you can just do

    let books_data = web::block(move || books.limit(100).load::<Book>(&mut connection))
        .await?;

This will probably still cause the same situation, as this only handles the result from block but not the inner function, which probably returns a result as well. If so, you can try

    let books_data = web::block(move || books.limit(100).load::<Book>(&mut connection))
        .await??;

or

    let books_data = web::block(move || books.limit(100).load::<Book>(&mut connection))
        .await?
        .map_err( /* convert the error into std::io::Error */ )?;
1 Like

Hi, thanks. Fixed. I changed the type of book from vec to result<vec,httpresponse>.