+ /*struct SlotFromNullableToNullable {
+ public int Value;
+
+ public SlotFromNullableToNullable (int value)
+ {
+ this.Value = value;
+ }
+
+ public override bool Equals (object obj)
+ {
+ if (!(obj is SlotFromNullableToNullable))
+ return false;
+
+ var other = (SlotFromNullableToNullable) obj;
+ return other.Value == this.Value;
+ }
+
+ public override int GetHashCode ()
+ {
+ return Value;
+ }
+
+ public static bool? operator == (SlotFromNullableToNullable? a, SlotFromNullableToNullable? b)
+ {
+ if (a.HasValue && b.HasValue)
+ return (bool?) (a.Value.Value == b.Value.Value);
+ else
+ return null;
+ }
+
+ public static bool? operator != (SlotFromNullableToNullable? a, SlotFromNullableToNullable? b)
+ {
+ return !(a == b);
+ }
+ }
+
+ [Test]
+ public void UserDefinedFromNullableToNullableEqual ()
+ {
+ var l = Expression.Parameter (typeof (SlotFromNullableToNullable?), "l");
+ var r = Expression.Parameter (typeof (SlotFromNullableToNullable?), "r");
+
+ var node = Expression.Equal (l, r);
+
+ Assert.IsFalse (node.IsLifted);
+ Assert.IsFalse (node.IsLiftedToNull);
+ Assert.AreEqual (typeof (bool?), node.Type);
+ Assert.IsNotNull (node.Method);
+
+ var eq = Expression.Lambda<Func<SlotFromNullableToNullable?, SlotFromNullableToNullable?, bool?>> (node, l, r).Compile ();
+
+ Assert.AreEqual ((bool?) null, eq (null, null));
+ Assert.AreEqual ((bool?) null, eq (new SlotFromNullableToNullable (2), null));
+ Assert.AreEqual ((bool?) null, eq (null, new SlotFromNullableToNullable (2)));
+ Assert.AreEqual ((bool?) true, eq (new SlotFromNullableToNullable (2), new SlotFromNullableToNullable (2)));
+ Assert.AreEqual ((bool?) false, eq (new SlotFromNullableToNullable (2), new SlotFromNullableToNullable (-2)));
+ }*/
+
+ [Test]
+ public void NullableBoolEqualToBool ()
+ {
+ var l = Expression.Parameter (typeof (bool?), "l");
+ var r = Expression.Parameter (typeof (bool?), "r");
+
+ var node = Expression.Equal (l, r);
+ Assert.IsTrue (node.IsLifted);
+ Assert.IsFalse (node.IsLiftedToNull);
+ Assert.AreEqual (typeof (bool), node.Type);
+ Assert.IsNull (node.Method);
+
+ var eq = Expression.Lambda<Func<bool?, bool?, bool>> (node, l, r).Compile ();
+
+ Assert.AreEqual (false, eq (true, null));
+ Assert.AreEqual (true, eq (null, null));
+ Assert.AreEqual (true, eq (false, false));
+ }
+
+ public enum Foo {
+ Bar,
+ Baz,
+ }
+
+ [Test]
+ public void EnumEqual ()
+ {
+ var l = Expression.Parameter (typeof (Foo), "l");
+ var r = Expression.Parameter (typeof (Foo), "r");
+
+ var node = Expression.Equal (l, r);
+ Assert.IsFalse (node.IsLifted);
+ Assert.IsFalse (node.IsLiftedToNull);
+ Assert.AreEqual (typeof (bool), node.Type);
+ Assert.IsNull (node.Method);
+
+ var eq = Expression.Lambda<Func<Foo, Foo, bool>> (node, l, r).Compile ();
+
+ Assert.AreEqual (true, eq (Foo.Bar, Foo.Bar));
+ Assert.AreEqual (false, eq (Foo.Bar, Foo.Baz));
+ }
+
+ [Test]
+ public void LiftedEnumEqual ()
+ {
+ var l = Expression.Parameter (typeof (Foo?), "l");
+ var r = Expression.Parameter (typeof (Foo?), "r");
+
+ var node = Expression.Equal (l, r);
+ Assert.IsTrue (node.IsLifted);
+ Assert.IsFalse (node.IsLiftedToNull);
+ Assert.AreEqual (typeof (bool), node.Type);
+ Assert.IsNull (node.Method);
+
+ var eq = Expression.Lambda<Func<Foo?, Foo?, bool>> (node, l, r).Compile ();
+
+ Assert.AreEqual (true, eq (Foo.Bar, Foo.Bar));
+ Assert.AreEqual (false, eq (Foo.Bar, Foo.Baz));
+ Assert.AreEqual (false, eq (Foo.Bar, null));
+ Assert.AreEqual (true, eq (null, null));
+ }
+
+ [Test]
+ [Category ("NotWorkingInterpreter")]
+ public void NullableNullEqual ()
+ {
+ var param = Expression.Parameter (typeof (DateTime?), "x");
+
+ var node = Expression.Equal (param, Expression.Constant (null));
+
+ Assert.IsTrue (node.IsLifted);
+ Assert.IsFalse (node.IsLiftedToNull);
+ Assert.AreEqual (typeof (bool), node.Type);
+ Assert.IsNull (node.Method);
+
+ var eq = Expression.Lambda<Func<DateTime?, bool>> (node, new [] { param }).Compile ();
+
+ Assert.AreEqual (true, eq (null));
+ Assert.AreEqual (false, eq (DateTime.Now));
+ }