diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/ExpressionTrees.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/ExpressionTrees.cs index bcf20b512e..525743cd4b 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/ExpressionTrees.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/ExpressionTrees.cs @@ -894,6 +894,12 @@ public void NullCoalescing() Test>((string a, string b) => a ?? b, (string a, string b) => a ?? b); Test>((int? a) => a ?? 1, (int? a) => a ?? 1); } + + public void NullableLifting(Guid? a, Guid? b) + { + ToCode(null, () => a == b); + ToCode(null, () => (Guid)a == (Guid)b); + } } internal static class Extensions diff --git a/ICSharpCode.Decompiler/IL/Transforms/TransformExpressionTrees.cs b/ICSharpCode.Decompiler/IL/Transforms/TransformExpressionTrees.cs index f50e000268..29d4b2f392 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/TransformExpressionTrees.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/TransformExpressionTrees.cs @@ -515,15 +515,16 @@ ILInstruction Convert() Arguments = { left(), right() } }, method.ReturnType); case 4: - if (!invocation.Arguments[2].MatchLdcI4(out var isLifted)) + if (!invocation.Arguments[2].MatchLdcI4(out var isLiftedToNull)) return (null, SpecialType.UnknownType); if (!MatchGetMethodFromHandle(invocation.Arguments[3], out method)) return (null, SpecialType.UnknownType); - if (isLifted != 0) + bool isLifted = NullableType.IsNullable(leftType); + if (isLifted) method = CSharpOperators.LiftUserDefinedOperator((IMethod)method); return (() => new Call((IMethod)method) { Arguments = { left(), right() } - }, method.ReturnType); + }, isLiftedToNull != 0 ? NullableType.Create(method.Compilation, method.ReturnType) : method.ReturnType); default: return (null, SpecialType.UnknownType); } @@ -729,13 +730,12 @@ Func[] ConvertCallArguments(IList arguments, IMeth var (right, rightType) = ConvertInstruction(invocation.Arguments[1]); if (right == null) return (null, SpecialType.UnknownType); - if (invocation.Arguments.Count == 4 && invocation.Arguments[2].MatchLdcI4(out var isLifted) && MatchGetMethodFromHandle(invocation.Arguments[3], out var method)) + if (invocation.Arguments.Count == 4 && invocation.Arguments[2].MatchLdcI4(out var isLiftedToNull) && MatchGetMethodFromHandle(invocation.Arguments[3], out var method)) { - if (isLifted != 0) - { + bool isLifted = NullableType.IsNullable(leftType); + if (isLifted) method = CSharpOperators.LiftUserDefinedOperator((IMethod)method); - } - return (() => new Call((IMethod)method) { Arguments = { left(), right() } }, method.ReturnType); + return (() => new Call((IMethod)method) { Arguments = { left(), right() } }, isLiftedToNull != 0 ? NullableType.Create(method.Compilation, method.ReturnType) : method.ReturnType); } var rr = resolver.ResolveBinaryOperator(kind.ToBinaryOperatorType(), new ResolveResult(leftType), new ResolveResult(rightType)) as OperatorResolveResult; if (rr != null && !rr.IsError && rr.UserDefinedOperatorMethod != null) @@ -979,15 +979,16 @@ Block BuildBlock() Arguments = { left(), right() } }, method.ReturnType); case 4: - if (!invocation.Arguments[2].MatchLdcI4(out var isLifted)) + if (!invocation.Arguments[2].MatchLdcI4(out var isLiftedToNull)) return (null, SpecialType.UnknownType); if (!MatchGetMethodFromHandle(invocation.Arguments[3], out method)) return (null, SpecialType.UnknownType); - if (isLifted != 0) + bool isLifted = NullableType.IsNullable(leftType); + if (isLifted) method = CSharpOperators.LiftUserDefinedOperator((IMethod)method); return (() => new Call((IMethod)method) { Arguments = { left(), right() } - }, method.ReturnType); + }, isLiftedToNull != 0 ? NullableType.Create(method.Compilation, method.ReturnType) : method.ReturnType); default: return (null, SpecialType.UnknownType); }