title: Destructuring a struct containing a borrow in a function argument
body: <p>I am trying to implement a system that would use borrow checking/lifetimes in order to provide safe custom indices on a collection. Consider the following code:</p>
  
  <pre><code>struct Graph(i32);
  
  struct Edge&lt;'a&gt;(&amp;'a Graph, i32);
  
  impl Graph {
      pub fn get_edge(&amp;self) -&gt; Edge {
          Edge(&amp;self, 0)
      }
  
      pub fn split(&amp;mut self, Edge(_, edge_id): Edge) {
          self.0 = self.0 + edge_id;
      }
  
      pub fn join(&amp;mut self, Edge(_, edge0_id): Edge, Edge(_, edge1_id): Edge) {
          self.0 = self.0 + edge0_id + edge1_id;
      }
  }
  
  
  fn main() {
      let mut graph = Graph(0);
      let edge = graph.get_edge();
      graph.split(edge)
  }
  </code></pre>
  
  <p>References to the graph borrowed by the <code>Edge</code> struct should be dropped when methods such as <code>split</code> or <code>join</code> are called. This would fulfill the API invariant that all edge indices must be destroyed when the graph is mutated. However, the compiler doesn't get it. It fails with messages like</p>
  
  <pre class="lang-none prettyprint-override"><code>error[E0502]: cannot borrow `graph` as mutable because it is also borrowed as immutable
    --&gt; src/main.rs:23:5
     |
  22 |     let edge = graph.get_edge();
     |                ----- immutable borrow occurs here
  23 |     graph.split(edge)
     |     ^^^^^ mutable borrow occurs here
  24 | }
     | - immutable borrow ends here
  </code></pre>
  
  <p>If I understand this correctly, the compiler fails to realise that the borrowing of the graph that happened in the edge struct is actually being released when the function is called. Is there a way to teach the compiler what I am trying to do here?</p>
  
  <p>Bonus question: is there a way to do exactly the same but without actually borrowing the graph in the <code>Edge</code> struct? The edge struct is only used as a temporary for the purpose of traversal and will <em>never</em> be part of an external object state (I have 'weak' versions of the edge for that).   </p>
  
  <p><strong>Addendum</strong>: After some digging around, it seems to be really far from trivial. First of all, <code>Edge(_, edge_id)</code> does not actually destructure the <code>Edge</code>, because <code>_</code> does not get bound at all (yes, <code>i32</code> is Copy which makes things even more complicated, but this is easily remedied by wrapping it into a non-Copy struct). Second, even if I completely destructure <code>Edge</code> (i.e. by doing it in a separate scope), the reference to the graph is still there, even though it should have been moved (this must be a bug). It only works if I perform the destructuring in a separate function. Now, I have an idea how to circumvent it (by having a separate object that describes a state change and destructures the indices as they are supplied), but this becomes very awkward very quickly. </p>