# Callbacks: Accept immutable where mutable is accepted

**URL:** <https://internals.rust-lang.org/t/callbacks-accept-immutable-where-mutable-is-accepted/6005>\
**Category:** Uncategorized\
**Created:** [October 4, 2017, 4:37pm UTC](https://internals.rust-lang.org/t/callbacks-accept-immutable-where-mutable-is-accepted/6005 "2017-10-04T16:37:35Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![derekdreery](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/derekdreery/32/2632_2.png) [@derekdreery](https://internals.rust-lang.org/u/derekdreery)\
**Post date:** [October 4, 2017, 4:37pm UTC](https://internals.rust-lang.org/t/callbacks-accept-immutable-where-mutable-is-accepted/6005/1 "2017-10-04T16:37:36Z")

</div>

Suppose you have a function that takes a callback

```rust
Fn(&mut Obj)

```

is there a time that a function like

```rust
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.

---

<div class="post-metadata">

**Author:** ![cuviper](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cuviper/32/1897_2.png) [@cuviper](https://internals.rust-lang.org/u/cuviper)\
**Post date:** [October 4, 2017, 5:19pm UTC](https://internals.rust-lang.org/t/callbacks-accept-immutable-where-mutable-is-accepted/6005/2 "2017-10-04T17:19:46Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![ExpHP](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/exphp/32/6208_2.png) [@ExpHP](https://internals.rust-lang.org/u/ExpHP)\
**Post date:** [October 4, 2017, 8:29pm UTC](https://internals.rust-lang.org/t/callbacks-accept-immutable-where-mutable-is-accepted/6005/3 "2017-10-04T20:29:02Z")

</div>

I like @Gankra's [original reflection on this idea](https://github.com/rust-lang/rfcs/pull/1353#issuecomment-154868483):

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

---

<div class="post-metadata">

**Author:** ![Boscop](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/boscop/32/3820_2.png) [@Boscop](https://internals.rust-lang.org/u/Boscop)\
**Post date:** [October 17, 2017, 7:42pm UTC](https://internals.rust-lang.org/t/callbacks-accept-immutable-where-mutable-is-accepted/6005/4 "2017-10-17T19:42:36Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![system](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/system/32/14092_2.png) [@system](https://internals.rust-lang.org/u/system)\
**Post date:** [March 25, 2019, 8:29am UTC](https://internals.rust-lang.org/t/callbacks-accept-immutable-where-mutable-is-accepted/6005/5 "2019-03-25T08:29:04Z")

</div>

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.
