title: How to allow immutable and mutable borrows to coexist in a function with explicit lifetimes?
body: <p>For context: I'm implementing an Entity, basically a thin wrapper around a heterogenous map, and trying to implement an <code>update</code> method:</p>
  <pre class="lang-rust prettyprint-override"><code>struct Entity {
      pub id: u64,
      data: HashMap&lt;TypeId, Box&lt;dyn Any&gt;&gt;,
  }
  
  impl Entity {
  
      pub fn new(id: u64) -&gt; Self {
          Entity { id, data: HashMap::new() }
      }
  
      pub fn get_atom&lt;T: Any&gt;(&amp;self) -&gt; Option&lt;&amp;T&gt; {
          self.data.get(&amp;TypeId::of::&lt;T&gt;())?.downcast_ref()
      }
  
      pub fn set_atom&lt;T: Any&gt;(&amp;mut self, value: T) {
          self.data.insert(TypeId::of::&lt;T&gt;(), Box::new(value));
      }
  
      pub fn update&lt;T: Any, R: Any&gt;(&amp;mut self, f: impl Fn(&amp;T) -&gt; R) 
      {
          if let Some(val) = self.get_atom() {
              self.set_atom(f(val));
          }
      }
  }
  </code></pre>
  <p>This works, but gives a warning:</p>
  <pre class="lang-rust prettyprint-override"><code>warning: cannot borrow `*self` as mutable because it is also borrowed as immutable
    --&gt; src/entity.rs:71:13
     |
  70 |         if let Some(val) = self.get_atom() {
     |                            --------------- immutable borrow occurs here
  71 |             self.set_atom(f(val));
     |             ^^^^^^^^^^^^^^^^---^^
     |             |               |
     |             |               immutable borrow later used here
     |             mutable borrow occurs here
  </code></pre>
  <p>OK, that's fixable like this, which removes the warning.</p>
  <pre><code>    pub fn update&lt;T: Any, R: Any&gt;(&amp;mut self, f: impl Fn(&amp;T) -&gt; R) 
      {
          let maybe : Option&lt;R&gt; = self.get_atom().map(f);
          if let Some(val) = maybe {
              self.set_atom(val);
          }
      }
  </code></pre>
  <p>The problem I have is when I introduce a trait for abstracting over getting stuff out of the entity (which permits me to abstract over arity: getting a tuple returns a value if each of the components is in the entity):</p>
  <pre class="lang-rust prettyprint-override"><code>trait GetComponent&lt;'a, T&gt; {
      fn get_component(entity: &amp;'a Entity) -&gt; Option&lt;T&gt;;
  }
  
  // sample atom impl
  impl &lt;'a&gt; GetComponent&lt;'a, &amp;'a u32&gt; for &amp;'a u32 {
      fn get_component(entity: &amp;'a Entity) -&gt; Option&lt;&amp;'a u32&gt; {
          entity.get_atom()
      }
  }
  
  // sample composite impl
  impl &lt;'a, A, B&gt; GetComponent&lt;'a, (A, B)&gt; for (A, B) where 
      A: GetComponent&lt;'a, A&gt;, 
      B: GetComponent&lt;'a, B&gt;,
  {
      fn get_component(entity: &amp;'a Entity) -&gt; Option&lt;(A, B)&gt; {
          Some((A::get_component(entity)?, B::get_component(entity)?))
      }
  }
  
  impl Entity {
      &lt;in addition to the above&gt;
  
      pub fn get&lt;'a, T: GetComponent&lt;'a, T&gt;&gt;(&amp;'a self) -&gt; Option&lt;T&gt; {
          T::get_component(self)
      }
  
      pub fn update&lt;'a, T: 'a, R: Any&gt;(&amp;'a mut self, f: impl Fn(&amp;T) -&gt; R) 
          where &amp;'a T: GetComponent&lt;'a, &amp;'a T&gt;
      {
          let maybe : Option&lt;R&gt; = self.get().map(f);
          if let Some(val) = maybe {
              self.set_atom(val);
          }
      }
  }
  </code></pre>
  <p>The trait requires me to be explicit about lifetimes, and everything else I've tried to do so far with the entity seems to be just fine. But this update method gives this compile error (not a warning this time):</p>
  <pre class="lang-rust prettyprint-override"><code>error[E0502]: cannot borrow `*self` as mutable because it is also borrowed as immutable
    --&gt; src/entity.rs:56:13
     |
  51 |     pub fn update&lt;'a, T: 'a, R: Any&gt;(&amp;'a mut self, f: impl Fn(&amp;T) -&gt; R) 
     |                   -- lifetime `'a` defined here
  ...
  54 |         let maybe : Option&lt;R&gt; = self.get().map(f);
     |                                 ----------
     |                                 |
     |                                 immutable borrow occurs here
     |                                 argument requires that `*self` is borrowed for `'a`
  55 |         if let Some(val) = maybe {
  56 |             self.set_atom(val);
     |             ^^^^^^^^^^^^^^^^^^ mutable borrow occurs here
  </code></pre>
  <p>Now, as far as I can see, there's no reason why I shouldn't be able to immutably borrow for a shorter period, so the immutable borrow &quot;expires&quot; before I do the mutation - just like in the version without explicit lifetimes used prior to the trait.</p>
  <p>But I can't for the life of me work out how to make this work.</p>