Browse Source

Merge branch '5.0.x' of https://github.com/icsharpcode/ILSpy

pull/1790/head
Siegfried Pammer 6 years ago
parent
commit
8470d87cb5
  1. 9
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/DelegateConstruction.cs
  2. 30
      ICSharpCode.Decompiler/IL/Transforms/TransformDisplayClassUsage.cs

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

@ -376,5 +376,14 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
return captured; return captured;
}; };
} }
public static Func<TCaptured> CapturedTypeParameter2<TNonCaptured, TCaptured>(TNonCaptured a, Func<TNonCaptured, List<TCaptured>> f)
{
List<TCaptured> captured = f(a);
return delegate {
Console.WriteLine(captured.GetType().FullName);
return captured.FirstOrDefault();
};
}
} }
} }

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

@ -278,11 +278,11 @@ namespace ICSharpCode.Decompiler.IL.Transforms
inst.Value.AcceptVisitor(this); inst.Value.AcceptVisitor(this);
if (IsParameterAssignment(inst, out var displayClass, out var field, out var parameter)) { if (IsParameterAssignment(inst, out var displayClass, out var field, out var parameter)) {
context.Step($"Detected parameter assignment {parameter.Name}", inst); context.Step($"Detected parameter assignment {parameter.Name}", inst);
displayClass.Variables.Add(field, parameter); displayClass.Variables.Add((IField)field.MemberDefinition, parameter);
instructionsToRemove.Add(inst); instructionsToRemove.Add(inst);
} else if (IsDisplayClassAssignment(inst, out displayClass, out field, out var variable)) { } else if (IsDisplayClassAssignment(inst, out displayClass, out field, out var variable)) {
context.Step($"Detected display-class assignment {variable.Name}", inst); context.Step($"Detected display-class assignment {variable.Name}", inst);
displayClass.Variables.Add(field, variable); displayClass.Variables.Add((IField)field.MemberDefinition, variable);
instructionsToRemove.Add(inst); instructionsToRemove.Add(inst);
} else { } else {
inst.Target.AcceptVisitor(this); inst.Target.AcceptVisitor(this);
@ -324,7 +324,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return false; return false;
if (!(inst.Value.MatchLdLoc(out var v) && v.Kind == VariableKind.Parameter && v.Function == currentFunction)) if (!(inst.Value.MatchLdLoc(out var v) && v.Kind == VariableKind.Parameter && v.Function == currentFunction))
return false; return false;
if (displayClass.Variables.ContainsKey(field)) if (displayClass.Variables.ContainsKey((IField)field.MemberDefinition))
return false; return false;
if (displayClassVar.Function != currentFunction) if (displayClassVar.Function != currentFunction)
return false; return false;
@ -339,7 +339,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
field = null; field = null;
if (!(inst is LdFlda ldflda)) if (!(inst is LdFlda ldflda))
return false; return false;
field = (IField)ldflda.Field.MemberDefinition; field = ldflda.Field;
return IsDisplayClassLoad(ldflda.Target, out displayClassVar) return IsDisplayClassLoad(ldflda.Target, out displayClassVar)
&& displayClasses.TryGetValue(displayClassVar, out displayClass); && displayClasses.TryGetValue(displayClassVar, out displayClass);
} }
@ -350,11 +350,16 @@ namespace ICSharpCode.Decompiler.IL.Transforms
// Get display class info // Get display class info
if (!IsDisplayClassFieldAccess(inst, out _, out DisplayClass displayClass, out IField field)) if (!IsDisplayClassFieldAccess(inst, out _, out DisplayClass displayClass, out IField field))
return; return;
// We want the specialized version, so that display-class type parameters are
// substituted with the type parameters from the use-site.
var fieldType = field.Type;
// However, use the unspecialized member definition to make reference comparisons in dictionary possible.
field = (IField)field.MemberDefinition;
if (!displayClass.Variables.TryGetValue(field, out var v)) { if (!displayClass.Variables.TryGetValue(field, out var v)) {
context.Step($"Introduce captured variable for {field.FullName}", inst); context.Step($"Introduce captured variable for {field.FullName}", inst);
// Introduce a fresh variable for the display class field. // Introduce a fresh variable for the display class field.
Debug.Assert(displayClass.Definition == field.DeclaringTypeDefinition); Debug.Assert(displayClass.Definition == field.DeclaringTypeDefinition);
v = displayClass.DeclaringFunction.RegisterVariable(VariableKind.Local, GetVariableTypeFromClosureField(field), field.Name); v = displayClass.DeclaringFunction.RegisterVariable(VariableKind.Local, fieldType, field.Name);
v.HasInitialValue = true; v.HasInitialValue = true;
v.CaptureScope = displayClass.CaptureScope; v.CaptureScope = displayClass.CaptureScope;
inst.ReplaceWith(new LdLoca(v).WithILRange(inst)); inst.ReplaceWith(new LdLoca(v).WithILRange(inst));
@ -364,20 +369,5 @@ namespace ICSharpCode.Decompiler.IL.Transforms
inst.ReplaceWith(new LdLoca(v).WithILRange(inst)); inst.ReplaceWith(new LdLoca(v).WithILRange(inst));
} }
} }
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