title: Enforcing lifetimes on temporary values containing references
body: <p>I am using <a href="http://doc.rust-lang.org/std/collections/struct.HashMap.html" rel="nofollow noreferrer"><code>HashMap</code></a> but I'm stumbling over how to "release" a mutable borrow of the <code>HashMap</code> and cannot find a good explanation of how to do this.</p>
  
  <p>This is just an example and that the goal is not to "solve the problem" but rather to understand how to accomplish this and/or why it should not be done this way.</p>
  
  <p>The example consists of a <code>HashMap</code> storing some simple <code>Record</code>s:</p>
  
  <pre><code>type Map = HashMap&lt;String, Record&gt;;
  
  pub struct Record {
      pub count: u32,
      pub name: String,
  }
  
  impl Record {
      fn new&lt;S: Into&lt;String&gt;&gt;(name: S) -&gt; Record {
          Record { name: name.into(), count: 0 }
      }
  
      pub fn add&lt;'a&gt;(&amp;'a mut self, inc: u32) -&gt; &amp;'a mut Record {
          self.count += inc;
          self
       }
   }
  </code></pre>
  
  <p>The <code>add</code> function is there to have a mutable function on the record but is not the real culprit here.</p>
  
  <p>We now want to implement a function that returns a reference to a <code>Record</code> in the <code>HashMap</code> so that we can modify it in-place. In addition to this, we want to be able to have control over the returned reference so that we can do some side effects (for this example it is sufficient that we assume that we want to print out what is happening, but it could be some other action to handle statistics and/or accessing some other storage or do lazy evaluation). To handle this, we introduce a <code>Handle</code> struct that keeps a reference to the <code>Record</code> as well as a reference to the <code>HashMap</code> that the record is coming from.</p>
  
  <pre><code>pub struct Handle&lt;'a&gt; {
      map: &amp;'a Map,
      record: &amp;'a Record,
  }
  
  impl&lt;'a&gt; Handle&lt;'a&gt; {
      fn new(record: &amp;'a Record, map: &amp;'a Map) -&gt; Handle&lt;'a&gt; {
           println!("Retrieving record");
           Handle { record: record, map: map }
      }
  
      fn mut_record(&amp;mut self) -&gt; &amp;mut Record {
          println!("Modifying record");
          self.record
      }
  }
  </code></pre>
  
  <p>Let's assume that we need both references for some reason and note that we are fine with retaining an immutable borrow to the <code>HashMap</code> while the handle is in existence, so no modifications of the <code>HashMap</code> should happen.</p>
  
  <p>The <code>Handle</code> is just temporary and we expect that it can be used roughly like this:</p>
  
  <pre><code>let mut map = HashMap::new();
  let foo = get_or_insert(&amp;mut map, "foo");
  foo.mut_record().do_something(|record| record.add(3))
  </code></pre>
  
  <p>The first implementation of <code>get_or_insert</code> is this:</p>
  
  <pre><code>pub fn get_or_insert&lt;'a, S&gt;(map: &amp;'a mut Map, name: S) -&gt; Handle&lt;'a&gt;
      where S: Into&lt;String&gt;
  {
      let key = name.into();
      let record = map.entry(key.clone()).or_insert(Record::new(key));
      Handle::new(record, map)
  }
  </code></pre>
  
  <p>This gives the following error:</p>
  
  <pre class="lang-none prettyprint-override"><code>error[E0502]: cannot borrow `*map` as immutable because it is also borrowed as mutable
    --&gt; hashmap.rs:65:29
     |
  64 |         let record = map.entry(key.clone()).or_insert(Record::new(key));
     |                      --- mutable borrow occurs here
  65 |         Handle::new(record, map)
     |                             ^^^ immutable borrow occurs here
  66 |     }
     |     - mutable borrow ends here
  </code></pre>
  
  <p>There are two references to the <code>HashMap</code> with the first one being a mutable borrow. We need to "release" the first mutable borrow of the map before we can grab an immutable borrow. I tried to write the code in this manner and added a scope around the first mutable borrow expecting it to be "released" when the scope ends:</p>
  
  <pre><code>pub fn get_or_insert&lt;'a, S&gt;(map: &amp;'a mut Map, name: S) -&gt; Handle&lt;'a&gt;
      where S: Into&lt;String&gt;
  {
      let key = name.into();
      let record = {
          map.entry(key.clone()).or_insert(Record::new(key))
      };
      Handle::new(record, map)
  }
  </code></pre>
  
  <p>But the error remains.</p>
  
  <p>It is very strange that the mutable borrow remain even after the scope has finished. According to <a href="http://doc.rust-lang.org/book/references-and-borrowing.html" rel="nofollow noreferrer">References and Borrowing</a> the borrow should end at the end of the scope, and according to <a href="http://rustbyexample.com/variable_bindings/scope.html" rel="nofollow noreferrer">Scope and shadowing</a> scopes are controlled by blocks, which are collections of statements enclosed in braces, so superficially, it appears that the later function definition should end the scope with the mutable borrow of the reference to the map.</p>
  
  <p>How do you implement a <code>Handle</code> like this in reasonable way so that the lifetime of <code>Handle</code> does not exceed that of the <code>HashMap</code> and capture this at compile time? I'm looking at a good way to create a <code>Handle</code> that</p>
  
  <ul>
  <li><p>Abstract away the access to the underlying storage by using the temporary <code>Handle</code> as the abstraction provided by the implementation.</p></li>
  <li><p>Capture misuses at compile time rather than runtime, which disqualifies <code>RefCell</code> and <code>Rc</code>.</p></li>
  <li><p>Perform a single lookup in the underlying structure.</p></li>
  </ul>
  
  <p>I looked at <code>RefCell</code> but that moves the checks from compile time to runtime, and it would be beneficial to be able to catch misuses of <code>Handle</code> at compile time.</p>
  
  <p>The question in <a href="https://stackoverflow.com/questions/25190063/rust-borrowing-issues-with-attempted-caching">Rust: Borrowing issues with attempted caching</a> is similar to this one but the answer is using <code>UnsafeCell</code>, which work around the checks rather than solve them.</p>
  
  <p>To me the problem seems to be that there need to be a way to transform a mutable reference to a immutable reference and release the mutable borrow (with the restriction that it should be permitted by the code), but still not sure if I have misunderstood something.</p>
  
  <p><strong>Update:</strong> There were originally three bullets for this question in an attempt to make it more structured, but it's been rewritten to just pose a single question to make it clear what the goal is.</p>