joey@voyager-pc ~/P/voyager> cargo run --example hello
Compiling voyager v0.1.0 (/home/joey/Projects/voyager)
error[E0308]: mismatched types
--> examples/hello.rs:20:49
|
20 | m.handle("/world".to_string(), Handler::new(world_handler));
| ^^^^^^^^^^^^^ expected closure, found a different closure
|
= note: expected type `[closure@examples/hello.rs:10:25: 13:6]`
found type `[closure@examples/hello.rs:14:25: 17:6]`
= note: no two closures, even if identical, have the same type
= help: consider boxing your closure and/or using it as a trait object
error: aborting due to previous error
For more information about this error, try `rustc --explain E0308`.
error: Could not compile `voyager`.
To learn more, run the command again with --verbose.
Since my Handler struct is a generic struct, why these 2 lines doesn't compile
This is because, as the error explains, the closures are not ambiguous in the compiler's eyes. Meaning that they are different functions/closures defined at different places, and therefore require using some kind of interface to interact with it so that it can be changes. The first closure has a type, technically named [closure@examples/hello.rs:10:25: 13:6] but we'll call it A and the second one technically has a name, [closure@examples/hello.rs:14:25: 17:6] but we'll call it B. The Mux<T> object requires that its T impls Fn(&ResponseWriter, &Request) + Clone. This is true for both A and B. But this doesn't mean you can put bothA and B into Mux<T>. I.E. if I had this case:
trait Foo {}
struct A;
impl Foo for A {}
struct B;
impl Foo for B {}
struct Cont<T: Foo> {_a: std::marker::PhantomData<T>}
In this case, we would be able initialize Cont with any generic type that implements Foo, but not put any other type in there. This is the problem, so I'd solve it by changing your handler to look like this:
This uses dynamic dispatch, meaning that it's the type equivalent of HRTBs (Or in other words, it allows _any type that impls Fn(&ResponseWriter, &Request) + Clone in there)
It's a trait for the closure(s), it will be using dynamic dispatch. Closures are unnamed types so if your specifying one type then you have to use generics / impl Trait.
Compile with #![warn(bare_trait_objects)] to see where code should use dyn. (No idea why warning hasn't been turned on in 2018 edition.)