title: Why are generic and non-generic structs treated differently when building expression that lifts operator == to nullable?
body: <p>This looks like a bug in lifting to null of operands on generic structs.</p>
  
  <p>Consider the following dummy struct, that overrides <code>operator==</code>:</p>
  
  <pre class="lang-cs prettyprint-override"><code>struct MyStruct
  {
      private readonly int _value;
      public MyStruct(int val) { this._value = val; }
  
      public override bool Equals(object obj) { return false; }
      public override int GetHashCode() { return base.GetHashCode(); }
  
      public static bool operator ==(MyStruct a, MyStruct b) { return false; }
      public static bool operator !=(MyStruct a, MyStruct b) { return false; }
  }
  </code></pre>
  
  <p>Now consider the following expressions:</p>
  
  <pre class="lang-cs prettyprint-override"><code>Expression&lt;Func&lt;MyStruct, MyStruct, bool&gt;&gt; exprA   = 
      (valueA, valueB) =&gt; valueA == valueB;
  
  Expression&lt;Func&lt;MyStruct?, MyStruct?, bool&gt;&gt; exprB = 
      (nullableValueA, nullableValueB) =&gt; nullableValueA == nullableValueB;
  
  Expression&lt;Func&lt;MyStruct?, MyStruct, bool&gt;&gt; exprC  = 
      (nullableValueA, valueB) =&gt; nullableValueA == valueB;
  </code></pre>
  
  <p>All three compile and run as expected. </p>
  
  <p>When they're compiled (using <code>.Compile()</code>) they produce the following code (paraphrased to English from the IL):</p>
  
  <ol>
  <li><p>The first expression that takes only <code>MyStruct</code> (not nullable) args, simply calls <code>op_Equality</code> (our implementation of <code>operator ==</code>)</p></li>
  <li><p>The second expression, when compiled, produces code that checks each argument to see if it <code>HasValue</code>. If both don't (both equal <code>null</code>), returns <code>true</code>. If only one has a value, returns <code>false</code>. Otherwise, calls <code>op_Equality</code> on the two values.</p></li>
  <li><p>The third expression checks the nullable argument to see if it has a value - if not, returns false. Otherwise, calls <code>op_Equality</code>. </p></li>
  </ol>
  
  <p>So far so good.</p>
  
  <p>Next step: do the exact same thing with a generic type - change <code>MyStruct</code> to <code>MyStruct&lt;T&gt;</code> everywhere in the definition of the type, and change it to <code>MyStruct&lt;int&gt;</code> in the expressions.</p>
  
  <p>Now the third expression compiles but throws a runtime exception <code>InvalidOperationException</code> with the following message:</p>
  
  <blockquote>
    <p>The operands for operator 'Equal' do not match the parameters of method 'op_Equality'.</p>
  </blockquote>
  
  <p>I would expect generic structs to behave exactly the same as non-generic ones, with all the nullable-lifting described above.</p>
  
  <p>So my questions are:</p>
  
  <ol>
  <li>Why is there a difference between generic and non-generic structs?</li>
  <li>What is the meaning of this exception?</li>
  <li>Is this a bug in C#/.NET?</li>
  </ol>
  
  <hr>
  
  <p>The full code for reproducing this is <a href="https://gist.github.com/anonymous/5664417" rel="nofollow noreferrer">available on this gist</a>.</p>