Getting: error[E0382]: use of moved value: `shared_pool`

Getting getting:

error[E0382]: use of moved value: `shared_pool`
  --> src/main.rs:51:43
   |
43 |     let shared_pool = Arc::new(pool);
   |         ----------- move occurs because `shared_pool` has type `Arc<Pool<Postgres>>`, which does not implement the `Copy` trait
...
47 |     .route("/api/todos", get(move || get_todos(shared_pool.clone())))
   |                              -------           ----------- variable moved due to use in closure
   |                              |
   |                              value moved into closure here
...
51 |     .route("/api/todo/delete/:id", delete(move |path: Path<i32>| {
   |                                           ^^^^^^^^^^^^^^^^^^^^^^ value used here after move
52 |         // let pool_clone = Arc::clone(&shared_pool);
53 |         delete_todo(path, shared_pool.clone())
   |                           ----------- use occurs due to use in closure

For more information about this error, try `rustc --explain E0382`.
warning: `todo` (bin "todo") generated 8 warnings
error: could not compile `todo` due to previous error; 8 warnings emitted

Here is my main.rs

use std::sync::{Arc, Mutex};

use axum::{
    
     routing::{get, post, put, delete},  Json, Router, middleware::AddExtension, Extension, extract::Path
    
};










mod db;
use db::create_db_pool;


mod handlers;
use handlers::{get_todos, create_todo,delete_todo, root};


mod model;
use model::NewTodo;







#[tokio::main]
async fn main() {
    
    let pool = create_db_pool().await;
    let pool_clone = pool.clone(); 
    let editPool = pool.clone();


    let shared_pool = Arc::new(pool);

    let app = Router::new()
    .route("/", get(root))
    .route("/api/todos", get(move || get_todos(shared_pool.clone())))
    .route("/api/todo/create", post(move |Json(new_todo): Json<NewTodo>| {
        create_todo(axum::Json(new_todo),pool_clone.clone())
    }))
    .route("/api/todo/delete/:id", delete(move |path: Path<i32>| {
        // let pool_clone = Arc::clone(&shared_pool);
        delete_todo(path, shared_pool.clone())
    }));
    // .route("/api/todo/delete/:id", delete(delete_todo));
    // .layer(Extension( shared_pool));

    


    
    
    
    
    

    println!("🚀 Server started successfully");
    axum::Server::bind(&"0.0.0.0:8000".parse().unwrap())
        .serve(app.into_make_service())
        .await
        .unwrap();
}


and my delete handler is :

os)
}


pub async fn create_todo(Json(new_todo): Json<NewTodo>, pool: PgPool) -> impl IntoResponse {
    let title = new_todo.title;
    let description = new_todo.description;
    let completed = new_todo.completed;

    let query_result = query!(
       
        "
        INSERT INTO todo_items (title, description, completed)
        VALUES ($1, $2, $3)
        RETURNING *",
        title,
        description,
        completed
        
    )
    .fetch_one(&pool)
    .await;

    match query_result {
        Ok(row) => {
            let new_id = row.id;
            Json(json!({
                "status": "success",
                "message": "Todo created successfully",
                "new_id": new_id
            }))
        }
        Err(_) => {
            // Handle error case
            // You can return an error response or customize it as needed
            // For now, let's return a generic error response
            Json(json!({
                "status": "error",
                "message": "Failed to create todo"
            }))
        }
    }
}



// #[axum_macros::debug_handler] 
pub async fn delete_todo(
    Path(id): Path<i32>, 
    pool: Arc<PgPool>
// Extension(db_pool): Extension<Arc<Mutex<PgPool>>>
) -> impl IntoResponse {
    println!("delete_todo id = {}", id);


    
    
    // Use the id to delete the item from the database
    let delete_result = query!(
        "DELETE FROM todo_items WHERE id = $1",
        id
    )
    .execute(&*pool)
    .await;

    if delete_result.is_ok() {
        // Return a success response
        Json(json!({
            "status": "success",
            "message": format!("Todo item with ID {} deleted", id)
        }))
    } else {
        // Return an error response
        Json(json!({
            "status": "error",
            "message": format!("Failed to delete todo item with ID {}", id)
        }))
    }
   
}

You need to clone before moving the value and move the clone instead. I.e.

let shared_pool = Arc::new(pool);

let pool_for_todos = shared_pool.clone();

route("/api/todos", get(move || get_todos(pool_for_todos)));
3 Likes

That fixed it. Thank you.

1 Like

By the way, some people prefer writing cloning Arcs as Arc::clone(&shared_pool) instead, because Arc is a smart pointer where (unlike .clone()) most method calls will dereference to call a method on the pointed-to value, so readers might get confused believing the contents got cloned. Arc's own inherent method follow this convention of all not taking a self argument, so that as much of the method namespace is left open for the target types to use.

2 Likes