0
votes

I'm learning rust and I'm struggling to understand why the following code does not compile with some "Error[E0505]: cannot move out of req because it is borrowed" error on the req.into_body(). If I remove the println! or move it before the match, it runs.

async fn hello_world(req: Request<Body>) -> Result<Response<Body>, Infallible> {
  let mut response = Response::new(Body::empty());

  let method = req.method();
  let path = req.uri().path();

  match (method, path) {
    (&Method::GET, "/") => {
      *response.body_mut() = Body::from("Try POSTing data to /echo");
    }
    (&Method::POST, "/echo") => {
      *response.body_mut() = req.into_body();
    }
    _ => {
      *response.status_mut() = StatusCode::NOT_FOUND;
    }
  };
  println!("{} {}", method, path);

  Ok(response)
}

I understand some of the borrowing, but I don't understand why the position of the println changes anything, as I'm already defining non mutable variables that are used successfully in the match.

1
Try req.method().clone() and req.uri().path().clone() in the beginning in case those methods return references on request, not standalone objectsAlexey Larionov
I tried that before posting, but it doesn't help.e741af0d41bc74bf854041f1fbdbf

1 Answers

1
votes

You cannot have mutable and immutable borrow at the same time. For your case, would be a converting the borrowed types (return of method() and uri().path()) to owned ones. You can do it via ToOwned::to_owned, or via explicit conversions (playground):

async fn hello_world(req: Request<Body>) -> Result<Response<Body>, Infallible> {
    let mut response = Response::new(Body::empty());

    let method = req.method().clone(); // &Method -> Method
    let path = req.uri().path().to_string(); // &str -> String
    // `req` is not borrowed at this point, so it can be mutated

    match (method.clone(), path.as_str()) {
        (Method::GET, "/") => {
            *response.body_mut() = Body::from("Try POSTing data to /echo");
        }
        (Method::POST, "/echo") => {
            *response.body_mut() = req.into_body();
        }
        _ => {
            *response.status_mut() = StatusCode::NOT_FOUND;
        }
    };
    println!("{} {}", method, path);

    Ok(response)
}