Reputation: 1922
I replaced fn(x) -> y
typing with FnMut(x) -> y
according to my needs and according to what was suggested for me here. But I got another error:
trait objects must include the
dyn
keyword
This is minimal sandbox that reproduces the error.
I tried to investigate the issue. So, I found this. After that I tried to add dyn. But since I got error that size in not known at compile time, I also tried to add Box
to typing like:
-> vector<Box<dyn FnMut(HandlerInput) -> Result<HandlerResponse, Error>>>
and after that tried to wrap handlers with Box::new()
, but still have no success. I feel like I do something wrong.
Could somebody explain me how to fix this issue ? Maybe dyn not what I should use ? (I also tried to use impl instead, but this not helped)
Upvotes: 7
Views: 6728
Reputation: 8678
There is a huge difference between fn(x) -> y
and FnMut(x) -> y
: the former is a type (basically, it's a pointer to a function), while the second is a trait. This means that you can't switch the one for the other. Fortunately, there is a way (actually, multiple ways) to tell Rust that you want to accept any type that implements a given trait. One of these is trait objects, whose syntax is dyn Trait
where Trait
is a trait.
Traits objects use dynamic dispatch, which means that Rust allows any type that implements a given trait Trait
to be passed where a dyn Trait
was expected, and the information about where the different methods are found for a given value of type dyn Trait
is provided by runtime information (ie. that value also has a little table included providing that information). This means that, for instance, Rust cannot know the size of dyn Trait
at compile time, simply because it could be any value, as long as its type implements Trait
. For this reason, you need to allocate it on the heap, and pass a pointer to the allocated data instead. This is the job of Box
.
The solution is therefore to replace any occurence of Trait
as a type declaration with Box<dyn Trait>
(in your case, Box<dyn FnMut(HandlerInput) -> Result<HandlerResponse, Error>>>
) and make the appropriate changes (ie. (un)box your closures).
Upvotes: 8