What i'm trying to do is to create a simple web-service via Hyper.
And i want to pass a Database
structure to the router using make_service_fn
.
Thus i've ran into the problem: i can't clone a variable inside of the async move
block inside of a closure. But if i do it right before the async move
block - everything is fine.
Can someone explain why is that since i have to move a variable to the closure explicitly by move
but still running into the move out of ... occurs here
error ?
Concrete example:
Code
use hyper::server::conn::AddrStream;
use hyper::service::{make_service_fn, service_fn};
use hyper::{Body, Method, Request, Response, Server, StatusCode};
use std::convert::Infallible;
type ResponseFuture = Result<Response<Body>, Infallible>;
async fn router(req: Request<Body>, _db: Database) -> ResponseFuture {
let mut response = Response::new(Body::empty());
match (req.method(), req.uri().path()) {
(&Method::GET, "/hello") => {
*response.body_mut() = Body::from("OH HI");
}
(&Method::GET, "/create") => {
*response.status_mut() = StatusCode::NOT_FOUND;
*response.body_mut() = Body::from("NOT IMPLEMENTED YET");
}
_ => {
*response.status_mut() = StatusCode::NOT_FOUND;
}
}
Ok(response)
}
#[derive(Clone)]
struct Database;
#[tokio::main]
async fn main() {
let addr = ([127, 0, 0, 1], 3000).into();
let user_collection = Database;
let make_svc = make_service_fn(move |socket: &AddrStream| async move {
let collec = user_collection.clone();
Ok::<_, Infallible>(service_fn(move |req: Request<Body>| async move {
let coll = collec.clone();
Ok::<_, Infallible>(match router(req, coll).await {
Ok(val) => val,
Err(_e) => Response::new(Body::empty()),
})
}))
});
let server = Server::bind(&addr).serve(make_svc);
if let Err(e) = server.await {
eprintln!("server error: {}", e);
}
}
Errors
error[E0507]: cannot move out of `collec`, a captured variable in an `FnMut` closure
--> src/main.rs:53:77
|
52 | let collec = user_collection;
| ------ captured outer variable
53 | Ok::<_, Infallible>(service_fn(move |req: Request<Body>| async move {
| _____________________________________________________________________________^
54 | | let coll = collec.clone();
| | ------
| | |
| | move occurs because `collec` has type `Database`, which does not implement the `Copy` trait
| | move occurs due to use in generator
55 | | Ok::<_, Infallible>(match router(req, coll).await {
56 | | Ok(val) => val,
57 | | Err(_e) => Response::new(Body::empty()),
58 | | })
59 | | }))
| |_________^ move out of `collec` occurs here
error[E0507]: cannot move out of `user_collection`, a captured variable in an `FnMut` closure
--> src/main.rs:51:74
|
49 | let user_collection = Database;
| --------------- captured outer variable
50 |
51 | let make_svc = make_service_fn(move |socket: &AddrStream| async move {
| __________________________________________________________________________^
52 | | let collec = user_collection;
| | ---------------
| | |
| | move occurs because `user_collection` has type `Database`, which does not implement the `Copy` trait
| | move occurs due to use in generator
53 | | Ok::<_, Infallible>(service_fn(move |req: Request<Body>| async move {
54 | | let coll = collec.clone();
... |
59 | | }))
60 | | });
| |_____^ move out of `user_collection` occurs here