I'm fighting with a function that takes an Option<FnMut(String) -> ()> as parameter when I want to pass None, because the type of T cannot be deferred.
fn maybe_closure<T: FnMut(String) -> ()>(closure: Option<T>) -> () {
...
}
// Works
maybe_closure(Some(...));
// Does not compile
maybe_closure(None);
The compiler tells me
11 | maybe_closure(None);
| ^^^^^^^^^^^^^^^^^^ cannot infer type for `T`
|
= note: type annotations or generic parameter binding required
I get that. But I have no idea how to actually specify T, because if I use None::<FnMut(String) -> () the compiler explains
|
11 | maybe_closure("Deutsche Bank", None::<FnMut(String) -> ()>);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Sized` is not implemented for `std::ops::FnMut(std::string::String)`
|
= note: `std::ops::FnMut(std::string::String)` does not have a constant size known at compile-time
= note: required by `std::prelude::v1::None`
I also get that.
But I have no idea how to solve this issue satisfying the compiler and me.
I think None::<Box<FnMut(String) -> ()>> should work. The error is because the size of the closure is unknown at compile time, so you have to box it.
Someone correct me if I'm wrong 'cause I'm not so expert.
That's because Rust doesn't know what is the type of T. An easy workaround would be to provide any type that fits T, the easiest pick would be function literal pointer.
maybe_closure(None::<fn(_)>);
Unfortunately, this is ugly, you may want to try providing a different API, depending on what None actually means in your API.
If semantics of None are essentially doing nothing, then don't accept Option, and just specify empty function like || {} as an argument. As the function is generic over types, and closures have different types the compiler will be able to optimize that out by inlining. No need to micro-optimise
I hit this exact same issue while adding a new test in my code. I had a helper function and wanted to add an optional function to invoke at a certain point. After struggling with the same errors you did I gave up and just defined a fn nothing(...) to use instead of None.