The reason why the third example works is because of lifted operators. So:
For the equality operators
== !=
a lifted form of an operator exists if the operand types are both non-nullable value types and if the result type is bool. The lifted form is constructed by adding a single ? modifier to each operand type. The lifted operator considers two null values equal, and a null value unequal to any non-null value. If both operands are non-null, the lifted operator unwraps the operands and applies the underlying operator to produce the bool result.
So, that's why the third example works - because all of this machinery has been invented and it works for all nullable types.
Your second example could have been made to work but it would have required the compiler to perform special work for exactly one nullable type - bool?
. It's simply not appropriate, in general, for every use of a nullable type to perform an implicit conversion back to the original value type.
(Quote above from section 7.3.7 of the language specification)