title: Rust borrow mutable self inside match expression
body: <p>I have a problem with <code>self</code> borrowing in a <code>match</code> expression:</p>
  
  <pre><code>fn add_once(&amp;'t mut self, p_name: &amp;'t str) -&gt; Box&lt;Element&gt; {
      match self.get(p_name) {
          Some(x) =&gt; Box::new(*x),
          None =&gt; self.add(p_name),
      }
  }
  </code></pre>
  
  <p>The signature of the <code>get()</code> and <code>add()</code> functions are:</p>
  
  <pre><code>fn get(&amp;self, p_name: &amp;str) -&gt; Option&lt;&amp;Element&gt;
  fn add(&amp;'t mut self, p_name: &amp;'t str) -&gt; Box&lt;Element&gt;
  </code></pre>
  
  <p>The compiler refuses this code:</p>
  
  <pre class="lang-none prettyprint-override"><code>error[E0502]: cannot borrow `*self` as mutable because it is also borrowed as immutable
    --&gt; src/main.rs:38:21
     |
  36 |         match self.get(p_name) {
     |               ---- immutable borrow occurs here
  37 |             Some(x) =&gt; Box::new(*x),
  38 |             None =&gt; self.add(p_name),
     |                     ^^^^ mutable borrow occurs here
  39 |         }
  40 |     }
     |     - immutable borrow ends here
  </code></pre>
  
  <p>I get that, but I don't see how I can rewrite the <code>match</code> expression.</p>
  
  <p>In a <a href="https://stackoverflow.com/questions/23032464/rust-cannot-borrow-self-as-mutable-because-self-history-is-also-borrow">related question</a>, it was solved by having the <code>match</code> return a value and then calling the function. However, that doesn't work here because the meaning of the conditional is not to choose a value but selectively execute an action.</p>
  
  <p>The full code sample is below:</p>
  
  <pre><code>struct Element&lt;'e&gt; {
      name: &amp;'e str, 
  }
  
  impl&lt;'e&gt; Element&lt;'e&gt; {
      fn new(p_name: &amp;str) -&gt; Element {
          Element { name: p_name }
      }
  }
  
  struct Top&lt;'t&gt; {
      list: Vec&lt;Element&lt;'t&gt;&gt;,
  }
  
  impl&lt;'t&gt; Top&lt;'t&gt; {
      fn new() -&gt; Top&lt;'t&gt; {
          Top { list: vec![] }
      }
  
      fn get(&amp;self, p_name: &amp;str) -&gt; Option&lt;&amp;Element&gt; {
          for element in self.list.iter() {
              if element.name == p_name {
                  return Some(element);
              }
          }
          None
      }
  
      fn add(&amp;'t mut self, p_name: &amp;'t str) -&gt; Box&lt;Element&gt; {
          let new_element = Box::new(Element::new(p_name));
          self.list.push(*new_element);
          return new_element;
      }
  
      fn add_once(&amp;'t mut self, p_name: &amp;'t str) -&gt; Box&lt;Element&gt; {
          match self.get(p_name) {
              Some(x) =&gt; Box::new(*x),
              None =&gt; self.add(p_name),
          }
      }
  }
  
  fn main() {
      let mut t = Top::new();
      let plop1 = t.add_once("plop1");
      let plop2 = t.add_once("plop1");
  }
  </code></pre>