Browse Source

TransformExpressionTrees: inline MatchConstantCall into ConvertConstant

ConvertConstant is its only caller, and with the result type gone the
out parameter that reconstructed it - a switch over LdNull/LdStr/Ldc* -
has no consumer. What remains is a match condition: the two-argument
Expression.Constant overload must pass its type as typeof(T), while the
one-argument overload legacy csc emits for display-class instances has
nothing to check.

Assisted-by: Claude:claude-opus-5[1m]:Claude Code
pull/4091/head
Siegfried Pammer 2 weeks ago committed by Daniel Grunwald
parent
commit
49b7257e9c
  1. 38
      ICSharpCode.Decompiler/IL/Transforms/TransformExpressionTrees.cs

38
ICSharpCode.Decompiler/IL/Transforms/TransformExpressionTrees.cs

@ -888,7 +888,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -888,7 +888,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
Func<ILInstruction> ConvertConstant(CallInstruction invocation)
{
if (!MatchConstantCall(invocation, out var value, out var type))
if (!MatchConstantCall(invocation, out var value))
return null;
if (value.MatchBox(out var arg, out var boxType))
{
@ -897,6 +897,19 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -897,6 +897,19 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return () => ConvertValue(arg, invocation);
}
return () => ConvertValue(value, invocation);
static bool MatchConstantCall(ILInstruction inst, out ILInstruction value)
{
value = null;
if (inst is CallInstruction call && call.Method.FullName == "System.Linq.Expressions.Expression.Constant")
{
value = call.Arguments[0];
// The two-argument overload passes the constant's type as typeof(T);
// legacy csc uses the one-argument overload for display-class instances.
return call.Arguments.Count != 2 || MatchGetTypeFromHandle(call.Arguments[1], out _);
}
return false;
}
}
Func<ILInstruction> ConvertElementInit(CallInstruction invocation)
@ -1512,29 +1525,6 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -1512,29 +1525,6 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return variable.Type.FullName == "System.Linq.Expressions.ParameterExpression";
}
bool MatchConstantCall(ILInstruction inst, out ILInstruction value, out IType type)
{
value = null;
type = null;
if (inst is CallInstruction call && call.Method.FullName == "System.Linq.Expressions.Expression.Constant")
{
value = call.Arguments[0];
if (call.Arguments.Count == 2)
return MatchGetTypeFromHandle(call.Arguments[1], out type);
type = value switch {
LdNull => SpecialType.NullType,
LdStr => context.TypeSystem.FindType(KnownTypeCode.String),
LdcF4 => context.TypeSystem.FindType(KnownTypeCode.Single),
LdcF8 => context.TypeSystem.FindType(KnownTypeCode.Double),
LdcI4 => context.TypeSystem.FindType(KnownTypeCode.Int32),
LdcI8 => context.TypeSystem.FindType(KnownTypeCode.Int64),
_ => value.InferType(context.TypeSystem),
};
return true;
}
return false;
}
internal static bool MatchGetTypeFromHandle(ILInstruction inst, out IType type)
{
type = null;

Loading…
Cancel
Save