diff --git a/ICSharpCode.Decompiler/IL/Transforms/LocalFunctionDecompiler.cs b/ICSharpCode.Decompiler/IL/Transforms/LocalFunctionDecompiler.cs index 0b9ae651e..003462046 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/LocalFunctionDecompiler.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/LocalFunctionDecompiler.cs @@ -484,7 +484,27 @@ namespace ICSharpCode.Decompiler.IL.Transforms break; parametersToRemove++; } - return new LocalFunctionMethod(method, method.Name, parametersToRemove, typeParametersToRemove); + return new LocalFunctionMethod(method, method.Name, CanBeStaticLocalFunction(), parametersToRemove, typeParametersToRemove); + + bool CanBeStaticLocalFunction() + { + if (!context.Settings.StaticLocalFunctions) + return false; + // Cannot be static because there are closure parameters that will be removed + if (parametersToRemove > 0) + return false; + // no closure parameters, but static: + // we can safely assume, this local function can be declared static + if (method.IsStatic) + return true; + // the local function is used in conjunction with a lambda, which means, + // it is defined inside the display-class type + var declaringType = method.DeclaringTypeDefinition; + if (!declaringType.IsCompilerGenerated()) + return false; + // if there are no instance fields, we can make it a static local function + return !declaringType.GetFields(f => !f.IsStatic).Any(); + } } static void TransformToLocalFunctionReference(ILFunction function, CallInstruction useSite) diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/LocalFunctionMethod.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/LocalFunctionMethod.cs index 57cce32dd..1139366f1 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/LocalFunctionMethod.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/LocalFunctionMethod.cs @@ -31,12 +31,13 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation { readonly IMethod baseMethod; - public LocalFunctionMethod(IMethod baseMethod, string name, int numberOfCompilerGeneratedParameters, int numberOfCompilerGeneratedTypeParameters) + public LocalFunctionMethod(IMethod baseMethod, string name, bool isStaticLocalFunction, int numberOfCompilerGeneratedParameters, int numberOfCompilerGeneratedTypeParameters) { if (baseMethod == null) throw new ArgumentNullException(nameof(baseMethod)); this.baseMethod = baseMethod; this.Name = name; + this.IsStaticLocalFunction = isStaticLocalFunction; this.NumberOfCompilerGeneratedParameters = numberOfCompilerGeneratedParameters; this.NumberOfCompilerGeneratedTypeParameters = numberOfCompilerGeneratedTypeParameters; } @@ -47,7 +48,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation return false; return baseMethod.Equals(other.baseMethod, typeNormalization) && NumberOfCompilerGeneratedParameters == other.NumberOfCompilerGeneratedParameters - && NumberOfCompilerGeneratedTypeParameters == other.NumberOfCompilerGeneratedTypeParameters; + && NumberOfCompilerGeneratedTypeParameters == other.NumberOfCompilerGeneratedTypeParameters + && IsStaticLocalFunction == other.IsStaticLocalFunction; } public override bool Equals(object obj) @@ -56,7 +58,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation return false; return baseMethod.Equals(other.baseMethod) && NumberOfCompilerGeneratedParameters == other.NumberOfCompilerGeneratedParameters - && NumberOfCompilerGeneratedTypeParameters == other.NumberOfCompilerGeneratedTypeParameters; + && NumberOfCompilerGeneratedTypeParameters == other.NumberOfCompilerGeneratedTypeParameters + && IsStaticLocalFunction == other.IsStaticLocalFunction; } public override int GetHashCode() @@ -66,14 +69,14 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation public override string ToString() { - return string.Format("[LocalFunctionMethod: ReducedFrom={0}, Name={1}, NumberOfGeneratedParameters={2}, NumberOfCompilerGeneratedTypeParameters={3}]", ReducedFrom, Name, NumberOfCompilerGeneratedParameters, NumberOfCompilerGeneratedTypeParameters); + return string.Format("[LocalFunctionMethod: ReducedFrom={0}, Name={1}, NumberOfGeneratedParameters={2}, NumberOfCompilerGeneratedTypeParameters={3}, IsStaticLocalFunction={4}]", ReducedFrom, Name, NumberOfCompilerGeneratedParameters, NumberOfCompilerGeneratedTypeParameters, IsStaticLocalFunction); } internal int NumberOfCompilerGeneratedParameters { get; } internal int NumberOfCompilerGeneratedTypeParameters { get; } - internal bool IsStaticLocalFunction => NumberOfCompilerGeneratedParameters == 0 && (baseMethod.IsStatic || (baseMethod.DeclaringTypeDefinition.IsCompilerGenerated() && !baseMethod.DeclaringType.GetFields(f => !f.IsStatic).Any())); + internal bool IsStaticLocalFunction { get; } public IMember MemberDefinition => this; @@ -89,7 +92,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation { return new LocalFunctionMethod( baseMethod.Specialize(substitution), - Name, NumberOfCompilerGeneratedParameters, NumberOfCompilerGeneratedTypeParameters); + Name, IsStaticLocalFunction, NumberOfCompilerGeneratedParameters, NumberOfCompilerGeneratedTypeParameters); } IMember IMember.Specialize(TypeParameterSubstitution substitution)