Browse Source

Fix #1759: Substitute display-class type parameters with method type parameters in TransformDisplayClassUsage.

pull/1790/head
Siegfried Pammer 6 years ago
parent
commit
6330be36b3
  1. 34
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/DelegateConstruction.cs
  2. 19
      ICSharpCode.Decompiler/IL/Transforms/TransformDisplayClassUsage.cs

34
ICSharpCode.Decompiler.Tests/TestCases/Pretty/DelegateConstruction.cs

@ -151,6 +151,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{
void M3();
}
public class BaseClass : IM3
{
protected virtual void M1()
@ -163,6 +164,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{
}
}
public class SubClass : BaseClass
{
protected override void M2()
@ -193,6 +195,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
Noop("M3", M3);
#endif
}
public void Test2()
{
Noop("M3.new", new BaseClass().M3);
@ -204,6 +207,28 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
}
}
public class GenericTest<TNonCaptured, TCaptured>
{
public Func<TCaptured> GetFunc(Func<TNonCaptured, TCaptured> f)
{
TCaptured captured = f(default(TNonCaptured));
return delegate {
Console.WriteLine(captured.GetType().FullName);
return captured;
};
}
public Func<TNonCaptured, TNonCapturedMP, TCaptured> GetFunc<TNonCapturedMP>(Func<TCaptured> f)
{
TCaptured captured = f();
return delegate(TNonCaptured a, TNonCapturedMP d) {
Console.WriteLine(a.GetHashCode());
Console.WriteLine(captured.GetType().FullName);
return captured;
};
}
}
public static Func<string, string, bool> test0 = (string a, string b) => string.IsNullOrEmpty(a) || string.IsNullOrEmpty(b);
public static Func<string, string, bool> test1 = (string a, string b) => string.IsNullOrEmpty(a) || !string.IsNullOrEmpty(b);
public static Func<string, string, bool> test2 = (string a, string b) => !string.IsNullOrEmpty(a) || string.IsNullOrEmpty(b);
@ -342,5 +367,14 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{
return (int b) => (int c) => (int d) => a + b + c + d;
}
public static Func<TCaptured> CapturedTypeParameter1<TNonCaptured, TCaptured>(TNonCaptured a, Func<TNonCaptured, TCaptured> f)
{
TCaptured captured = f(a);
return delegate {
Console.WriteLine(captured.GetType().FullName);
return captured;
};
}
}
}

19
ICSharpCode.Decompiler/IL/Transforms/TransformDisplayClassUsage.cs

@ -321,7 +321,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
if (displayClass.IsMono && displayClass.CaptureScope == null && !IsOuterClosureReference(field)) {
displayClass.CaptureScope = BlockContainer.FindClosestContainer(inst);
}
v = displayClass.DeclaringFunction.RegisterVariable(VariableKind.Local, field.Type, field.Name);
v = displayClass.DeclaringFunction.RegisterVariable(VariableKind.Local, GetVariableTypeFromClosureField(field), field.Name);
v.HasInitialValue = true;
v.CaptureScope = displayClass.CaptureScope;
inst.ReplaceWith(new StLoc(v, inst.Value).WithILRange(inst));
@ -370,7 +370,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
context.Step($"Introduce captured variable for {field.FullName}", inst);
// Introduce a fresh variable for the display class field.
Debug.Assert(displayClass.Definition == field.DeclaringTypeDefinition);
var v = displayClass.DeclaringFunction.RegisterVariable(VariableKind.Local, field.Type, field.Name);
var v = displayClass.DeclaringFunction.RegisterVariable(VariableKind.Local, GetVariableTypeFromClosureField(field), field.Name);
v.HasInitialValue = true;
v.CaptureScope = displayClass.CaptureScope;
inst.ReplaceWith(new LdLoca(v).WithILRange(inst));
@ -381,5 +381,20 @@ namespace ICSharpCode.Decompiler.IL.Transforms
Debug.Fail("LdFlda pattern not supported!");
}
}
private IType GetVariableTypeFromClosureField(IField field)
{
if (!(field.Type is ITypeParameter typeParameter))
return field.Type;
var rootMethod = context.Function.Method;
if (typeParameter.Owner != field.DeclaringTypeDefinition)
return field.Type;
if (typeParameter.Index >= rootMethod.TypeParameters.Count) {
Debug.Assert(false, "Cannot map display-class type parameter to method type parameter");
return field.Type;
}
return rootMethod.TypeParameters[typeParameter.Index];
}
}
}
Loading…
Cancel
Save