4

I am trying to store a hyper::server::Server as a member of my struct (struct MyApp below). I can do this from, for example, my program's main() function.

How can I do this in my struct's MyApp::new() method? I think I need the concrete type for F in MyApp<F>. However, despite trying, I am unable to (correctly) specify a concrete type for this closure.

I can't figure out how to do this. I thought Boxing the closure would work by allowing me to pass the closure as a concrete type, and indeed it does when I do this in main(), but not MyApp::new(). I am hoping there is a way to do this in stable rust, as I would really like to implement a structure which contains a hyper Server.

Here is my struct:

struct MyApp<F> { hyper_server: Server<MyBoxedClosure<F>, hyper::Body>, } 

And here is the full code that works -- it sets the MyApp.hyper_server field in main():

extern crate hyper; extern crate futures; use hyper::Error; use hyper::server::{Http, Server, NewService, Service, Request, Response}; use hyper::header::ContentLength; pub struct HelloWorld; const PHRASE: &'static str = "Hello, World!"; impl Service for HelloWorld { type Request = Request; type Response = Response; type Error = hyper::Error; type Future = futures::future::FutureResult<Self::Response, Self::Error>; fn call(&self, _req: Request) -> Self::Future { futures::future::ok( Response::new() .with_header(ContentLength(PHRASE.len() as u64)) .with_body(PHRASE), ) } } pub struct MyBoxedClosure<F> { value: Box<F>, } impl<F> NewService for MyBoxedClosure<F> where F: Fn() -> std::result::Result<HelloWorld, std::io::Error>, { type Request = Request; type Response = Response; type Error = Error; type Instance = HelloWorld; fn new_service(&self) -> std::result::Result<Self::Instance, std::io::Error> { self.value.new_service() } } struct MyApp<F> { hyper_server: Server<MyBoxedClosure<F>, hyper::Body>, } fn main() { let mbc = MyBoxedClosure { value: Box::new(|| Ok(HelloWorld)) }; let addr = "127.0.0.1:3000".parse().unwrap(); let hyper_server = Http::new().bind(&addr, mbc).unwrap(); let my_app = MyApp { hyper_server: hyper_server }; println!("Hello, world!"); } 

If I create a MyApp::new() function and call that from the main() instead, I can't figure out how to avoid a compiler error.

impl<F> MyApp<F> where F: Fn() -> std::result::Result<HelloWorld, std::io::Error> + Send + Sync, { fn new() -> MyApp<F> { let mbc = MyBoxedClosure { value: Box::new(|| Ok(HelloWorld)) }; let addr = "127.0.0.1:3000".parse().unwrap(); let hyper_server = Http::new().bind(&addr, mbc).unwrap(); MyApp { hyper_server: hyper_server } } } fn main() { let _my_app = MyApp::new(); println!("Hello, world!"); } 

The compiler error is this:

error[E0308]: mismatched types --> src/main.rs:56:9 | 56 | MyApp { hyper_server: hyper_server } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected type parameter, found closure | = note: expected type `MyApp<F>` found type `MyApp<[closure@src/main.rs:53:52: 53:69]>` 
13
  • You create generic function that should return any type user want fn new() -> MyApp<F>, but you return concrete type instead of F Commented Jul 23, 2017 at 9:58
  • 1
    @AndrewStraw closure or not is not important. Import that you tell fn new() -> MyApp<F> I return any type you want, and then you return conrete type. Note that your signature allow too call like this let a = MyApp::<String>::new(), while your new obviouse return not MyApp<String> Commented Jul 23, 2017 at 12:16
  • 1
    Right. Now it's a duplicate of Returning a closure from a function. Commented Jul 23, 2017 at 12:34
  • 1
    @AndrewStraw You should redo your code, the most simple way is remove F completly make MyBoxedClosure concrete type with Box<Fn(..> something as field. Commented Jul 23, 2017 at 14:01
  • 1
    Here's one solution. As @user1034749 mentions, replacing the type parameter with a boxed trait object is currently the best way to return a closure. Commented Jul 23, 2017 at 15:00

0

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.