6

I am trying to mutably borrow a mutable variable. Deref and DerefMut are implemented for Foo, but compilation fails:

use std::ops::{Deref, DerefMut};

struct Foo;

impl Deref for Foo {
    type Target = FnMut() + 'static;
    fn deref(&self) -> &Self::Target {
        unimplemented!()
    }
}

impl DerefMut for Foo {
    fn deref_mut(&mut self) -> &mut Self::Target {
        unimplemented!()
    }
}

fn main() {
    let mut t = Foo;
    t();
}
error[E0596]: cannot borrow immutable borrowed content as mutable
  --> src/main.rs:20:5
   |
20 |     t();
   |     ^ cannot borrow as mutable

Newer versions of the compiler have an updated error message:

error[E0596]: cannot borrow data in a dereference of `Foo` as mutable
  --> src/main.rs:20:5
   |
20 |     t();
   |     ^ cannot borrow as mutable
   |
   = help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `Foo`
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
chabapok
  • 921
  • 1
  • 8
  • 14

1 Answers1

5

This is a known issue regarding how the function traits are inferred through Deref. As a workaround, you need to explicitly get a mutable reference by doing a mutable reborrow:

let mut t = Foo;
(&mut *t)();

or by calling DerefMut::deref_mut:

let mut t = Foo;
t.deref_mut()();
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
  • 1
    Given this is a work-around, I would really favour using a method-name. It makes finding the pattern more easily (search for `deref_mut()(`). – Matthieu M. Sep 28 '17 at 15:10