title: "use of moved value" when matching while merging two vectors
body: <p>I am writing a merge function for vectors of tags with counts, but am getting borrowing errors.</p>
  
  <pre><code>fn merge(mut l1: Vec&lt;(String, u32)&gt;, mut l2: Vec&lt;(String, u32)&gt;) -&gt; Vec&lt;(String, u32)&gt; {
      let mut d1 = l1.drain(..);
      let mut d2 = l2.drain(..);
      let mut result = Vec::new();
      let mut v1 = d1.next();
      let mut v2 = d2.next();
      loop {
          match (v1, v2) {
              (None, None) =&gt; return result,
              (None, Some(x)) =&gt; {
                  result.push(x.clone());
                  v2 = d2.next()
              }
              (Some(x), None) =&gt; {
                  result.push(x.clone());
                  v1 = d1.next()
              }
              (Some(p1), Some(p2)) =&gt; {
                  let (ref s1, t1) = p1;
                  let (ref s2, t2) = p2;
                  if s1 == s2 {
                      result.push((s1.clone(), t1 + t2));
                      v1 = d1.next();
                      v2 = d2.next();
                  } else if s1 &lt; s2 {
                      result.push(p1.clone());
                      v1 = d1.next();
                  } else {
                      result.push(p2.clone());
                      v2 = d2.next();
                  }
              }
          }
      }
  }
  </code></pre>
  
  <p>gives the error:</p>
  
  <pre><code>error: use of moved value: `v1` [E0382]
           match (v1,v2) {
                  ^~
  help: run `rustc --explain E0382` to see a detailed explanation
  note: `v1` was previously moved here because it has type `core::option::Option&lt;(collections::string::String, u32)&gt;`, which is non-copyable
  </code></pre>
  
  <p>and a similar error for <code>v2</code>.  It usually shows the problem location and the previous move that causes the problem, but not here.</p>
  
  <p>I've tried many permutations, and with the following change I've gotten it to compile, but I'm not happy about all the cloning and recreating tuples and recreating <code>Option</code>s.</p>
  
  <pre><code>match (v1, v2) {
      (None, None) =&gt; return result,
      (None, Some(x)) =&gt; {
          result.push(x.clone());
          v1 = None;
          v2 = d2.next();
      }
      (Some(x), None) =&gt; {
          result.push(x.clone());
          v1 = d1.next();
          v2 = None;
      }
      (Some(p1), Some(p2)) =&gt; {
          let (ref s1, t1) = p1;
          let (ref s2, t2) = p2;
          if s1 == s2 {
              result.push((s1.clone(), t1 + t2));
              v1 = d1.next();
              v2 = d2.next();
          } else if s1 &lt; s2 {
              result.push(p1.clone());
              v1 = d1.next();
              v2 = Some((s2.clone(), t2));
          } else {
              result.push(p2.clone());
              v1 = Some((s1.clone(), t1));
              v2 = d2.next();
          }
      }
  }
  </code></pre>
  
  <p>Adding what I'd <strong>really</strong> like to write, for reference, in case someone is looking for a challenge for the borrow checker:</p>
  
  <pre><code>fn merge(mut l1: Vec&lt;(String, u32)&gt;, mut l2: Vec&lt;(String, u32)&gt;) -&gt; Vec&lt;(String, u32)&gt; {
      let mut d1 = l1.drain(..);
      let mut d2 = l2.drain(..);
      let mut result = Vec::new();
      let mut v1 = d1.next();
      let mut v2 = d2.next();
      loop {
          match (v1, v2) {
              (None, None) =&gt; return result,
              (None, Some(p2)) =&gt; {
                  result.push(p2);
                  v1 = None;
                  v2 = d2.next()
              }
              (Some(p1), None) =&gt; {
                  result.push(p1);
                  v1 = d1.next();
                  v2 = None
              }
              (Some(p1 @ (s1, _)), o2 @ Some((s2, _))) if s1 &lt; s2 =&gt; {
                  result.push(p1);
                  v1 = d1.next();
                  v2 = o2
              }
              (o1 @ Some((s1, _)), Some(p2 @ (s2, _))) if s1 &gt; s2 =&gt; {
                  result.push(p2);
                  v1 = o1;
                  v2 = d2.next()
              }
              (Some((s1, t1)), Some((_, t2))) =&gt; {
                  result.push((s1, t1 + t2));
                  v1 = d1.next();
                  v2 = d2.next()
              }
          }
      }
  }
  </code></pre>
  
  <p>Note that the match on <code>(v1, v2)</code> should move the values so that each path is enforced to set <code>v1</code> and <code>v2</code>.  Still not as clean as Haskell, but closer.</p>