diff --git a/src/linker/Linker.Dataflow/CompilerGeneratedNames.cs b/src/linker/Linker.Dataflow/CompilerGeneratedNames.cs index 46e6c9764782..afdb716f5af6 100644 --- a/src/linker/Linker.Dataflow/CompilerGeneratedNames.cs +++ b/src/linker/Linker.Dataflow/CompilerGeneratedNames.cs @@ -34,6 +34,19 @@ internal static bool IsStateMachineType (string typeName) return typeName.Length > i + 1 && typeName[i + 1] == 'd'; } + internal static bool IsStateMachineCurrentField (string fieldName) + { + if (!IsGeneratedMemberName (fieldName)) + return false; + + int i = fieldName.LastIndexOf ('>'); + if (i == -1) + return false; + + // Current field is <>2__current + return fieldName.Length > i + 1 && fieldName[i + 1] == '2'; + } + internal static bool IsGeneratedType (string name) => IsStateMachineType (name) || IsLambdaDisplayClass (name); internal static bool IsLambdaOrLocalFunction (string methodName) => IsLambdaMethod (methodName) || IsLocalFunction (methodName); diff --git a/src/linker/Linker.Dataflow/CompilerGeneratedState.cs b/src/linker/Linker.Dataflow/CompilerGeneratedState.cs index 3213f49fdc49..3033cef70153 100644 --- a/src/linker/Linker.Dataflow/CompilerGeneratedState.cs +++ b/src/linker/Linker.Dataflow/CompilerGeneratedState.cs @@ -55,10 +55,16 @@ static IEnumerable GetCompilerGeneratedNestedTypes (TypeDefiniti public static bool IsHoistedLocal (FieldDefinition field) { - // Treat all fields on compiler-generated types as hoisted locals. - // This avoids depending on the name mangling scheme for hoisted locals. - var declaringTypeName = field.DeclaringType.Name; - return CompilerGeneratedNames.IsLambdaDisplayClass (declaringTypeName) || CompilerGeneratedNames.IsStateMachineType (declaringTypeName); + if (CompilerGeneratedNames.IsLambdaDisplayClass (field.DeclaringType.Name)) + return true; + + if (CompilerGeneratedNames.IsStateMachineType (field.DeclaringType.Name)) { + // Don't track the "current" field which is used for state machine return values, + // because this can be expensive to track. + return !CompilerGeneratedNames.IsStateMachineCurrentField (field.Name); + } + + return false; } // "Nested function" refers to lambdas and local functions. diff --git a/test/Mono.Linker.Tests.Cases/DataFlow/CompilerGeneratedCodeDataflow.cs b/test/Mono.Linker.Tests.Cases/DataFlow/CompilerGeneratedCodeDataflow.cs index 53032ae723e4..90b2c53bf058 100644 --- a/test/Mono.Linker.Tests.Cases/DataFlow/CompilerGeneratedCodeDataflow.cs +++ b/test/Mono.Linker.Tests.Cases/DataFlow/CompilerGeneratedCodeDataflow.cs @@ -210,8 +210,8 @@ public static void Test () FlowParameterAcrossYieldReturn (); FlowUnannotatedParameterAcrossYieldReturn (); FlowAcrossYieldReturnWithBackwardsBranch (); - - foreach (var o in ReturnManyObjects ()); + + foreach (var o in ReturnManyObjects ()) ; } } diff --git a/test/Mono.Linker.Tests/TestCasesRunner/ILVerifier.cs b/test/Mono.Linker.Tests/TestCasesRunner/ILVerifier.cs index bf935cc22067..d9d4b8a43234 100644 --- a/test/Mono.Linker.Tests/TestCasesRunner/ILVerifier.cs +++ b/test/Mono.Linker.Tests/TestCasesRunner/ILVerifier.cs @@ -14,13 +14,13 @@ #nullable enable namespace Mono.Linker.Tests.TestCasesRunner { - class ILVerifier : ILVerify.IResolver + sealed class ILVerifier : ILVerify.IResolver { - Verifier _verifier; - NPath _assemblyFolder; - NPath _frameworkFolder; - Dictionary _assemblyCache; - AssemblyLoadContext _alc; + readonly Verifier _verifier; + readonly NPath _assemblyFolder; + readonly NPath _frameworkFolder; + readonly Dictionary _assemblyCache; + readonly AssemblyLoadContext _alc; public IEnumerable Results { get; private set; } @@ -123,7 +123,7 @@ bool TryLoadAssemblyFromFolder (string assemblyName, NPath folder, [NotNullWhen PEReader? ILVerify.IResolver.ResolveModule (AssemblyName referencingModule, string fileName) => Resolve (Path.GetFileNameWithoutExtension (fileName)); - public string GetErrorMessage (VerificationResult result) + public static string GetErrorMessage (VerificationResult result) { return $"IL Verification error:\n{result.Message}"; } diff --git a/test/Mono.Linker.Tests/TestCasesRunner/ResultChecker.cs b/test/Mono.Linker.Tests/TestCasesRunner/ResultChecker.cs index ccb76575ff41..4a7de6de60bd 100644 --- a/test/Mono.Linker.Tests/TestCasesRunner/ResultChecker.cs +++ b/test/Mono.Linker.Tests/TestCasesRunner/ResultChecker.cs @@ -55,7 +55,7 @@ static void VerifyIL (NPath pathToAssembly) foreach (var result in verifier.Results) { if (result.Code == ILVerify.VerifierError.None) continue; - Assert.Fail (verifier.GetErrorMessage (result)); + Assert.Fail (ILVerifier.GetErrorMessage (result)); } } @@ -1122,7 +1122,7 @@ static bool TryGetCustomAttribute (ICustomAttributeProvider caProvider, string a return false; } - static IEnumerable GetCustomAttributes (ICustomAttributeProvider caProvider, string attributeName ) + static IEnumerable GetCustomAttributes (ICustomAttributeProvider caProvider, string attributeName) { if (caProvider is AssemblyDefinition assembly && assembly.EntryPoint != null) return assembly.EntryPoint.DeclaringType.CustomAttributes