From 9947ad528ae7f55313daf2139b906872bfc4a75a Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Sat, 5 Sep 2026 11:51:51 +0200 Subject: [PATCH] TransformExpressionTrees: compare operand stack types, not operand types A conversion of a small integer type to Int32 returns its operand unchanged, because such values already occupy an I4 stack slot. The two operands of `(short a, int b) => a + b` are therefore Int16 and Int32, and requiring them to be equal rejected the conversion; the whole expression tree was then left untransformed, or worse, aborted the enclosing method. What BinaryNumericInstruction requires of its operands is a common stack type. TryConvertExpressionTree also has to cope with a builder that fails, rather than dereferencing the lambda it did not get. Assisted-by: Claude:claude-opus-5[1m]:Claude Code --- .../IL/Transforms/TransformExpressionTrees.cs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/ICSharpCode.Decompiler/IL/Transforms/TransformExpressionTrees.cs b/ICSharpCode.Decompiler/IL/Transforms/TransformExpressionTrees.cs index f6b608b3d..1f9916e07 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/TransformExpressionTrees.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/TransformExpressionTrees.cs @@ -172,6 +172,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms { context.Step("Convert Expression Tree", instruction); var newLambda = (ILFunction)lambda(); + if (newLambda == null) + return false; SetExpressionTreeFlag(newLambda, (CallInstruction)instruction); instruction.ReplaceWith(newLambda); context.EndStep(newLambda); @@ -642,8 +644,15 @@ namespace ICSharpCode.Decompiler.IL.Transforms } else { - if (!rightType.Equals(leftType)) + // Compare the stack types rather than the types themselves: a conversion + // of a small integer type to Int32 leaves its operand unchanged, because + // such values already occupy an I4 stack slot, so the two sides of + // `(short a, int b) => a + b` are Int16 and Int32 at this point. + if (NullableType.GetUnderlyingType(rightType).GetStackType() + != NullableType.GetUnderlyingType(leftType).GetStackType()) + { return null; + } } if (leftType.IsKnownType(KnownTypeCode.Decimal)) {