This issue applies to e.g. return types too.
So I think it shouldn’t be hardcoded to only work for function argument types.
A <: B => Fn() -> A <: Fn() -> B (return types are covariant).
E.g. if I have
fn foo<F: Fn() -> &T>(f: F), I could pass it a function
Fn() -> &mut T
A <: B => Fn(B) -> A <: Fn(A) -> B (argument types are contravariant)
Lets say you’re using a crate that has a function that takes a
Vec<Box<Fn(&mut T) -> &T>> and you want to pass it a
Vec<Box<Fn(&T) -> &mut T>>.
That would be sound and should be accepted by the compiler.
This issue also applies to function pointers and all other situations where covariance/contravariance plays a role, e.g. generics.
Btw, what is the current attitude/roadmap towards covariance/contravariance for generics? (It would make sense to consider this issue in that larger context.)