Callbacks: Accept immutable where mutable is accepted


#1

Suppose you have a function that takes a callback

Fn(&mut Obj)

is there a time that a function like

Fn(&Obj)

would not be valid? If not, aren’t valid functions of the form Fn(&Obj) a subset of Fn(&mut Obj), and so the compiler could accept &Obj in place of &mut Obj?

I am modifing some code, and I am writing functions with &mut, when & would suffice and be more descriptive.


#2

I think would always be valid, because you can always get a & from &mut simply with &*x, and often just implicitly. If you wrap it in a closure like |x: &mut T| immut(x) then it will auto-ref to &T as needed.

But I don’t think the Fn itself can be coerced. Not that it’s impossible, just that it doesn’t happen now. ISTR that idea has been discussed before though.


#3

I like @Gankro’s original reflection on this idea:

Finally, there’s a moonshot alternative here: impl<F> Fn(.., &mut, ..) for F where F: Fn(.., &, ..), which would allow us to upgrade this interface (and ones like it) without any breakage. This would have to be an exceptionally magical implementation, and may cause coherence, inference, and resolution to all melt into a pile of poop. That said, as far as I can tell it would be sound.


#4

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.)