Random thing I wanted to jot down that I was just reminded of. For a long time, we've had this annoyance that you can't implement an impl that is generic over all fn types. This is true for a few reasons: the need for variadic generics is one of them, but also the need to be generic over all ABIs, and the fact that fn(T) cannot equal for<'a> fn(&'a u32) for any type T, as T cannot name the bound region 'a.
A long time I was thinking about adding a fundamental, built-in trait FnPointer that is implemented for all fn types (and for nothing else). Manual impls of this would be illegal, like Sized. It could be as simple as a single method, that converts the fn pointer to a usize. This would allow implementing PartialEq, Eq, Hash, and all those other methods in terms of that method.
In other words, you could write things like:
impl<T: FnPointer> PartialEq for T { ... }
I believe that if FnPointer is a fundamental trait, this would not overlap with other impls of PartialEq and friends. It's not perfect, you couldn't have an impl<T: Foo> PartialEq for T for some other trait. I doubt we have such an impl but maybe we do; I'd have to check the other traits that fn types implement.
I always felt this was too .. idk, hacky or something, but the more I think about it the more I feel like it's an obvious practical sol'n to an annoying set of problems. Has this been proposed and discussed before?
Another option would be something like struct Func<F> { ... } where F: FnPointer. We could then make fn(T) -> B desugar to Func<???> and all zero-sized function types would also desugar to Func<???> (with a unique type inside the Func).
If its only method is going to be "convert to usize", maybe it should be implemented for everything that "naturally" points to a code location? I'm thinking function pointers, closures, and function items. This is especially useful for closures, because there is no way on stable to get the "code location" of a closure, which you might want to use for "code equality" or something like that (I recently had a need for this, and gave up and used function pointers).
The alternative might be to prove methods like is_eq, hash, and so forth, which doesn't really effect this question of what it ought to be applied to necessarily.
I mean, I'm mostly interested in building a sandbox that prevents recursion. There's other ways around this, but checking that the same usize value doesn't appear twice is a good-enough approximation (though not quite perfect, since function pointer equality is made of sharp edges and broken dreams[1]).
Related to @RustyYato's proposal would be a trait for fn pointers and fn items / ZSTs, which I realized could be generalized to closures that have a const inhabitant: