However, sometimes the f passed in is an Fn instead of an FnOnce. In this case, I would like the whole function returned by the combinator to also be an Fn. If I simply reference the Fn to get an FnOnce, I can call my original increment but it will return me an FnOnce — I want an Fn.
Clearly I cannot have two functions with the same name! Is there a way to create a unified version of the increment combinator that will use the first version if f is FnOnce and the second version if f is Fn?
You would need to have a single signature that correctly reveals all of these behaviors. If you were dealing with a normal trait you could implement on your own types, this would be possible with an approach looking like this:
Create your own struct with a field for the closure and make it generic over the closure.
Make an impl<F: FnOnce()> FnOnce() for MyStruct<F>
Make an impl<F: Fn()> Fn() for MyStruct<F>
Explicitly return that type instead of an impl FnOnce()
This way the compiler can deduce whether the type is Fn by looking at the generic parameter on it. Unfortunately it is not possible to manually implement the Fn traits on your own types, so this is not possible.
Note that the actual type of the closure you're implementing actually does exactly as above, so if you could name the type of the closure explicitly that would also work. Unfortunately the type of the closure is not nameable, so this is also not possible.