Reputation: 1209
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.
Upvotes: 0
Views: 68
Reputation: 3443
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)
}
Upvotes: 1