Browse Source

Fix #1660: Generic proxy calls should use the callee's type parameter substitution, not the caller's.

pull/1686/head
Siegfried Pammer 6 years ago
parent
commit
f5185d5697
  1. 17
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/FixProxyCalls.cs
  2. 17
      ICSharpCode.Decompiler/IL/Transforms/ProxyCallReplacer.cs

17
ICSharpCode.Decompiler.Tests/TestCases/Pretty/FixProxyCalls.cs

@ -114,6 +114,23 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.ILPretty @@ -114,6 +114,23 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.ILPretty
}
}
public class Issue1660 : Issue1660Base
{
public Action<object> M(object state)
{
return delegate(object x) {
base.BaseCall(x, state, (Func<object>)(() => null));
};
}
}
public class Issue1660Base
{
protected virtual void BaseCall<T>(object x, object state, Func<T> action)
{
}
}
internal class J : I
{
protected internal override void Test(int a)

17
ICSharpCode.Decompiler/IL/Transforms/ProxyCallReplacer.cs

@ -30,13 +30,12 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -30,13 +30,12 @@ namespace ICSharpCode.Decompiler.IL.Transforms
MethodDefinition methodDef = metadata.GetMethodDefinition((MethodDefinitionHandle)inst.Method.MetadataToken);
if (!methodDef.HasBody())
return;
var genericContext = DelegateConstruction.GenericContextFromTypeArguments(inst.Method.Substitution);
if (genericContext == null)
return;
// Use the callee's generic context
var genericContext = new GenericContext(inst.Method);
// partially copied from CSharpDecompiler
var ilReader = context.CreateILReader();
var body = context.PEFile.Reader.GetMethodBody(methodDef.RelativeVirtualAddress);
var proxyFunction = ilReader.ReadIL(handle, body, genericContext.Value, ILFunctionKind.TopLevelFunction, context.CancellationToken);
var proxyFunction = ilReader.ReadIL(handle, body, genericContext, ILFunctionKind.TopLevelFunction, context.CancellationToken);
var transformContext = new ILTransformContext(context, proxyFunction);
proxyFunction.RunTransforms(CSharp.CSharpDecompiler.EarlyILTransforms(), transformContext);
if (!(proxyFunction.Body is BlockContainer blockContainer))
@ -81,8 +80,14 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -81,8 +80,14 @@ namespace ICSharpCode.Decompiler.IL.Transforms
}
}
context.Step("Replace proxy: " + inst.Method.Name + " with " + call.Method.Name, inst);
Call newInst = (Call)call.Clone();
// Apply the wrapper call's substitution to the actual method call.
Call newInst = new Call(call.Method.Specialize(inst.Method.Substitution));
// copy flags
newInst.ConstrainedTo = call.ConstrainedTo;
newInst.ILStackWasEmpty = call.ILStackWasEmpty;
newInst.IsTail = call.IsTail;
// copy IL ranges
newInst.AddILRange(call);
newInst.Arguments.ReplaceList(inst.Arguments);
inst.ReplaceWith(newInst);
}

Loading…
Cancel
Save