title: Why is a Cell used to create unmovable objects?
body: <p>So I ran into <a href="https://gist.github.com/Kimundi/d846f1da490ef4e9b0d9">this code snippet</a> showing how to create "unmoveable" types in Rust - moves are prevented because the compiler treats the object as borrowed for its whole lifetime.</p>
  
  <pre><code>use std::cell::Cell;
  use std::marker;
  
  struct Unmovable&lt;'a&gt; {
      lock: Cell&lt;marker::ContravariantLifetime&lt;'a&gt;&gt;,
      marker: marker::NoCopy
  }
  
  impl&lt;'a&gt; Unmovable&lt;'a&gt; {
      fn new() -&gt; Unmovable&lt;'a&gt; {
          Unmovable { 
              lock: Cell::new(marker::ContravariantLifetime),
              marker: marker::NoCopy
          }
      }
      fn lock(&amp;'a self) {
          self.lock.set(marker::ContravariantLifetime);
      }
      fn new_in(self_: &amp;'a mut Option&lt;Unmovable&lt;'a&gt;&gt;) {
          *self_ = Some(Unmovable::new());
          self_.as_ref().unwrap().lock();
      }
  }
  
  fn main(){
      let x = Unmovable::new();
      x.lock();
  
      // error: cannot move out of `x` because it is borrowed
      // let z = x; 
  
      let mut y = None;
      Unmovable::new_in(&amp;mut y);
  
      // error: cannot move out of `y` because it is borrowed
      // let z = y; 
  
      assert_eq!(std::mem::size_of::&lt;Unmovable&gt;(), 0)
  }
  </code></pre>
  
  <p>I don't yet understand how this works. My guess is that the lifetime of the borrow-pointer argument is forced to match the lifetime of the lock field. The weird thing is, this code continues working in the same way if:</p>
  
  <ul>
  <li>I change <code>ContravariantLifetime&lt;'a&gt;</code> to <code>CovariantLifetime&lt;'a&gt;</code>, or to <code>InvariantLifetime&lt;'a&gt;</code>.</li>
  <li>I remove the body of the <code>lock</code> method.</li>
  </ul>
  
  <p>But, if I remove the <code>Cell</code>, and just use <code>lock: marker::ContravariantLifetime&lt;'a&gt;</code> directly, as so:</p>
  
  <pre><code>use std::marker;
  
  struct Unmovable&lt;'a&gt; {
      lock: marker::ContravariantLifetime&lt;'a&gt;,
      marker: marker::NoCopy
  }
  
  impl&lt;'a&gt; Unmovable&lt;'a&gt; {
      fn new() -&gt; Unmovable&lt;'a&gt; {
          Unmovable { 
              lock: marker::ContravariantLifetime,
              marker: marker::NoCopy
          }
      }
      fn lock(&amp;'a self) {
      }
      fn new_in(self_: &amp;'a mut Option&lt;Unmovable&lt;'a&gt;&gt;) {
          *self_ = Some(Unmovable::new());
          self_.as_ref().unwrap().lock();
      }
  }
  
  fn main(){
      let x = Unmovable::new();
      x.lock();
  
      // does not error?
      let z = x;
  
      let mut y = None;
      Unmovable::new_in(&amp;mut y);
  
      // does not error?
      let z = y;
  
      assert_eq!(std::mem::size_of::&lt;Unmovable&gt;(), 0)
  }
  </code></pre>
  
  <p>Then the "Unmoveable" object is allowed to move. Why would that be?</p>