Browse Source

#918: CallBuilder: Add fix-up logic for lambda expressions with anonymous parameter types to ensure the correct overload is called after removing the 'implicit' call to 'new Nullable<T>(T value)'.

pull/946/head
Siegfried Pammer 8 years ago
parent
commit
818a90af95
  1. 38
      ICSharpCode.Decompiler/CSharp/CallBuilder.cs
  2. 2
      ICSharpCode.Decompiler/CSharp/Resolver/LambdaResolveResult.cs

38
ICSharpCode.Decompiler/CSharp/CallBuilder.cs

@ -143,10 +143,16 @@ namespace ICSharpCode.Decompiler.CSharp @@ -143,10 +143,16 @@ namespace ICSharpCode.Decompiler.CSharp
.WithILInstruction(inst)
.WithRR(rr);
} else {
if (IsUnambiguousCall(inst, target, method, Array.Empty<IType>(), arguments) != OverloadResolutionErrors.None) {
for (int i = 0; i < arguments.Count; i++) {
if (!settings.AnonymousTypes || !expectedParameters[i].Type.ContainsAnonymousType())
if (settings.AnonymousTypes && expectedParameters[i].Type.ContainsAnonymousType()) {
if (arguments[i].Expression is LambdaExpression lambda) {
ModifyReturnTypeOfLambda(lambda);
}
} else {
arguments[i] = arguments[i].ConvertTo(expectedParameters[i].Type, expressionBuilder);
}
}
}
return new ObjectCreateExpression(expressionBuilder.ConvertType(inst.Method.DeclaringType), arguments.SelectArray(arg => arg.Expression))
@ -180,8 +186,13 @@ namespace ICSharpCode.Decompiler.CSharp @@ -180,8 +186,13 @@ namespace ICSharpCode.Decompiler.CSharp
if (!argumentsCasted) {
argumentsCasted = true;
for (int i = 0; i < arguments.Count; i++) {
if (!settings.AnonymousTypes || !expectedParameters[i].Type.ContainsAnonymousType())
if (settings.AnonymousTypes && expectedParameters[i].Type.ContainsAnonymousType()) {
if (arguments[i].Expression is LambdaExpression lambda) {
ModifyReturnTypeOfLambda(lambda);
}
} else {
arguments[i] = arguments[i].ConvertTo(expectedParameters[i].Type, expressionBuilder);
}
}
} else if (!targetCasted) {
targetCasted = true;
@ -213,6 +224,29 @@ namespace ICSharpCode.Decompiler.CSharp @@ -213,6 +224,29 @@ namespace ICSharpCode.Decompiler.CSharp
}
}
private void ModifyReturnTypeOfLambda(LambdaExpression lambda)
{
var resolveResult = (DecompiledLambdaResolveResult)lambda.GetResolveResult();
if (lambda.Body is Expression exprBody)
lambda.Body = new TranslatedExpression(exprBody.Detach()).ConvertTo(resolveResult.ReturnType, expressionBuilder);
else
ModifyReturnStatementInsideLambda(resolveResult.ReturnType, lambda);
resolveResult.InferredReturnType = resolveResult.ReturnType;
}
private void ModifyReturnStatementInsideLambda(IType returnType, AstNode parent)
{
foreach (var child in parent.Children) {
if (child is LambdaExpression || child is AnonymousMethodExpression)
continue;
if (child is ReturnStatement ret) {
ret.Expression = new TranslatedExpression(ret.Expression.Detach()).ConvertTo(returnType, expressionBuilder);
continue;
}
ModifyReturnStatementInsideLambda(returnType, child);
}
}
private bool IsDelegateEqualityComparison(IMethod method, IList<TranslatedExpression> arguments)
{
// Comparison on a delegate type is a C# builtin operator

2
ICSharpCode.Decompiler/CSharp/Resolver/LambdaResolveResult.cs

@ -109,7 +109,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver @@ -109,7 +109,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
/// Can differ from <c>ReturnType</c> if a return statement
/// performs an implicit conversion.
/// </summary>
public readonly IType InferredReturnType;
public IType InferredReturnType;
public DecompiledLambdaResolveResult(IL.ILFunction function,
IType delegateType,

Loading…
Cancel
Save