title: Why can the Rust compiler not optimize Option::take and an "if let" if you print the value?
body: <p>I bumped into the following observation:</p>
  
  <pre><code>pub fn xx(mut x: Option&lt;usize&gt;) -&gt; usize {
      let y = x.take();
      //print!("{:?}", x);
      if let Some(x) = x {
          x
      } else {
          0
      }
  }
  </code></pre>
  
  <p>This code (with <code>print!</code> being commented out) gets optimized to "nothing":</p>
  
  <pre><code>xorl    %eax, %eax
  retq
  </code></pre>
  
  <p>Once I uncomment the <code>print!</code>, it can no longer optimize out the <code>if let Some(x) = x</code> anymore. I went ahead and expanded the macro (using <code>rustc +nightly --pretty=expanded -Z unstable-options main.rs</code>) and stripped minimized the code down to a minimal compilable example:</p>
  
  <pre><code>#![feature(print_internals)]
  #![feature(fmt_internals)]
  
  pub fn xx(mut x: Option&lt;usize&gt;) -&gt; usize {
      let y = x.take();
  
      std::io::_print(
          ::std::fmt::Arguments::new_v1_formatted(
              &amp;[""],
              &amp;[::std::fmt::ArgumentV1::new(&amp;x, ::std::fmt::Debug::fmt)],
              &amp;[]
          )
      );
  
      if let Some(x) = x {
          x
      } else {
          0
      }
  }
  </code></pre>
  
  <p>As far as I can see, we only reference <code>x</code> once, and it is a non-mutable reference, so nothing should prevent the optimizer from assuming it is <code>None</code> (since we <code>take()</code> it) and just constantly return <code>0</code> as in the first snippet.</p>
  
  <p><a href="https://godbolt.org/g/P6Tk38" rel="nofollow noreferrer">Here are the snippets in the Compiler Explorer</a></p>