From 7319f861b9a6a4bbd09655ae254e64b7fdea83de Mon Sep 17 00:00:00 2001 From: Vitek Karas <10670590+vitek-karas@users.noreply.github.com> Date: Sat, 3 Jun 2023 13:53:59 -0700 Subject: [PATCH] Unify trim warnings for accessing compiler generated code (#86816) This modifies the behavior of both the illink and ilc to match and to implement some changes we've discussed recently - https://github.com/dotnet/runtime/issues/86008. The semantic changes (mostly as compared to previous illink behavior): * Reflection access to a RUC virtual method will produce warning on all methods which have RUC, regardless of their relationships. Specifically if both the override and base methods are accessed, and they both have RUC, they will both generate a warning. (This effectively removes an optimization which illink had to avoid "duplicate" warnings where it tried to warn only on the base methods in this case. But this has holes - see https://github.com/dotnet/runtime/issues/86008). * Reflection access to compiler generated code will not produce warnings even if the target has RUC on it. It proved to be really difficult to design a good experience for reporting warnings in these cases. The problem is that developer has little control over the generated code and fully reporting all warnings leads to lot of noise. The above optimization in the illink tried to solve some of this, but it's not very successful. So we're removing all of these warnings. The reasoning is that reflection access to compiler generated members is an undefined behavior (even on non-trimmed, normal CLR) - and is likely to break for example between compiler versions - and there's no diagnostics about it ignoring trimming. Trimming/AOT just makes it a little bit worse. * AOT compiler will not implement warnings caused by reflection access to compiler generated code which has annotations either (so `IL2118`, `IL2119` and `IL2120`). The plan is to eventually remove these from illink as well. Note that there are exceptions to the above rules, which can be described as: Accessing a token of a member in IL is considered a reflection access (because the token can be turned into a reflection object), but it is also considered a direct reference. So in that case marking is implemented as "reflection access", but diagnostics is implemented as "direct reference". What this means is that accessing a compiler generated member through its token will still produce all warnings (RUC or DAM) as for non-compiler-generated member. This is important for things like creation of `Action` from a lambda, where the lambda is a compiler generated method, but we need to produce warnings if it uses annotations for example. Refactorings: * Refactored code in MarkStep to move most of the diagnostics logic into `ReportWarningsForReflectionAccess` - this is to mirror the design in ilc and also to make it more in sync with the already existing `ReportWarningsForTypeHierarchyReflectionAccess`. Test changes: * Adapting existing tests to the new behavior * Adding some new tests, specifically around reflection access to compiler generated code and token access to compiler generated code. * Enables `CompilerGeneratedCodeAccessedViaReflection` for ilc --- .../Compiler/Dataflow/ReflectionMarker.cs | 52 ++-- .../src/linker/Linker.Steps/MarkStep.cs | 139 ++++++----- ...pilerGeneratedCodeAccessedViaReflection.cs | 225 ++++++++++++------ .../TypeHierarchyReflectionWarnings.cs | 176 +++++++++++++- ...flectionAccessFromCompilerGeneratedCode.cs | 14 +- .../RequiresAccessedThrough.cs | 146 +++++++----- .../RequiresAttributeMismatch.cs | 39 +-- .../RequiresInCompilerGeneratedCode.cs | 124 ++-------- .../RequiresCapability/RequiresOnClass.cs | 40 +++- .../RequiresOnVirtualsAndInterfaces.cs | 17 +- .../RequiresCapability/RequiresViaDataflow.cs | 156 ++++++++---- .../TestCasesRunner/AssemblyChecker.cs | 19 +- 12 files changed, 713 insertions(+), 434 deletions(-) diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReflectionMarker.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReflectionMarker.cs index d32757d162d8..c2132ce7aa6d 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReflectionMarker.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReflectionMarker.cs @@ -239,30 +239,24 @@ private void ReportWarningsForReflectionAccess(in MessageOrigin origin, TypeSyst // This is because reflection access is actually problematic on all members which are in a "requires" scope // so for example even instance methods. See for example https://github.com/dotnet/linker/issues/3140 - it's possible // to call a method on a "null" instance via reflection. - if (_logger.ShouldSuppressAnalysisWarningsForRequires(entity, DiagnosticUtilities.RequiresUnreferencedCodeAttribute, out CustomAttributeValue? requiresAttribute)) - { - if (!ShouldSkipWarningsForOverride(entity, accessKind)) + if (_logger.ShouldSuppressAnalysisWarningsForRequires(entity, DiagnosticUtilities.RequiresUnreferencedCodeAttribute, out CustomAttributeValue? requiresAttribute) && + ShouldProduceRequiresWarningForReflectionAccess(entity, accessKind)) ReportRequires(origin, entity, DiagnosticUtilities.RequiresUnreferencedCodeAttribute, requiresAttribute.Value); - } - if (_logger.ShouldSuppressAnalysisWarningsForRequires(entity, DiagnosticUtilities.RequiresAssemblyFilesAttribute, out requiresAttribute)) - { - if (!ShouldSkipWarningsForOverride(entity, accessKind)) + if (_logger.ShouldSuppressAnalysisWarningsForRequires(entity, DiagnosticUtilities.RequiresAssemblyFilesAttribute, out requiresAttribute) && + ShouldProduceRequiresWarningForReflectionAccess(entity, accessKind)) ReportRequires(origin, entity, DiagnosticUtilities.RequiresAssemblyFilesAttribute, requiresAttribute.Value); - } - if (_logger.ShouldSuppressAnalysisWarningsForRequires(entity, DiagnosticUtilities.RequiresDynamicCodeAttribute, out requiresAttribute)) - { - if (!ShouldSkipWarningsForOverride(entity, accessKind)) + if (_logger.ShouldSuppressAnalysisWarningsForRequires(entity, DiagnosticUtilities.RequiresDynamicCodeAttribute, out requiresAttribute) && + ShouldProduceRequiresWarningForReflectionAccess(entity, accessKind)) ReportRequires(origin, entity, DiagnosticUtilities.RequiresDynamicCodeAttribute, requiresAttribute.Value); - } // Below is about accessing DAM annotated members, so only RUC is applicable as a suppression scope if (_logger.ShouldSuppressAnalysisWarningsForRequires(origin.MemberDefinition, DiagnosticUtilities.RequiresUnreferencedCodeAttribute)) return; bool isReflectionAccessCoveredByDAM = Annotations.ShouldWarnWhenAccessedForReflection(entity); - if (isReflectionAccessCoveredByDAM && !ShouldSkipWarningsForOverride(entity, accessKind)) + if (isReflectionAccessCoveredByDAM && ShouldProduceRequiresWarningForReflectionAccess(entity, accessKind)) { if (entity is MethodDesc) _logger.LogWarning(origin, DiagnosticId.DynamicallyAccessedMembersMethodAccessedViaReflection, entity.GetDisplayName()); @@ -273,16 +267,16 @@ private void ReportWarningsForReflectionAccess(in MessageOrigin origin, TypeSyst // We decided to not warn on reflection access to compiler-generated methods: // https://github.com/dotnet/runtime/issues/85042 - // All override methods should have the same annotations as their base methods - // (else we will produce warning IL2046 or IL2092 or some other warning). - // When marking override methods via DynamicallyAccessedMembers, we should only issue a warning for the base method. - // PERF: Avoid precomputing this as this method is relatively expensive. Only call it once we're about to produce a warning. - static bool ShouldSkipWarningsForOverride(TypeSystemEntity entity, AccessKind accessKind) + static bool ShouldProduceRequiresWarningForReflectionAccess(TypeSystemEntity entity, AccessKind accessKind) { - if (accessKind != AccessKind.DynamicallyAccessedMembersMark || entity is not MethodDesc method || !method.IsVirtual) - return false; + bool isCompilerGenerated = CompilerGeneratedState.IsNestedFunctionOrStateMachineMember(entity); - return MetadataVirtualMethodAlgorithm.FindSlotDefiningMethodForVirtualMethod(method) != method; + // Compiler generated code accessed via a token is considered a "hard" reference + // even though we also have to treat it as reflection access. + // So we need to enforce RUC check/warn in this case. + bool forceRequiresWarning = accessKind == AccessKind.TokenAccess; + + return !isCompilerGenerated || forceRequiresWarning; } } @@ -319,7 +313,8 @@ static bool IsDeclaredWithinType(TypeSystemEntity member, TypeDesc type) // causing problems is pretty low. bool isReflectionAccessCoveredByRUC = _logger.ShouldSuppressAnalysisWarningsForRequires(entity, DiagnosticUtilities.RequiresUnreferencedCodeAttribute, out CustomAttributeValue? requiresUnreferencedCodeAttribute); - if (isReflectionAccessCoveredByRUC && !ShouldSkipWarningsForOverride(entity)) + bool isCompilerGenerated = CompilerGeneratedState.IsNestedFunctionOrStateMachineMember(entity); + if (isReflectionAccessCoveredByRUC && !isCompilerGenerated) { var id = reportOnMember ? DiagnosticId.DynamicallyAccessedMembersOnTypeReferencesMemberWithRequiresUnreferencedCode : DiagnosticId.DynamicallyAccessedMembersOnTypeReferencesMemberOnBaseWithRequiresUnreferencedCode; _logger.LogWarning(origin, id, _typeHierarchyDataFlowOrigin.GetDisplayName(), @@ -329,7 +324,7 @@ static bool IsDeclaredWithinType(TypeSystemEntity member, TypeDesc type) } bool isReflectionAccessCoveredByDAM = Annotations.ShouldWarnWhenAccessedForReflection(entity); - if (isReflectionAccessCoveredByDAM && !ShouldSkipWarningsForOverride(entity)) + if (isReflectionAccessCoveredByDAM && !isCompilerGenerated) { var id = reportOnMember ? DiagnosticId.DynamicallyAccessedMembersOnTypeReferencesMemberWithDynamicallyAccessedMembers : DiagnosticId.DynamicallyAccessedMembersOnTypeReferencesMemberOnBaseWithDynamicallyAccessedMembers; _logger.LogWarning(origin, id, _typeHierarchyDataFlowOrigin.GetDisplayName(), entity.GetDisplayName()); @@ -337,17 +332,6 @@ static bool IsDeclaredWithinType(TypeSystemEntity member, TypeDesc type) // We decided to not warn on reflection access to compiler-generated methods: // https://github.com/dotnet/runtime/issues/85042 - - // All override methods should have the same annotations as their base methods - // (else we will produce warning IL2046 or IL2092 or some other warning). - // When marking override methods via DynamicallyAccessedMembers, we should only issue a warning for the base method. - static bool ShouldSkipWarningsForOverride(TypeSystemEntity entity) - { - if (entity is not MethodDesc method || !method.IsVirtual) - return false; - - return MetadataVirtualMethodAlgorithm.FindSlotDefiningMethodForVirtualMethod(method) != method; - } } private void ReportRequires(in MessageOrigin origin, TypeSystemEntity entity, string requiresAttributeName, in CustomAttributeValue requiresAttribute) diff --git a/src/tools/illink/src/linker/Linker.Steps/MarkStep.cs b/src/tools/illink/src/linker/Linker.Steps/MarkStep.cs index 98b456626e09..b6376efeef6f 100644 --- a/src/tools/illink/src/linker/Linker.Steps/MarkStep.cs +++ b/src/tools/illink/src/linker/Linker.Steps/MarkStep.cs @@ -1628,6 +1628,74 @@ protected void MarkField (FieldReference reference, DependencyInfo reason, in Me MarkField (field, reason, origin); } + void ReportWarningsForReflectionAccess (in MessageOrigin origin, MethodDefinition method, DependencyKind dependencyKind) + { + if (Annotations.ShouldSuppressAnalysisWarningsForRequiresUnreferencedCode (origin.Provider, out _)) + return; + + bool isReflectionAccessCoveredByRUC; + bool isCompilerGenerated = CompilerGeneratedState.IsNestedFunctionOrStateMachineMember (method); + bool forceRUCCheck = false; + RequiresUnreferencedCodeAttribute? requiresUnreferencedCode; + switch (dependencyKind) { + case DependencyKind.AttributeProperty: + // Property assignment in an attribute instance. + // This case is more like a direct method call than reflection, and should + // be logically similar to what is done in ReflectionMethodBodyScanner for method calls. + isReflectionAccessCoveredByRUC = Annotations.DoesMethodRequireUnreferencedCode (method, out requiresUnreferencedCode); + break; + + case DependencyKind.Ldftn: + case DependencyKind.Ldvirtftn: + case DependencyKind.Ldtoken: + // Compiler generated code accessed via a token is considered a "hard" reference + // even though we also have to treat it as reflection access. + // So we need to enforce RUC check/warn in this case. + forceRUCCheck = true; + isReflectionAccessCoveredByRUC = Annotations.ShouldSuppressAnalysisWarningsForRequiresUnreferencedCode (method, out requiresUnreferencedCode); + break; + + default: + // If the method being accessed has warnings suppressed due to Requires attributes, + // we need to issue a warning for the reflection access. This is true even for instance + // methods, which can be reflection-invoked without ever calling a constructor of the + // accessed type. + isReflectionAccessCoveredByRUC = Annotations.ShouldSuppressAnalysisWarningsForRequiresUnreferencedCode (method, out requiresUnreferencedCode); + break; + } + + if (isReflectionAccessCoveredByRUC && (!isCompilerGenerated || forceRUCCheck)) + ReportRequiresUnreferencedCode (method.GetDisplayName (), requiresUnreferencedCode!, new DiagnosticContext (origin, diagnosticsEnabled: true, Context)); + + bool isReflectionAccessCoveredByDAM = Annotations.FlowAnnotations.ShouldWarnWhenAccessedForReflection (method); + if (isReflectionAccessCoveredByDAM && (!isCompilerGenerated || forceRUCCheck)) { + // ReflectionMethodBodyScanner handles more cases for data flow annotations + // so don't warn for those. + switch (dependencyKind) { + case DependencyKind.AttributeConstructor: + case DependencyKind.AttributeProperty: + break; + default: + Context.LogWarning (origin, DiagnosticId.DynamicallyAccessedMembersMethodAccessedViaReflection, method.GetDisplayName ()); + break; + } + } + + // Warn on reflection access to compiler-generated methods, if the method isn't already unsafe to access via reflection + // due to annotations. For the annotation-based warnings, we skip virtual overrides since those will produce warnings on + // the base, but for unannotated compiler-generated methods this is not the case, so we must produce these warnings even + // for virtual overrides. This ensures that we include the unannotated MoveNext state machine method. Lambdas and local + // functions should never be virtual overrides in the first place. + bool isCoveredByAnnotations = isReflectionAccessCoveredByRUC || isReflectionAccessCoveredByDAM; + switch (dependencyKind) { + case DependencyKind.AccessedViaReflection: + case DependencyKind.DynamicallyAccessedMember: + if (ShouldWarnForReflectionAccessToCompilerGeneratedCode (method, isCoveredByAnnotations)) + Context.LogWarning (origin, DiagnosticId.CompilerGeneratedMemberAccessedViaReflection, method.GetDisplayName ()); + break; + } + } + void ReportWarningsForTypeHierarchyReflectionAccess (IMemberDefinition member, MessageOrigin origin) { Debug.Assert (member is MethodDefinition or FieldDefinition); @@ -1653,14 +1721,9 @@ static bool IsDeclaredWithinType (IMemberDefinition member, TypeDefinition type) if (reportOnMember) origin = new MessageOrigin (member); - - // All override methods should have the same annotations as their base methods - // (else we will produce warning IL2046 or IL2092 or some other warning). - // When marking override methods via DynamicallyAccessedMembers, we should only issue a warning for the base method. - bool skipWarningsForOverride = member is MethodDefinition m && m.IsVirtual && Annotations.GetBaseMethods (m) != null; - bool isReflectionAccessCoveredByRUC = Annotations.ShouldSuppressAnalysisWarningsForRequiresUnreferencedCode (member, out RequiresUnreferencedCodeAttribute? requiresUnreferencedCodeAttribute); - if (isReflectionAccessCoveredByRUC && !skipWarningsForOverride) { + bool isCompilerGenerated = CompilerGeneratedState.IsNestedFunctionOrStateMachineMember (member); + if (isReflectionAccessCoveredByRUC && !isCompilerGenerated) { var id = reportOnMember ? DiagnosticId.DynamicallyAccessedMembersOnTypeReferencesMemberWithRequiresUnreferencedCode : DiagnosticId.DynamicallyAccessedMembersOnTypeReferencesMemberOnBaseWithRequiresUnreferencedCode; Context.LogWarning (origin, id, type.GetDisplayName (), ((MemberReference) member).GetDisplayName (), // The cast is valid since it has to be a method or field @@ -1669,7 +1732,7 @@ static bool IsDeclaredWithinType (IMemberDefinition member, TypeDefinition type) } bool isReflectionAccessCoveredByDAM = Annotations.FlowAnnotations.ShouldWarnWhenAccessedForReflection (member); - if (isReflectionAccessCoveredByDAM && !skipWarningsForOverride) { + if (isReflectionAccessCoveredByDAM && !isCompilerGenerated) { var id = reportOnMember ? DiagnosticId.DynamicallyAccessedMembersOnTypeReferencesMemberWithDynamicallyAccessedMembers : DiagnosticId.DynamicallyAccessedMembersOnTypeReferencesMemberOnBaseWithDynamicallyAccessedMembers; Context.LogWarning (origin, id, type.GetDisplayName (), ((MemberReference) member).GetDisplayName ()); } @@ -3071,74 +3134,20 @@ void ProcessAnalysisAnnotationsForMethod (MethodDefinition method, DependencyKin // Don't warn for methods kept due to non-understood DebuggerDisplayAttribute // until https://github.com/dotnet/linker/issues/1873 is fixed. case DependencyKind.KeptForSpecialAttribute: - return; + break; case DependencyKind.DynamicallyAccessedMemberOnType: // DynamicallyAccessedMembers on type gets special treatment so that the warning origin // is the type or the annotated member. ReportWarningsForTypeHierarchyReflectionAccess (method, origin); - return; + break; default: // All other cases have the potential of us missing a warning if we don't report it // It is possible that in some cases we may report the same warning twice, but that's better than not reporting it. + ReportWarningsForReflectionAccess (origin, method, dependencyKind); break; }; - - if (Annotations.ShouldSuppressAnalysisWarningsForRequiresUnreferencedCode (origin.Provider, out _)) - return; - - bool skipWarningsForOverride; - bool isReflectionAccessCoveredByRUC; - RequiresUnreferencedCodeAttribute? requiresUnreferencedCode; - if (dependencyKind == DependencyKind.AttributeProperty) { - // Property assignment in an attribute instance. - // This case is more like a direct method call than reflection, and should - // be logically similar to what is done in ReflectionMethodBodyScanner for method calls. - skipWarningsForOverride = false; - isReflectionAccessCoveredByRUC = Annotations.DoesMethodRequireUnreferencedCode (method, out requiresUnreferencedCode); - } else { - // All override methods should have the same annotations as their base methods - // (else we will produce warning IL2046 or IL2092 or some other warning). - // When marking override methods via DynamicallyAccessedMembers, we should only issue a warning for the base method. - skipWarningsForOverride = dependencyKind == DependencyKind.DynamicallyAccessedMember && method.IsVirtual && Annotations.GetBaseMethods (method) != null; - // If the method being accessed has warnings suppressed due to Requires attributes, - // we need to issue a warning for the reflection access. This is true even for instance - // methods, which can be reflection-invoked without ever calling a constructor of the - // accessed type. - isReflectionAccessCoveredByRUC = Annotations.ShouldSuppressAnalysisWarningsForRequiresUnreferencedCode (method, out requiresUnreferencedCode); - } - - if (isReflectionAccessCoveredByRUC && !skipWarningsForOverride) - ReportRequiresUnreferencedCode (method.GetDisplayName (), requiresUnreferencedCode!, new DiagnosticContext (origin, diagnosticsEnabled: true, Context)); - - bool isReflectionAccessCoveredByDAM = Annotations.FlowAnnotations.ShouldWarnWhenAccessedForReflection (method); - if (isReflectionAccessCoveredByDAM && !skipWarningsForOverride) { - // ReflectionMethodBodyScanner handles more cases for data flow annotations - // so don't warn for those. - switch (dependencyKind) { - case DependencyKind.AttributeConstructor: - case DependencyKind.AttributeProperty: - break; - default: - Context.LogWarning (origin, DiagnosticId.DynamicallyAccessedMembersMethodAccessedViaReflection, method.GetDisplayName ()); - break; - } - } - - // Warn on reflection access to compiler-generated methods, if the method isn't already unsafe to access via reflection - // due to annotations. For the annotation-based warnings, we skip virtual overrides since those will produce warnings on - // the base, but for unannotated compiler-generated methods this is not the case, so we must produce these warnings even - // for virtual overrides. This ensures that we include the unannotated MoveNext state machine method. Lambdas and local - // functions should never be virtual overrides in the first place. - bool isCoveredByAnnotations = isReflectionAccessCoveredByRUC || isReflectionAccessCoveredByDAM; - switch (dependencyKind) { - case DependencyKind.AccessedViaReflection: - case DependencyKind.DynamicallyAccessedMember: - if (ShouldWarnForReflectionAccessToCompilerGeneratedCode (method, isCoveredByAnnotations)) - Context.LogWarning (origin, DiagnosticId.CompilerGeneratedMemberAccessedViaReflection, method.GetDisplayName ()); - break; - } } internal static void ReportRequiresUnreferencedCode (string displayName, RequiresUnreferencedCodeAttribute requiresUnreferencedCode, in DiagnosticContext diagnosticContext) diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/CompilerGeneratedCodeAccessedViaReflection.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/CompilerGeneratedCodeAccessedViaReflection.cs index 283f08e89446..abe939c2322b 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/CompilerGeneratedCodeAccessedViaReflection.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/CompilerGeneratedCodeAccessedViaReflection.cs @@ -15,7 +15,6 @@ namespace Mono.Linker.Tests.Cases.DataFlow { - [IgnoreTestCase ("Ignore in NativeAOT, see https://github.com/dotnet/runtime/issues/82447", IgnoredBy = Tool.NativeAot)] [SkipKeptItemsValidation] [ExpectedNoWarnings] class CompilerGeneratedCodeAccessedViaReflection @@ -29,6 +28,9 @@ public static void Main () LocalFunctions.Test (); SelfMarkingMethods.Test (); + DelegateAccess.Test (); + + DAMReflectionAccessToCompilerGeneratedCode.Test (); } class BaseTypeWithIteratorStateMachines @@ -55,9 +57,9 @@ public static IEnumerable IteratorWithoutDataflow () [ExpectedWarning ("IL2026", "--MethodWithRequires--", CompilerGeneratedCode = true)] [ExpectedWarning ("IL3002", "--MethodWithRequires--", - ProducedBy = Tool.Analyzer)] + ProducedBy = Tool.Analyzer | Tool.NativeAot, CompilerGeneratedCode = true)] [ExpectedWarning ("IL3050", "--MethodWithRequires--", - ProducedBy = Tool.Analyzer)] + ProducedBy = Tool.Analyzer | Tool.NativeAot, CompilerGeneratedCode = true)] [ExpectedWarning ("IL2119", "<" + nameof (IteratorCallsMethodWithRequires) + ">", "MoveNext", CompilerGeneratedCode = true, ProducedBy = Tool.Trimmer)] public static IEnumerable IteratorCallsMethodWithRequires () @@ -102,28 +104,24 @@ public static IEnumerable IteratorWithProblematicDataflow () } [ExpectedWarning ("IL2112", nameof (RUCTypeWithIterators) + "()", "--RUCTypeWithIterators--", CompilerGeneratedCode = true, - ProducedBy = Tool.Trimmer)] + ProducedBy = Tool.Trimmer | Tool.NativeAot)] // warning about .ctor [RequiresUnreferencedCode ("--RUCTypeWithIterators--")] class RUCTypeWithIterators { - [ExpectedWarning ("IL2112", "<" + nameof (StaticIteratorCallsMethodWithRequires) + ">", "(Int32)", "--RUCTypeWithIterators--", CompilerGeneratedCode = true, - ProducedBy = Tool.Trimmer)] // state machine ctor - [ExpectedWarning ("IL2112", nameof (StaticIteratorCallsMethodWithRequires) + "()", "--RUCTypeWithIterators--", - ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2112", nameof (StaticIteratorCallsMethodWithRequires) + "()", + ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot, CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot, CompilerGeneratedCode = true)] public static IEnumerable StaticIteratorCallsMethodWithRequires () { yield return 0; MethodWithRequires (); } - [ExpectedWarning ("IL2112", "<" + nameof (InstanceIteratorCallsMethodWithRequires) + ">", "(Int32)", "--RUCTypeWithIterators--", CompilerGeneratedCode = true, - ProducedBy = Tool.Trimmer)] // state machine ctor [ExpectedWarning ("IL2112", nameof (InstanceIteratorCallsMethodWithRequires) + "()", - ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer)] + ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot, CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot, CompilerGeneratedCode = true)] public IEnumerable InstanceIteratorCallsMethodWithRequires () { yield return 0; @@ -144,11 +142,7 @@ public IEnumerable InstanceIteratorCallsMethodWithRequires () [ExpectedWarning ("IL2026", nameof (RUCTypeWithIterators) + "()", "--RUCTypeWithIterators--")] // Expect to see warnings about RUC on type, for all static state machine members. [ExpectedWarning ("IL2026", nameof (RUCTypeWithIterators.StaticIteratorCallsMethodWithRequires) + "()", "--RUCTypeWithIterators--")] - [ExpectedWarning ("IL2026", "<" + nameof (RUCTypeWithIterators.StaticIteratorCallsMethodWithRequires) + ">", - ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2026", nameof (RUCTypeWithIterators.InstanceIteratorCallsMethodWithRequires) + "()", ProducedBy = Tool.Trimmer | Tool.Analyzer)] - [ExpectedWarning ("IL2026", "<" + nameof (RUCTypeWithIterators.InstanceIteratorCallsMethodWithRequires) + ">", "(Int32)", - ProducedBy = Tool.Trimmer)] // state machine ctor + [ExpectedWarning ("IL2026", nameof (RUCTypeWithIterators.InstanceIteratorCallsMethodWithRequires) + "()")] [ExpectedWarning ("IL2118", "<" + nameof (IteratorWithCorrectDataflow) + ">", "", ProducedBy = Tool.Trimmer)] [ExpectedWarning ("IL2118", "<" + nameof (IteratorWithProblematicDataflow) + ">", "", @@ -176,8 +170,8 @@ public static async Task AsyncWithoutDataflow () } [ExpectedWarning ("IL2026", "--MethodWithRequires--", CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot, CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot, CompilerGeneratedCode = true)] public static async Task AsyncCallsMethodWithRequires () { MethodWithRequires (); @@ -220,8 +214,8 @@ public static async IAsyncEnumerable AsyncIteratorWithoutDataflow () } [ExpectedWarning ("IL2026", "--MethodWithRequires--", CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot, CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot, CompilerGeneratedCode = true)] public static async IAsyncEnumerable AsyncIteratorCallsMethodWithRequires () { yield return await MethodAsync (); @@ -272,8 +266,8 @@ static void LambdaCallsMethodWithRequires () { var lambda = [ExpectedWarning ("IL2026", "--MethodWithRequires--")] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] [ExpectedWarning ("IL2119", "<" + nameof (LambdaCallsMethodWithRequires) + ">", ProducedBy = Tool.Trimmer)] () => MethodWithRequires (); @@ -293,12 +287,10 @@ static void LambdaWithCorrectDataflow () } [ExpectedWarning ("IL2111", "<" + nameof (LambdaWithCorrectParameter) + ">", - ProducedBy = Tool.Trimmer)] + ProducedBy = Tool.Trimmer | Tool.NativeAot)] static void LambdaWithCorrectParameter () { var lambda = - [ExpectedWarning ("IL2114", "<" + nameof (LambdaWithCorrectParameter) + ">", - ProducedBy = Tool.Trimmer)] ([DynamicallyAccessedMembersAttribute (DynamicallyAccessedMemberTypes.All)] Type t) => { t.RequiresAll (); }; @@ -357,26 +349,22 @@ static void LambdaCallsPInvokeTakingObject () } [ExpectedWarning ("IL2112", nameof (RUCTypeWithLambdas) + "()", "--RUCTypeWithLambdas--", CompilerGeneratedCode = true, - ProducedBy = Tool.Trimmer)] + ProducedBy = Tool.Trimmer | Tool.NativeAot)] [RequiresUnreferencedCode ("--RUCTypeWithLambdas--")] class RUCTypeWithLambdas { - [ExpectedWarning ("IL2112", nameof (MethodWithLambdas), "--RUCTypeWithLambdas--", ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2112", nameof (MethodWithLambdas), "--RUCTypeWithLambdas--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] public void MethodWithLambdas () { var lambda = - [ExpectedWarning ("IL2112", "<" + nameof (MethodWithLambdas) + ">", "--RUCTypeWithLambdas--", - ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] () => MethodWithRequires (); int i = 0; var lambdaWithCapturedState = - [ExpectedWarning ("IL2112", "<" + nameof (MethodWithLambdas) + ">", "--RUCTypeWithLambdas--", - ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] () => { i++; MethodWithRequires (); @@ -393,18 +381,12 @@ public void MethodWithLambdas () ProducedBy = Tool.Trimmer)] [ExpectedWarning ("IL2118", "<" + nameof (LambdaWithCorrectDataflow) + ">", ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2111", "<" + nameof (LambdaWithCorrectParameter) + ">", - ProducedBy = Tool.Trimmer)] [ExpectedWarning ("IL2118", "<" + nameof (LambdaWithProblematicDataflow) + ">", ProducedBy = Tool.Trimmer)] [ExpectedWarning ("IL2118", "<" + nameof (LambdaWithCapturedTypeToDAM) + ">", ProducedBy = Tool.Trimmer)] [ExpectedWarning ("IL2026", nameof (RUCTypeWithLambdas) + "()", "--RUCTypeWithLambdas--")] - [ExpectedWarning ("IL2026", nameof (RUCTypeWithLambdas.MethodWithLambdas) + "()", "--RUCTypeWithLambdas--", ProducedBy = Tool.Trimmer | Tool.Analyzer)] - [ExpectedWarning ("IL2026", "<" + nameof (RUCTypeWithLambdas.MethodWithLambdas) + ">", "--RUCTypeWithLambdas--", - ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2026", "<" + nameof (RUCTypeWithLambdas.MethodWithLambdas) + ">", "--RUCTypeWithLambdas--", - ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2026", nameof (RUCTypeWithLambdas.MethodWithLambdas) + "()", "--RUCTypeWithLambdas--")] public static void Test (Lambdas test = null) { typeof (Lambdas).RequiresAll (); @@ -425,8 +407,8 @@ static void LocalFunctionWithoutDataflow () static void LocalFunctionCallsMethodWithRequires () { [ExpectedWarning ("IL2026", "--MethodWithRequires--")] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] [ExpectedWarning ("IL2119", "<" + nameof (LocalFunctionCallsMethodWithRequires) + ">", ProducedBy = Tool.Trimmer)] void LocalFunction () => MethodWithRequires (); @@ -494,31 +476,25 @@ static void LocalFunctionCallsPInvokeTakingObject () } [ExpectedWarning ("IL2112", nameof (RUCTypeWithLocalFunctions) + "()", CompilerGeneratedCode = true, - ProducedBy = Tool.Trimmer)] + ProducedBy = Tool.Trimmer | Tool.NativeAot)] [RequiresUnreferencedCode ("--RUCTypeWithLocalFunctions--")] class RUCTypeWithLocalFunctions { [ExpectedWarning ("IL2112", nameof (MethodWithLocalFunctions), "--RUCTypeWithLocalFunctions--", - ProducedBy = Tool.Trimmer)] + ProducedBy = Tool.Trimmer | Tool.NativeAot)] public void MethodWithLocalFunctions () { - [ExpectedWarning ("IL2112", "<" + nameof (MethodWithLocalFunctions) + ">", - ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] void LocalFunction () => MethodWithRequires (); - [ExpectedWarning ("IL2112", "<" + nameof (MethodWithLocalFunctions) + ">", - ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] static void StaticLocalFunction () => MethodWithRequires (); int i = 0; - [ExpectedWarning ("IL2112", "<" + nameof (MethodWithLocalFunctions) + ">", - ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] void LocalFunctionWithCapturedState () { i++; @@ -543,13 +519,7 @@ void LocalFunctionWithCapturedState () ProducedBy = Tool.Trimmer)] // Expect RUC warnings for static, compiler-generated code warnings for instance. [ExpectedWarning ("IL2026", nameof (RUCTypeWithLocalFunctions) + "()", "--RUCTypeWithLocalFunctions--")] - [ExpectedWarning ("IL2026", "<" + nameof (RUCTypeWithLocalFunctions.MethodWithLocalFunctions) + ">", "LocalFunctionWithCapturedState", - ProducedBy = Tool.Trimmer)] // displayclass ctor - [ExpectedWarning ("IL2026", "<" + nameof (RUCTypeWithLocalFunctions.MethodWithLocalFunctions) + ">", "StaticLocalFunction", - ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2026", "<" + nameof (RUCTypeWithLocalFunctions.MethodWithLocalFunctions) + ">", "LocalFunction", - ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2026", nameof (RUCTypeWithLocalFunctions.MethodWithLocalFunctions) + "()", ProducedBy = Tool.Trimmer | Tool.Analyzer)] + [ExpectedWarning ("IL2026", nameof (RUCTypeWithLocalFunctions.MethodWithLocalFunctions) + "()")] public static void Test (LocalFunctions test = null) { typeof (LocalFunctions).RequiresAll (); @@ -658,6 +628,121 @@ public static void Test () } } + class DelegateAccess + { + static void AnnotatedMethod ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] Type type) + { + } + + [ExpectedWarning ("IL2111", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + static void TestMethodThroughDelegate () + { + Action a = AnnotatedMethod; + } + + [ExpectedWarning ("IL2111", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + static void TestLambdaThroughDelegate () + { + Action a = ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] Type type) => { }; + a (null); + } + + [ExpectedWarning ("IL2111", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + static void TestLocalFunctionThroughDelegate () + { + Action a = LocalFunction; + a (null); + + void LocalFunction ([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] Type type) + { + } + } + + static void TestGenericLocalFunctionThroughDelegate () + { + Action a = LocalFunction; + a (); + + void LocalFunction <[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] T> () + { + } + } + + public static void Test () + { + TestMethodThroughDelegate (); + TestLambdaThroughDelegate (); + TestLocalFunctionThroughDelegate (); + TestGenericLocalFunctionThroughDelegate (); + } + } + + class DAMReflectionAccessToCompilerGeneratedCode + { + // ldftn access - this MUST warn since the action can be called without the annotation + [ExpectedWarning ("IL2111", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + static void Lambda () + { + Action a = ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] Type type) => { + type.GetMethods (); + }; + + a (typeof (string)); + } + + static void LambdaOnGeneric<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] T> () + { + Action a = () => { + typeof(T).GetMethods (); + }; + + a (); + } + + static void LocalFunction () + { + LocalFunctionInner (typeof (string)); + + static void LocalFunctionInner ([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] Type type) + { + type.GetMethods (); + } + } + + static void LocalFunctionOnGeneric<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] T>() + { + LocalFunctionInner (); + + static void LocalFunctionInner () + { + typeof(T).GetMethods (); + } + } + + static IEnumerable IteratorOnGeneric<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] T>() + { + yield return 0; + } + + static async Task AsyncOnGeneric<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] T> () + { + await Task.Delay (100); + } + + static async IAsyncEnumerable AsyncIteratorOnGeneric<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] T> () + { + yield return 0; + await Task.Delay (100); + } + + [ExpectedWarning ("IL2118", "<" + nameof (LambdaOnGeneric) + ">", ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2118", "<" + nameof (LocalFunctionOnGeneric) + ">", ProducedBy = Tool.Trimmer)] + public static void Test () + { + typeof (DAMReflectionAccessToCompilerGeneratedCode).RequiresAll (); + } + } + [RequiresUnreferencedCode ("--MethodWithRequires--")] [RequiresAssemblyFiles ("--MethodWithRequires--")] [RequiresDynamicCode ("--MethodWithRequires--")] @@ -685,5 +770,7 @@ static async Task MethodAsync () [DllImport ("Foo")] static extern void MethodTakingObject ([MarshalAs (UnmanagedType.IUnknown)] object obj); + + class TestType { } } } diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Reflection/TypeHierarchyReflectionWarnings.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Reflection/TypeHierarchyReflectionWarnings.cs index 087a11bc038a..6c37b7dd3fe1 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Reflection/TypeHierarchyReflectionWarnings.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Reflection/TypeHierarchyReflectionWarnings.cs @@ -3,8 +3,12 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Diagnostics.CodeAnalysis; +using System.Reflection; +using System.Runtime.CompilerServices; using System.Text; +using System.Threading.Tasks; using Mono.Linker.Tests.Cases.Expectations.Assertions; using Mono.Linker.Tests.Cases.Expectations.Helpers; using Mono.Linker.Tests.Cases.Expectations.Metadata; @@ -57,6 +61,9 @@ public static void Main () RUCOnVirtualOnAnnotatedBase.Test (); RUCOnVirtualOnAnnotatedBaseUsedByDerived.Test (); UseByDerived.Test (); + + CompilerGeneratedCodeRUC.Test (null); + CompilerGeneratedCodeDAM.Test (null); } [Kept] @@ -277,8 +284,7 @@ class AnnotatedInterfaces : RequiredInterface { [Kept] [KeptAttributeAttribute (typeof (RequiresUnreferencedCodeAttribute))] - // This should produce a warning: https://github.com/dotnet/linker/issues/2161 - [ExpectedWarning("IL2112", "--RUC on AnnotatedInterfaces.UnusedMethod--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL2112", "--RUC on AnnotatedInterfaces.UnusedMethod--")] [RequiresUnreferencedCode ("--RUC on AnnotatedInterfaces.UnusedMethod--")] public void RUCMethod () { } } @@ -426,7 +432,7 @@ class AnnotatedDerivedFromBase : Base [Kept] [KeptAttributeAttribute (typeof (RequiresUnreferencedCodeAttribute))] - // shouldn't warn because we warn on the base method instead + [ExpectedWarning ("IL2112", "--AnnotatedDerivedFromBase.RUCVirtualMethod--")] [RequiresUnreferencedCode ("--AnnotatedDerivedFromBase.RUCVirtualMethod--")] public override void RUCVirtualMethod () { } @@ -438,9 +444,12 @@ class AnnotatedDerivedFromBase : Base [Kept] [KeptBackingField] [KeptAttributeAttribute (typeof (DynamicallyAccessedMembersAttribute))] - // shouldn't warn because we warn on the base getter instead [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.NonPublicMethods)] - public override string DAMVirtualProperty { [Kept] get; } + public override string DAMVirtualProperty { + [Kept] + [ExpectedWarning ("IL2114", nameof (AnnotatedDerivedFromBase), nameof (DAMVirtualProperty))] + get; + } } @@ -463,7 +472,7 @@ class DerivedFromAnnotatedDerivedFromBase : AnnotatedDerivedFromBase [Kept] [KeptAttributeAttribute (typeof (RequiresUnreferencedCodeAttribute))] - // shouldn't warn because we warn on the base method instead + [ExpectedWarning ("IL2112", "--DerivedFromAnnotatedDerivedFromBase.RUCVirtualMethod--")] [RequiresUnreferencedCode ("--DerivedFromAnnotatedDerivedFromBase.RUCVirtualMethod--")] public override void RUCVirtualMethod () { } @@ -476,9 +485,12 @@ class DerivedFromAnnotatedDerivedFromBase : AnnotatedDerivedFromBase [Kept] [KeptBackingField] [KeptAttributeAttribute (typeof (DynamicallyAccessedMembersAttribute))] - // shouldn't warn because we warn on the base getter instead [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.NonPublicMethods)] - public override string DAMVirtualProperty { [Kept] get; } + public override string DAMVirtualProperty { + [Kept] + [ExpectedWarning ("IL2114", nameof (DerivedFromAnnotatedDerivedFromBase), nameof (DAMVirtualProperty))] + get; + } } [KeptMember (".ctor()")] @@ -629,8 +641,7 @@ public class Derived : Base [Kept] [KeptAttributeAttribute (typeof (RequiresUnreferencedCodeAttribute))] [RequiresUnreferencedCode ("--RUCOnVirtualMethodDerivedAnnotated.Derived.RUCVirtualMethod--")] - // https://github.com/dotnet/linker/issues/2815 - [ExpectedWarning ("IL2112", "--RUCOnVirtualMethodDerivedAnnotated.Derived.RUCVirtualMethod--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL2112", "--RUCOnVirtualMethodDerivedAnnotated.Derived.RUCVirtualMethod--")] public virtual void RUCVirtualMethod () { } } @@ -669,6 +680,7 @@ public class Derived : Base [Kept] [KeptAttributeAttribute (typeof (RequiresUnreferencedCodeAttribute))] [RequiresUnreferencedCode ("--RUCOnVirtualMethodDerivedAnnotated.Derived.RUCVirtualMethod--")] + [ExpectedWarning ("IL2112", "--RUCOnVirtualMethodDerivedAnnotated.Derived.RUCVirtualMethod--")] public override void RUCVirtualMethod () { } } @@ -712,6 +724,7 @@ public class Derived : Base [Kept] [KeptAttributeAttribute (typeof (RequiresUnreferencedCodeAttribute))] [RequiresUnreferencedCode ("--RUCOnVirtualMethodDerivedAnnotated.Derived.RUCVirtualMethod--")] + [ExpectedWarning ("IL2112", "--RUCOnVirtualMethodDerivedAnnotated.Derived.RUCVirtualMethod--")] public override void RUCVirtualMethod () { } } @@ -767,6 +780,7 @@ class Derived : AnnotatedBase [KeptAttributeAttribute (typeof (RequiresUnreferencedCodeAttribute))] [KeptAttributeAttribute (typeof (RequiresDynamicCodeAttribute))] [KeptAttributeAttribute (typeof (RequiresAssemblyFilesAttribute))] + [ExpectedWarning ("IL2112", "--Derived.VirtualMethodWithRequires--")] [RequiresUnreferencedCode ("--Derived.VirtualMethodWithRequires--")] [RequiresDynamicCode ("--Derived.VirtualMethodWithRequires--")] [RequiresAssemblyFiles ("--Derived.VirtualMethodWithRequires--")] @@ -846,5 +860,147 @@ public static void Test () derivedInstance.GetType ().RequiresNonPublicFields (); } } + + // This validates that marking compiler generated code via DAM-on-Type doesn't + // produce warnings about the compiler generated methods, even if they're in a RUC scope. + [Kept] + [KeptAttributeAttribute (typeof (DynamicallyAccessedMembersAttribute))] + [KeptMember (".ctor()")] + [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)] + class CompilerGeneratedCodeRUC + { + [Kept] + [ExpectedWarning ("IL2026", "LambdaWithRUC")] + static void LambdaWithRUC () + { + Action a = + [RequiresUnreferencedCode ("LambdaWithRUC")] + (Type type) => { type.GetMethods (); }; + + a (typeof (string)); + } + + [Kept] + [ExpectedWarning ("IL2026", "LocalFunctionWithRUC")] + static void LocalFunctionWithRUC () + { + LocalFunctionWithRUCInner (null); + + [RequiresUnreferencedCode ("LocalFunctionWithRUC")] + void LocalFunctionWithRUCInner (Type type) + { + type.GetMethods (); + } + } + + [Kept] + [KeptAttributeAttribute (typeof (IteratorStateMachineAttribute))] + [KeptAttributeAttribute (typeof (RequiresUnreferencedCodeAttribute))] + [RequiresUnreferencedCode ("IteratorWithRUC")] + [ExpectedWarning ("IL2112", "IteratorWithRUC")] + static IEnumerable IteratorWithRUC () + { + yield return 1; + yield return 0; + } + + [Kept] + [KeptAttributeAttribute (typeof (AsyncStateMachineAttribute))] + [KeptAttributeAttribute (typeof (RequiresUnreferencedCodeAttribute))] + [KeptAttributeAttribute (typeof (DebuggerStepThroughAttribute))] + [RequiresUnreferencedCode ("AsyncWithRUC")] + [ExpectedWarning ("IL2112", "AsyncWithRUC")] + static async Task AsyncWithRUC () + { + await Task.Delay (100); + } + + [Kept] + [KeptAttributeAttribute (typeof (AsyncIteratorStateMachineAttribute))] + [KeptAttributeAttribute (typeof (RequiresUnreferencedCodeAttribute))] + [RequiresUnreferencedCode ("AsyncIteratorWithRUC")] + [ExpectedWarning ("IL2112", "AsyncIteratorWithRUC")] + static async IAsyncEnumerable AsyncIteratorWithRUC () + { + await Task.Delay (100); + yield return 1; + } + + [Kept] + public static void Test (CompilerGeneratedCodeRUC instance) + { + instance.GetType ().RequiresAll (); + } + } + + [Kept] + [KeptAttributeAttribute (typeof (DynamicallyAccessedMembersAttribute))] + [KeptMember (".ctor()")] + [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)] + class CompilerGeneratedCodeDAM + { + [Kept] + [ExpectedWarning ("IL2111", nameof (LambdaWithDAM))] + static void LambdaWithDAM () + { + Action a = + ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] Type type) => { type.GetMethods (); }; + + a (typeof (string)); + } + + [Kept] + static void LocalFunctionWithDAM () + { + LocalFunctionWithDAMInner (typeof (string)); + + static void LocalFunctionWithDAMInner ([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] Type type) + { + type.GetMethods (); + } + } + + [Kept] + [KeptAttributeAttribute (typeof (IteratorStateMachineAttribute))] + [ExpectedWarning ("IL2119", nameof (IteratorWithGenericDAM), CompilerGeneratedCode = true, ProducedBy = Tool.Trimmer)] + static IEnumerable IteratorWithGenericDAM< + [KeptAttributeAttribute(typeof(DynamicallyAccessedMembersAttribute))] + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] T> () + { + foreach (MethodInfo m in typeof (T).GetMethods ()) + yield return m.IsPublic; + } + + [Kept] + [KeptAttributeAttribute (typeof (AsyncStateMachineAttribute))] + [KeptAttributeAttribute (typeof (DebuggerStepThroughAttribute))] + [ExpectedWarning ("IL2119", nameof (AsyncWithGenericDAM), CompilerGeneratedCode = true, ProducedBy = Tool.Trimmer)] + static async Task AsyncWithGenericDAM< + [KeptAttributeAttribute (typeof (DynamicallyAccessedMembersAttribute))] + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] T>() + { + await Task.Delay (100); + typeof (T).GetMethods (); + } + + [Kept] + [KeptAttributeAttribute (typeof (AsyncIteratorStateMachineAttribute))] + [ExpectedWarning("IL2119", nameof(AsyncIteratorWithGenericDAM), CompilerGeneratedCode = true, ProducedBy = Tool.Trimmer)] + static async IAsyncEnumerable AsyncIteratorWithGenericDAM< + [KeptAttributeAttribute(typeof(DynamicallyAccessedMembersAttribute))] + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] T>() + { + foreach (MethodInfo m in typeof (T).GetMethods ()) { + await Task.Delay (100); + yield return m.IsPublic; + } + } + + [Kept] + public static void Test (CompilerGeneratedCodeDAM instance) + { + instance.GetType ().RequiresAll (); + } + } } } diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/ReflectionAccessFromCompilerGeneratedCode.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/ReflectionAccessFromCompilerGeneratedCode.cs index f58b051b4a3e..6aa4bc0e7837 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/ReflectionAccessFromCompilerGeneratedCode.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/ReflectionAccessFromCompilerGeneratedCode.cs @@ -26,9 +26,6 @@ class ReflectionAccessFromStateMachine [ExpectedWarning ("IL2026", "--TypeWithMethodWithRequires.MethodWithRequires--", CompilerGeneratedCode = true)] [ExpectedWarning ("IL3002", "--TypeWithMethodWithRequires.MethodWithRequires--", CompilerGeneratedCode = true, ProducedBy = Tool.NativeAot)] [ExpectedWarning ("IL3050", "--TypeWithMethodWithRequires.MethodWithRequires--", CompilerGeneratedCode = true, ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2026", "--MethodWithLocalFunctionWithRUC.LocalFunction--", CompilerGeneratedCode = true, ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--MethodWithLocalFunctionWithRUC.LocalFunction--", CompilerGeneratedCode = true, ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--MethodWithLocalFunctionWithRUC.LocalFunction--", CompilerGeneratedCode = true, ProducedBy = Tool.NativeAot)] [ExpectedWarning ("IL2118", nameof (TypeWithMethodWithRequires.MethodWithLocalFunctionCallsRUC), "LocalFunction", CompilerGeneratedCode = true, ProducedBy = Tool.Trimmer)] [ExpectedWarning ("IL2111", nameof (TypeWithMethodWithRequires.MethodWithAnnotations), CompilerGeneratedCode = true)] @@ -50,9 +47,6 @@ static IEnumerable TestIteratorWithRUC () [ExpectedWarning ("IL2026", "--TypeWithMethodWithRequires.MethodWithRequires--", CompilerGeneratedCode = true)] [ExpectedWarning ("IL3002", "--TypeWithMethodWithRequires.MethodWithRequires--", CompilerGeneratedCode = true, ProducedBy = Tool.NativeAot)] [ExpectedWarning ("IL3050", "--TypeWithMethodWithRequires.MethodWithRequires--", CompilerGeneratedCode = true, ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2026", "--MethodWithLocalFunctionWithRUC.LocalFunction--", CompilerGeneratedCode = true, ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--MethodWithLocalFunctionWithRUC.LocalFunction--", CompilerGeneratedCode = true, ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--MethodWithLocalFunctionWithRUC.LocalFunction--", CompilerGeneratedCode = true, ProducedBy = Tool.NativeAot)] [ExpectedWarning ("IL2118", nameof (TypeWithMethodWithRequires.MethodWithLocalFunctionCallsRUC), "LocalFunction", CompilerGeneratedCode = true, ProducedBy = Tool.Trimmer)] [ExpectedWarning ("IL2111", nameof (TypeWithMethodWithRequires.MethodWithAnnotations), CompilerGeneratedCode = true)] @@ -79,7 +73,7 @@ static async void TestAsyncWithRUC () [ExpectedWarning ("IL3050", "--TestAsyncWithRUC--", ProducedBy = Tool.NativeAot | Tool.Analyzer)] public static void Test () { - TestIterator ().GetEnumerator ().MoveNext (); // Must actually une the enumerator, otherwise NativeAOT will trim the implementation + TestIterator ().GetEnumerator ().MoveNext (); // Must actually use the enumerator, otherwise NativeAOT will trim the implementation TestIteratorWithRUC (); TestAsync (); TestAsyncWithRUC (); @@ -93,9 +87,6 @@ static void TestLocalFunction () [ExpectedWarning ("IL2026", "--TypeWithMethodWithRequires.MethodWithRequires--")] [ExpectedWarning ("IL3002", "--TypeWithMethodWithRequires.MethodWithRequires--", ProducedBy = Tool.NativeAot)] [ExpectedWarning ("IL3050", "--TypeWithMethodWithRequires.MethodWithRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2026", "--MethodWithLocalFunctionWithRUC.LocalFunction--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--MethodWithLocalFunctionWithRUC.LocalFunction--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--MethodWithLocalFunctionWithRUC.LocalFunction--", ProducedBy = Tool.NativeAot)] [ExpectedWarning ("IL2118", nameof (TypeWithMethodWithRequires.MethodWithLocalFunctionCallsRUC), "LocalFunction", ProducedBy = Tool.Trimmer)] [ExpectedWarning ("IL2111", nameof (TypeWithMethodWithRequires.MethodWithAnnotations))] @@ -152,9 +143,6 @@ static void TestLambda () [ExpectedWarning ("IL2026", "--TypeWithMethodWithRequires.MethodWithRequires--")] [ExpectedWarning ("IL3002", "--TypeWithMethodWithRequires.MethodWithRequires--", ProducedBy = Tool.NativeAot)] [ExpectedWarning ("IL3050", "--TypeWithMethodWithRequires.MethodWithRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2026", "--MethodWithLocalFunctionWithRUC.LocalFunction--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--MethodWithLocalFunctionWithRUC.LocalFunction--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--MethodWithLocalFunctionWithRUC.LocalFunction--", ProducedBy = Tool.NativeAot)] [ExpectedWarning ("IL2118", nameof (TypeWithMethodWithRequires.MethodWithLocalFunctionCallsRUC), "LocalFunction", ProducedBy = Tool.Trimmer)] [ExpectedWarning ("IL2111", nameof (TypeWithMethodWithRequires.MethodWithAnnotations))] diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresAccessedThrough.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresAccessedThrough.cs index 15c0993c7a95..848d2b02669a 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresAccessedThrough.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresAccessedThrough.cs @@ -22,7 +22,6 @@ public static void Main () { TestRequiresOnlyThroughReflection (); AccessedThroughReflectionOnGenericType.Test (); - AccessedThroughGenericParameterAnnotation.Test (); AccessThroughSpecialAttribute.Test (); AccessThroughPInvoke.Test (); AccessThroughNewConstraint.Test (); @@ -31,6 +30,7 @@ public static void Main () AccessThroughNewConstraint.TestNewConstraintOnTypeParameterInAnnotatedMethod (); AccessThroughNewConstraint.TestNewConstraintOnTypeParameterInAnnotatedType (); AccessThroughLdToken.Test (); + AccessThroughDelegate.Test (); } class TestType { } @@ -74,59 +74,6 @@ public static void Test () } } - class AccessedThroughGenericParameterAnnotation - { - class TypeWithRequiresMethod - { - [RequiresUnreferencedCode("--AccessedThroughGenericParameterAnnotation.TypeWithRequiresMethod.MethodWhichRequires--")] - [RequiresDynamicCode ("--AccessedThroughGenericParameterAnnotation.TypeWithRequiresMethod.MethodWhichRequires--")] - [RequiresAssemblyFiles ("--AccessedThroughGenericParameterAnnotation.TypeWithRequiresMethod.MethodWhichRequires--")] - public static void MethodWhichRequires () { } - } - - class TypeWithPublicMethods<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] T> - { - public TypeWithPublicMethods () { } - } - - [ExpectedWarning ("IL2026", "--AccessedThroughGenericParameterAnnotation.TypeWithRequiresMethod.MethodWhichRequires--")] - [ExpectedWarning ("IL3002", "--AccessedThroughGenericParameterAnnotation.TypeWithRequiresMethod.MethodWhichRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--AccessedThroughGenericParameterAnnotation.TypeWithRequiresMethod.MethodWhichRequires--", ProducedBy = Tool.NativeAot)] - static void TestAccessOnGenericType () - { - new TypeWithPublicMethods (); - } - - static void MethodWithPublicMethods<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] T> () { } - - [ExpectedWarning ("IL2026", "--AccessedThroughGenericParameterAnnotation.TypeWithRequiresMethod.MethodWhichRequires--")] - [ExpectedWarning ("IL3002", "--AccessedThroughGenericParameterAnnotation.TypeWithRequiresMethod.MethodWhichRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--AccessedThroughGenericParameterAnnotation.TypeWithRequiresMethod.MethodWhichRequires--", ProducedBy = Tool.NativeAot)] - static void TestAccessOnGenericMethod () - { - MethodWithPublicMethods (); - } - - static void MethodWithPublicMethodsInference<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] T> (T instance) { } - - // https://github.com/dotnet/runtime/issues/86032 - // IL2026 should be produced by the analyzer as well, but it has a bug around inferred generic arguments - [ExpectedWarning ("IL2026", "--AccessedThroughGenericParameterAnnotation.TypeWithRequiresMethod.MethodWhichRequires--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--AccessedThroughGenericParameterAnnotation.TypeWithRequiresMethod.MethodWhichRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--AccessedThroughGenericParameterAnnotation.TypeWithRequiresMethod.MethodWhichRequires--", ProducedBy = Tool.NativeAot)] - static void TestAccessOnGenericMethodWithInferenceOnMethod () - { - MethodWithPublicMethodsInference (new TypeWithRequiresMethod ()); - } - - public static void Test () - { - TestAccessOnGenericType (); - TestAccessOnGenericMethod (); - TestAccessOnGenericMethodWithInferenceOnMethod (); - } - } - class AccessThroughSpecialAttribute { // https://github.com/dotnet/linker/issues/1873 @@ -284,10 +231,99 @@ class AccessThroughLdToken [ExpectedWarning ("IL3002", "--PropertyWithLdToken.get--", ProducedBy = Tool.NativeAot)] [ExpectedWarning ("IL3050", "--PropertyWithLdToken.get--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] [ExpectedWarning ("IL3050", "--PropertyWithLdToken.get--", ProducedBy = Tool.NativeAot)] - public static void Test () + static void TestPropertyLdToken () { Expression> getter = () => PropertyWithLdToken; } + + [RequiresUnreferencedCode ("Message for --MethodWithLdToken--")] + [RequiresAssemblyFiles ("Message for --MethodWithLdToken--")] + [RequiresDynamicCode ("Message for --MethodWithLdToken--")] + static void MethodWithLdToken () + { + } + + [ExpectedWarning ("IL2026", "--MethodWithLdToken--")] + [ExpectedWarning ("IL3002", "--MethodWithLdToken--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", "--MethodWithLdToken--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + static void TestMethodLdToken () + { + Expression e = () => MethodWithLdToken (); + } + + [RequiresUnreferencedCode ("--FieldWithLdToken--")] + [RequiresDynamicCode ("--FieldWithLdToken--")] + class FieldWithLdTokenType + { + public static int Field = 0; + } + + [ExpectedWarning ("IL2026", "--FieldWithLdToken--")] + [ExpectedWarning ("IL3050", "--FieldWithLdToken--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + static void TestFieldLdToken () + { + Expression> f = () => FieldWithLdTokenType.Field; + } + + public static void Test () + { + TestPropertyLdToken (); + TestMethodLdToken (); + TestFieldLdToken (); + } + } + + class AccessThroughDelegate + { + [RequiresUnreferencedCode ("Message for --MethodWithDelegate--")] + [RequiresAssemblyFiles ("Message for --MethodWithDelegate--")] + [RequiresDynamicCode ("Message for --MethodWithDelegate--")] + static void MethodWithDelegate () + { + } + + [ExpectedWarning ("IL2026", "--MethodWithDelegate--")] + [ExpectedWarning ("IL3002", "--MethodWithDelegate--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", "--MethodWithDelegate--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + static void TestMethodWithDelegate () + { + Action a = MethodWithDelegate; + } + + [ExpectedWarning ("IL2026", "--LambdaThroughDelegate--")] + [ExpectedWarning ("IL3002", "--LambdaThroughDelegate--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", "--LambdaThroughDelegate--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + static void LambdaThroughDelegate () + { + Action a = + [RequiresUnreferencedCode ("--LambdaThroughDelegate--")] + [RequiresAssemblyFiles ("--LambdaThroughDelegate--")] + [RequiresDynamicCode ("--LambdaThroughDelegate--")] + () => { }; + + a (); + } + + [ExpectedWarning ("IL2026", "--LocalFunctionThroughDelegate--")] + [ExpectedWarning ("IL3002", "--LocalFunctionThroughDelegate--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", "--LocalFunctionThroughDelegate--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + static void LocalFunctionThroughDelegate () + { + Action a = Local; + + [RequiresUnreferencedCode ("--LocalFunctionThroughDelegate--")] + [RequiresAssemblyFiles ("--LocalFunctionThroughDelegate--")] + [RequiresDynamicCode ("--LocalFunctionThroughDelegate--")] + void Local () + { } + } + + public static void Test () + { + TestMethodWithDelegate (); + LambdaThroughDelegate (); + LocalFunctionThroughDelegate (); + } } } } diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresAttributeMismatch.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresAttributeMismatch.cs index e5b28b192b76..6e2fcca2875d 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresAttributeMismatch.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresAttributeMismatch.cs @@ -22,7 +22,7 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability class RequiresAttributeMismatch { // General comment about IL3003 - // Analyzer looks at properties, events and method separately. So mistmatch on property level will be reported + // Analyzer looks at properties, events and methods separately. So mismatch on property level will be reported // only on the property and not on the accessors. And vice versa. // NativeAOT doesn't really see properties and events, only methods. So it is much easier to handle everything // on the method level. While it's a discrepancy in behavior, it's small and should have no adverse effects @@ -31,8 +31,6 @@ class RequiresAttributeMismatch // then both accessors will report IL3003 (the attribute on the property is treated as if it was specified // on all accessors, always). // This discrepancy is tracked by https://github.com/dotnet/runtime/issues/83235. - - // Base/Derived and Implementation/Interface differs between ILLink and analyzer https://github.com/dotnet/linker/issues/2533 [ExpectedWarning ("IL2026", "BaseClassWithRequires.VirtualPropertyAnnotationInAccesor.get")] [ExpectedWarning ("IL3002", "BaseClassWithRequires.VirtualPropertyAnnotationInAccesor.get", ProducedBy = Tool.NativeAot)] [ExpectedWarning ("IL3050", "BaseClassWithRequires.VirtualPropertyAnnotationInAccesor.get", ProducedBy = Tool.NativeAot)] @@ -42,11 +40,20 @@ class RequiresAttributeMismatch [ExpectedWarning ("IL2026", "BaseClassWithRequires.VirtualPropertyAnnotationInAccesor.get")] [ExpectedWarning ("IL3002", "BaseClassWithRequires.VirtualPropertyAnnotationInAccesor.get", ProducedBy = Tool.NativeAot)] [ExpectedWarning ("IL3050", "BaseClassWithRequires.VirtualPropertyAnnotationInAccesor.get", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2026", "DerivedClassWithRequires.VirtualPropertyAnnotationInAccesor.get", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2026", "DerivedClassWithAllWarnings.VirtualPropertyAnnotationInAccesor.set", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2026", "DerivedClassWithAllWarnings.VirtualPropertyAnnotationInProperty.get", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2026", "DerivedClassWithAllWarnings.VirtualPropertyAnnotationInProperty.set", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2026", "DerivedClassWithAllWarnings.VirtualPropertyAnnotationInPropertyAndAccessor.set", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2026", "DerivedClassWithRequires.VirtualPropertyAnnotationInAccesor.get")] + [ExpectedWarning ("IL3002", "DerivedClassWithRequires.VirtualPropertyAnnotationInAccesor.get", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "DerivedClassWithRequires.VirtualPropertyAnnotationInAccesor.get", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "DerivedClassWithRequires.VirtualPropertyAnnotationInProperty.get", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "DerivedClassWithRequires.VirtualPropertyAnnotationInProperty.set", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "DerivedClassWithAllWarnings.VirtualPropertyAnnotationInAccesor.get", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL2026", "DerivedClassWithAllWarnings.VirtualPropertyAnnotationInAccesor.set")] + [ExpectedWarning ("IL3002", "DerivedClassWithAllWarnings.VirtualPropertyAnnotationInAccesor.set", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL2026", "DerivedClassWithAllWarnings.VirtualPropertyAnnotationInProperty.get")] + [ExpectedWarning ("IL3002", "DerivedClassWithAllWarnings.VirtualPropertyAnnotationInProperty.get", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL2026", "DerivedClassWithAllWarnings.VirtualPropertyAnnotationInProperty.set")] + [ExpectedWarning ("IL3002", "DerivedClassWithAllWarnings.VirtualPropertyAnnotationInProperty.set", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL2026", "DerivedClassWithAllWarnings.VirtualPropertyAnnotationInPropertyAndAccessor.set")] + [ExpectedWarning ("IL3002", "DerivedClassWithAllWarnings.VirtualPropertyAnnotationInPropertyAndAccessor.set", ProducedBy = Tool.NativeAot)] [ExpectedWarning ("IL2026", "BaseClassWithRequires.VirtualMethod()")] [ExpectedWarning ("IL3002", "BaseClassWithRequires.VirtualMethod()", ProducedBy = Tool.NativeAot)] [ExpectedWarning ("IL3050", "BaseClassWithRequires.VirtualMethod()", ProducedBy = Tool.NativeAot)] @@ -56,7 +63,9 @@ class RequiresAttributeMismatch [ExpectedWarning ("IL2026", "BaseClassWithRequires.VirtualMethod()")] [ExpectedWarning ("IL3002", "BaseClassWithRequires.VirtualMethod()", ProducedBy = Tool.NativeAot)] [ExpectedWarning ("IL3050", "BaseClassWithRequires.VirtualMethod()", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2026", "DerivedClassWithRequires.VirtualMethod()", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2026", "DerivedClassWithRequires.VirtualMethod()")] + [ExpectedWarning ("IL3002", "DerivedClassWithRequires.VirtualMethod()", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "DerivedClassWithRequires.VirtualMethod()", ProducedBy = Tool.NativeAot)] [ExpectedWarning ("IL2026", "IBaseWithRequires.PropertyAnnotationInAccesor.get")] [ExpectedWarning ("IL3002", "IBaseWithRequires.PropertyAnnotationInAccesor.get", ProducedBy = Tool.NativeAot)] [ExpectedWarning ("IL3050", "IBaseWithRequires.PropertyAnnotationInAccesor.get", ProducedBy = Tool.NativeAot)] @@ -68,23 +77,23 @@ class RequiresAttributeMismatch [ExpectedWarning ("IL2026", "IBaseWithRequires.Method()")] [ExpectedWarning ("IL3002", "IBaseWithRequires.Method()", ProducedBy = Tool.NativeAot)] [ExpectedWarning ("IL3050", "IBaseWithRequires.Method()", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2026", "ImplementationClassWithRequires.Method()", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL2026", "ImplementationClassWithRequires.Method()")] [ExpectedWarning ("IL3002", "ImplementationClassWithRequires.Method()", ProducedBy = Tool.NativeAot)] [ExpectedWarning ("IL3050", "ImplementationClassWithRequires.Method()", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2026", "ImplementationClassWithRequires.PropertyAnnotationInAccesor.get", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL2026", "ImplementationClassWithRequires.PropertyAnnotationInAccesor.get")] [ExpectedWarning ("IL3002", "ImplementationClassWithRequires.PropertyAnnotationInAccesor.get", ProducedBy = Tool.NativeAot)] [ExpectedWarning ("IL3050", "ImplementationClassWithRequires.PropertyAnnotationInAccesor.get", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2026", "ImplementationClassWithRequires.PropertyAnnotationInPropertyAndAccessor.get", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL2026", "ImplementationClassWithRequires.PropertyAnnotationInPropertyAndAccessor.get")] [ExpectedWarning ("IL3002", "ImplementationClassWithRequires.PropertyAnnotationInPropertyAndAccessor.get", ProducedBy = Tool.NativeAot)] [ExpectedWarning ("IL3002", "ImplementationClassWithRequires.PropertyAnnotationInPropertyAndAccessor.set", ProducedBy = Tool.NativeAot)] [ExpectedWarning ("IL3002", "ImplementationClassWithRequires.PropertyAnnotationInProperty.get", ProducedBy = Tool.NativeAot)] [ExpectedWarning ("IL3002", "ImplementationClassWithRequires.PropertyAnnotationInProperty.set", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2026", "ImplementationClassWithoutRequires.PropertyAnnotationInPropertyAndAccessor.get", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL2026", "ImplementationClassWithoutRequires.PropertyAnnotationInPropertyAndAccessor.get")] [ExpectedWarning ("IL3002", "ImplementationClassWithoutRequires.PropertyAnnotationInPropertyAndAccessor.get", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2026", "ImplementationClassWithRequiresInSource.Method()", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL2026", "ImplementationClassWithRequiresInSource.Method()")] [ExpectedWarning ("IL3002", "ImplementationClassWithRequiresInSource.Method()", ProducedBy = Tool.NativeAot)] [ExpectedWarning ("IL3050", "ImplementationClassWithRequiresInSource.Method()", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2026", "ImplementationClassWithRequiresInSource.PropertyAnnotationInAccesor.get", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL2026", "ImplementationClassWithRequiresInSource.PropertyAnnotationInAccesor.get")] [ExpectedWarning ("IL3002", "ImplementationClassWithRequiresInSource.PropertyAnnotationInAccesor.get", ProducedBy = Tool.NativeAot)] [ExpectedWarning ("IL3050", "ImplementationClassWithRequiresInSource.PropertyAnnotationInAccesor.get", ProducedBy = Tool.NativeAot)] [ExpectedWarning ("IL3002", "ImplementationClassWithRequiresInSource.PropertyAnnotationInProperty.get", ProducedBy = Tool.NativeAot)] diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresInCompilerGeneratedCode.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresInCompilerGeneratedCode.cs index 06179031c754..37c9da005fb0 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresInCompilerGeneratedCode.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresInCompilerGeneratedCode.cs @@ -44,6 +44,8 @@ public static void Main () ComplexCases.AsyncBodyCallingMethodWithRequires.Test (); ComplexCases.GenericAsyncBodyCallingMethodWithRequires.Test (); ComplexCases.GenericAsyncEnumerableBodyCallingRequiresWithAnnotations.Test (); + + RUCOnDelegateCacheFields.Test (); } class WarnInIteratorBody @@ -1880,59 +1882,6 @@ static async void TestAsyncOnlyReferencedViaReflectionWhichShouldWarn () [ExpectedWarning ("IL2026", "--TestAsyncOnlyReferencedViaReflectionWhichShouldSuppress--")] [ExpectedWarning ("IL3002", "--TestAsyncOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.NativeAot)] [ExpectedWarning ("IL3050", "--TestAsyncOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.NativeAot)] - // Analyzer doesn't emit additional warnings about reflection access to the compiler-generated - // state machine members. - [ExpectedWarning ("IL2026", "--TestIteratorOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--TestIteratorOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TestIteratorOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.NativeAot)] - - // The MoveNext, Current.get and Reset methods produces warning in NativeAOT - // https://github.com/dotnet/runtime/issues/82447 - [ExpectedWarning ("IL2026", "--TestIteratorOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--TestIteratorOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TestIteratorOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2026", "--TestIteratorOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--TestIteratorOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TestIteratorOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2026", "--TestIteratorOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--TestIteratorOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TestIteratorOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2026", "--TestIteratorOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--TestIteratorOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TestIteratorOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2026", "--TestIteratorOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--TestIteratorOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TestIteratorOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2026", "--TestIteratorOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--TestIteratorOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TestIteratorOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2026", "--TestIteratorOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--TestIteratorOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TestIteratorOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2026", "--TestIteratorOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--TestIteratorOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TestIteratorOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2026", "--TestIteratorOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--TestIteratorOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TestIteratorOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.NativeAot)] -#if !RELEASE - [ExpectedWarning ("IL2026", "--TestAsyncOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--TestAsyncOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TestAsyncOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.NativeAot)] - // In debug mode, the async state machine is a class with a constructor, so a warning is emitted for the constructor. - // The MoveNext method is virtual, so doesn't warn either way. -#else - // In release mode, the async state machine is a struct which doesn't have a constructor, so no warning is emitted. -#endif - // The MoveNext method produces warning in NativeAOT - // https://github.com/dotnet/runtime/issues/82447 - [ExpectedWarning ("IL2026", "--TestAsyncOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--TestAsyncOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TestAsyncOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2026", "--TestAsyncOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--TestAsyncOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TestAsyncOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2118", nameof (StateMachinesOnlyReferencedViaReflection), "<" + nameof (TestAsyncOnlyReferencedViaReflectionWhichShouldWarn) + ">", "MoveNext()", ProducedBy = Tool.Trimmer)] [ExpectedWarning ("IL2118", nameof (StateMachinesOnlyReferencedViaReflection), "<" + nameof (TestIteratorOnlyReferencedViaReflectionWhichShouldWarn) + ">", "MoveNext()", @@ -2045,24 +1994,6 @@ void LocalFunction () [ExpectedWarning ("IL2026", "--TestLocalFunctionInMethodWithRequiresOnlyAccessedViaReflection--")] [ExpectedWarning ("IL3002", "--TestLocalFunctionInMethodWithRequiresOnlyAccessedViaReflection--", ProducedBy = Tool.NativeAot)] [ExpectedWarning ("IL3050", "--TestLocalFunctionInMethodWithRequiresOnlyAccessedViaReflection--", ProducedBy = Tool.NativeAot)] - // Trimming tools correctly emit warnings about reflection access to local functions with Requires - // or which inherit Requires from the containing method. The analyzer doesn't bind to local functions - // so does not warn here. - [ExpectedWarning ("IL2026", "--TestLocalFunctionWithRequires--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--TestLocalFunctionWithRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TestLocalFunctionWithRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2026", "--TestLocalFunctionWithRequiresOnlyAccessedViaReflection--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--TestLocalFunctionWithRequiresOnlyAccessedViaReflection--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TestLocalFunctionWithRequiresOnlyAccessedViaReflection--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2026", "--TestLocalFunctionWithClosureWithRequires--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--TestLocalFunctionWithClosureWithRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TestLocalFunctionWithClosureWithRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2026", "--TestLocalFunctionInMethodWithRequires--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--TestLocalFunctionInMethodWithRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TestLocalFunctionInMethodWithRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2026", "--TestLocalFunctionWithClosureInMethodWithRequires--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--TestLocalFunctionWithClosureInMethodWithRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TestLocalFunctionWithClosureInMethodWithRequires--", ProducedBy = Tool.NativeAot)] [ExpectedWarning ("IL2118", nameof (LocalFunctionsReferencedViaReflection), nameof (TestLocalFunctionInMethodWithRequiresOnlyAccessedViaReflection), ProducedBy = Tool.Trimmer)] static void TestAll () @@ -2080,22 +2011,6 @@ static void TestAll () [ExpectedWarning ("IL2026", "--TestLocalFunctionInMethodWithRequiresOnlyAccessedViaReflection--")] [ExpectedWarning ("IL3002", "--TestLocalFunctionInMethodWithRequiresOnlyAccessedViaReflection--", ProducedBy = Tool.NativeAot)] [ExpectedWarning ("IL3050", "--TestLocalFunctionInMethodWithRequiresOnlyAccessedViaReflection--", ProducedBy = Tool.NativeAot)] - // NonPublicMethods warns for local functions not emitted into display classes. - [ExpectedWarning ("IL2026", "--TestLocalFunctionWithRequires--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--TestLocalFunctionWithRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TestLocalFunctionWithRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2026", "--TestLocalFunctionWithRequiresOnlyAccessedViaReflection--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--TestLocalFunctionWithRequiresOnlyAccessedViaReflection--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TestLocalFunctionWithRequiresOnlyAccessedViaReflection--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2026", "--TestLocalFunctionWithClosureWithRequires--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--TestLocalFunctionWithClosureWithRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TestLocalFunctionWithClosureWithRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2026", "--TestLocalFunctionInMethodWithRequires--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--TestLocalFunctionInMethodWithRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TestLocalFunctionInMethodWithRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2026", "--TestLocalFunctionWithClosureInMethodWithRequires--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--TestLocalFunctionWithClosureInMethodWithRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TestLocalFunctionWithClosureInMethodWithRequires--", ProducedBy = Tool.NativeAot)] [ExpectedWarning ("IL2118", nameof (LocalFunctionsReferencedViaReflection), "<" + nameof (TestLocalFunctionInMethodWithRequiresOnlyAccessedViaReflection) + ">", ProducedBy = Tool.Trimmer)] static void TestNonPublicMethods () @@ -2173,21 +2088,6 @@ static void TestLambdaWithClosureInMethodWithRequires (int p = 0) [ExpectedWarning ("IL2026", "--TestLambdaWithClosureInMethodWithRequires--")] [ExpectedWarning ("IL3002", "--TestLambdaWithClosureInMethodWithRequires--", ProducedBy = Tool.NativeAot)] [ExpectedWarning ("IL3050", "--TestLambdaWithClosureInMethodWithRequires--", ProducedBy = Tool.NativeAot)] - // Trimming tools correctly emit warnings about reflection access to lambdas with Requires - // or which inherit Requires from the containing method. The analyzer doesn't bind to lambdas - // so does not warn here. - [ExpectedWarning ("IL2026", "--TestLambdaWithRequires--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--TestLambdaWithRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TestLambdaWithRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2026", "--TestLambdaWithClosureWithRequires--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--TestLambdaWithClosureWithRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TestLambdaWithClosureWithRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2026", "--TestLambdaInMethodWithRequires--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--TestLambdaInMethodWithRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TestLambdaInMethodWithRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2026", "--TestLambdaWithClosureInMethodWithRequires--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--TestLambdaWithClosureInMethodWithRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TestLambdaWithClosureInMethodWithRequires--", ProducedBy = Tool.NativeAot)] static void TestAll () { typeof (LambdasReferencedViaReflection).RequiresAll (); @@ -2200,7 +2100,6 @@ static void TestAll () [ExpectedWarning ("IL2026", "--TestLambdaWithClosureInMethodWithRequires--")] [ExpectedWarning ("IL3002", "--TestLambdaWithClosureInMethodWithRequires--", ProducedBy = Tool.NativeAot)] [ExpectedWarning ("IL3050", "--TestLambdaWithClosureInMethodWithRequires--", ProducedBy = Tool.NativeAot)] - // NonPublicMethods doesn't warn for lambdas emitted into display class types. static void TestNonPublicMethods () { typeof (LambdasReferencedViaReflection).RequiresNonPublicMethods (); @@ -2318,6 +2217,25 @@ class Disposable : IDisposable { public void Dispose () { } } static Task GetDisposableAsync () { return Task.FromResult (new Disposable ()); } } + class RUCOnDelegateCacheFields + { + [RequiresUnreferencedCode ("--RUCOnDelegateCacheFields.TargetType--")] + class TargetType + { + public static void Init () + { + var Action = () => { }; + } + } + + [ExpectedWarning ("IL2026", nameof (TargetType) + "()")] // .ctor + [ExpectedWarning ("IL2026", nameof (TargetType.Init) + "()")] // Init method + public static void Test () + { + typeof (TargetType).RequiresAll (); + } + } + static async Task MethodAsync () { return await Task.FromResult (0); diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresOnClass.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresOnClass.cs index 2ae2c7fb2002..24faa7879210 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresOnClass.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresOnClass.cs @@ -535,24 +535,18 @@ class ReflectionAccessOnMethod [ExpectedWarning ("IL3050", "BaseWithoutRequiresOnType.Method()", ProducedBy = Tool.NativeAot)] [ExpectedWarning ("IL2026", "BaseWithoutRequiresOnType.Method()")] [ExpectedWarning ("IL3050", "BaseWithoutRequiresOnType.Method()", ProducedBy = Tool.NativeAot)] - // https://github.com/dotnet/linker/issues/2533 - [ExpectedWarning ("IL2026", "DerivedWithRequiresOnType.Method()", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2026", "DerivedWithRequiresOnType.Method()")] + [ExpectedWarning ("IL3050", "DerivedWithRequiresOnType.Method()", ProducedBy = Tool.NativeAot)] [ExpectedWarning ("IL2026", "InterfaceWithoutRequires.Method(Int32)")] [ExpectedWarning ("IL3050", "InterfaceWithoutRequires.Method(Int32)", ProducedBy = Tool.NativeAot)] [ExpectedWarning ("IL2026", "InterfaceWithoutRequires.Method()")] [ExpectedWarning ("IL3050", "InterfaceWithoutRequires.Method()", ProducedBy = Tool.NativeAot)] [ExpectedWarning ("IL2026", "ImplementationWithRequiresOnType.Method()")] [ExpectedWarning ("IL3050", "ImplementationWithRequiresOnType.Method()", ProducedBy = Tool.NativeAot)] - // https://github.com/dotnet/linker/issues/2533 - // NativeAOT has a correct override resolution and in this case the method is not an override - so it should warn - [ExpectedWarning ("IL2026", "ImplementationWithRequiresOnType.Method(Int32)", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL2026", "ImplementationWithRequiresOnType.Method(Int32)")] [ExpectedWarning ("IL3050", "ImplementationWithRequiresOnType.Method(Int32)", ProducedBy = Tool.NativeAot)] - // ILLink incorrectly skips warnings for derived method, under the assumption that - // it will be covered by the base method. But in this case the base method - // is unannotated (and the mismatch produces no warning because the derived - // type has RUC). - // https://github.com/dotnet/linker/issues/2533 - [ExpectedWarning ("IL2026", "DerivedWithRequiresOnTypeOverBaseWithNoRequires.Method()", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2026", "DerivedWithRequiresOnTypeOverBaseWithNoRequires.Method()")] + [ExpectedWarning ("IL3050", "DerivedWithRequiresOnTypeOverBaseWithNoRequires.Method()", ProducedBy = Tool.NativeAot)] static void TestDAMAccess () { // Warns because BaseWithoutRequiresOnType.Method has Requires on the method @@ -814,6 +808,28 @@ static void TestDAMOnTypeAccessInRUCScope (DAMAnnotatedClassAccessedFromRUCScope instance.GetType ().GetMethod ("RUCMethod"); } + [RequiresUnreferencedCode ("--GenericTypeWithRequires--")] + [RequiresDynamicCode ("--GenericTypeWithRequires--")] + class GenericTypeWithRequires + { + public static int NonGenericField; + } + + // https://github.com/dotnet/runtime/issues/86633 - analyzer doesn't report this warning + [ExpectedWarning ("IL2026", "NonGenericField", "--GenericTypeWithRequires--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", "NonGenericField", "--GenericTypeWithRequires--", ProducedBy = Tool.NativeAot)] + static void TestDAMAccessOnOpenGeneric () + { + typeof (GenericTypeWithRequires<>).RequiresPublicFields (); + } + + [ExpectedWarning ("IL2026", "NonGenericField", "--GenericTypeWithRequires--")] + [ExpectedWarning ("IL3050", "NonGenericField", "--GenericTypeWithRequires--", ProducedBy = Tool.NativeAot)] + static void TestDAMAccessOnInstantiatedGeneric () + { + typeof (GenericTypeWithRequires).RequiresPublicFields (); + } + [ExpectedWarning ("IL2026", "--TestDAMOnTypeAccessInRUCScope--")] public static void Test () { @@ -822,6 +838,8 @@ public static void Test () TestDynamicDependencyAccess (); TestDAMOnTypeAccess (null); TestDAMOnTypeAccessInRUCScope (); + TestDAMAccessOnOpenGeneric (); + TestDAMAccessOnInstantiatedGeneric (); } } diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresOnVirtualsAndInterfaces.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresOnVirtualsAndInterfaces.cs index 5470aa117178..fa821b58e997 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresOnVirtualsAndInterfaces.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresOnVirtualsAndInterfaces.cs @@ -76,9 +76,6 @@ static void TestCallOnOverrideViaBase () tmp.VirtualMethodRequires (); } - // https://github.com/dotnet/runtime/issues/86008 - // This is the "direct reflection" case, which actually behaves differently from indirect (DAM annotation) - // in this case even trimmer will warn on both methods. [ExpectedWarning ("IL2026", "--BaseType.VirtualMethodRequires--")] [ExpectedWarning ("IL3002", "--BaseType.VirtualMethodRequires--", ProducedBy = Tool.NativeAot)] [ExpectedWarning ("IL3050", "--BaseType.VirtualMethodRequires--", ProducedBy = Tool.NativeAot)] @@ -96,13 +93,12 @@ static void TestDirectReflectionAccess () typeof(T).GetMethod("VirtualMethodRequires").Invoke(instance, Array.Empty ()); } - // https://github.com/dotnet/runtime/issues/86008 [ExpectedWarning ("IL2026", "--BaseType.VirtualMethodRequires--")] [ExpectedWarning ("IL3002", "--BaseType.VirtualMethodRequires--", ProducedBy = Tool.NativeAot)] [ExpectedWarning ("IL3050", "--BaseType.VirtualMethodRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2026", "--TypeWhichOverridesMethod.VirtualMethodRequires--", ProducedBy = Tool.Analyzer)] - //[ExpectedWarning ("IL3002", "--TypeWhichOverridesMethod.VirtualMethodRequires--", ProducedBy = Tool.NativeAot)] - //[ExpectedWarning ("IL3050", "--TypeWhichOverridesMethod.VirtualMethodRequires--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL2026", "--TypeWhichOverridesMethod.VirtualMethodRequires--")] + [ExpectedWarning ("IL3002", "--TypeWhichOverridesMethod.VirtualMethodRequires--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "--TypeWhichOverridesMethod.VirtualMethodRequires--", ProducedBy = Tool.NativeAot)] static void TestAnnotatedReflectionAccess() { CallMethodWithRequiresOnInstance(new TypeWhichOverridesMethod ()); @@ -209,9 +205,7 @@ static void TestDirectReflectionAccess () typeof (T).GetMethod ("MethodWithRequires").Invoke (new ImplementationClass (), Array.Empty ()); } - // https://github.com/dotnet/runtime/issues/86008 - // This is a bug in illink, the fact that there's no warning is an analysis hole - [ExpectedWarning ("IL2026", "--ImplementationClass.RequiresMethod--", ProducedBy = Tool.NativeAot | Tool.Analyzer)] + [ExpectedWarning ("IL2026", "--ImplementationClass.RequiresMethod--")] [ExpectedWarning ("IL3002", "--ImplementationClass.RequiresMethod--", ProducedBy = Tool.NativeAot)] [ExpectedWarning ("IL3050", "--ImplementationClass.RequiresMethod--", ProducedBy = Tool.NativeAot)] static void TestAnnotatedReflectionAccess () @@ -317,8 +311,7 @@ class Derived : Base // Reflection triggered warnings are not produced by analyzer for RDC/RAS [ExpectedWarning ("IL3002", "Message for --NewSlotVirtual.Base.RUCMethod--", ProducedBy = Tool.NativeAot)] [ExpectedWarning ("IL3050", "Message for --NewSlotVirtual.Base.RUCMethod--", ProducedBy = Tool.NativeAot)] - // https://github.com/dotnet/linker/issues/2815 - [ExpectedWarning ("IL2026", "Message for --NewSlotVirtual.Derived.RUCMethod--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL2026", "Message for --NewSlotVirtual.Derived.RUCMethod--")] // Reflection triggered warnings are not produced by analyzer for RDC/RAS [ExpectedWarning ("IL3002", "Message for --NewSlotVirtual.Derived.RUCMethod--", ProducedBy = Tool.NativeAot)] [ExpectedWarning ("IL3050", "Message for --NewSlotVirtual.Derived.RUCMethod--", ProducedBy = Tool.NativeAot)] diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresViaDataflow.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresViaDataflow.cs index 15dd829a93a1..a88250de5683 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresViaDataflow.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresViaDataflow.cs @@ -15,66 +15,142 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability [ExpectedNoWarnings] class RequiresViaDataflow { - // Base/Derived and Implementation/Interface differs between ILLink and analyzer https://github.com/dotnet/linker/issues/2533 - [ExpectedWarning ("IL2026", "--DynamicallyAccessedTypeWithRequires.MethodWithRequires--")] - [ExpectedWarning ("IL2026", "TypeWhichOverridesMethod.VirtualMethodRequires()", "--TypeWhichOverridesMethod.VirtualMethodRequires--", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2026", "BaseType.VirtualMethodRequires()", "--BaseType.VirtualMethodRequires--")] - [ExpectedWarning ("IL3002", "BaseType.VirtualMethodRequires()", "--BaseType.VirtualMethodRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "BaseType.VirtualMethodRequires()", "--BaseType.VirtualMethodRequires--", ProducedBy = Tool.NativeAot)] public static void Main () { - TestDynamicallyAccessedMembersWithRequires (typeof (DynamicallyAccessedTypeWithRequires)); - TestDynamicallyAccessedMembersWithRequires (typeof (TypeWhichOverridesMethod)); - TestRequiresInDynamicDependency (); + AnnotatedParameter.Test (); + AnnotatedGenericParameter.Test (); + DynamicDependency.Test (); } - class BaseType + class AnnotatedParameter { - [RequiresUnreferencedCode ("Message for --BaseType.VirtualMethodRequires--")] - [RequiresAssemblyFiles ("Message for --BaseType.VirtualMethodRequires--")] - [RequiresDynamicCode ("Message for --BaseType.VirtualMethodRequires--")] - public virtual void VirtualMethodRequires () + static void MethodWithAnnotatedParameter ( + [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] Type type) { } - } - class TypeWhichOverridesMethod : BaseType - { - [RequiresUnreferencedCode ("Message for --TypeWhichOverridesMethod.VirtualMethodRequires--")] - [RequiresAssemblyFiles ("Message for --TypeWhichOverridesMethod.VirtualMethodRequires--")] - [RequiresDynamicCode ("Message for --TypeWhichOverridesMethod.VirtualMethodRequires--")] - public override void VirtualMethodRequires () + public class DynamicallyAccessedTypeWithRequires { + [RequiresUnreferencedCode ("Message for --DynamicallyAccessedTypeWithRequires.MethodWithRequires--")] + public void MethodWithRequires () + { + } } - } - public class DynamicallyAccessedTypeWithRequires - { - [RequiresUnreferencedCode ("Message for --DynamicallyAccessedTypeWithRequires.MethodWithRequires--")] - public void MethodWithRequires () + [ExpectedWarning ("IL2026", "--DynamicallyAccessedTypeWithRequires.MethodWithRequires--")] + static void TestNonVirtualMethod () { + MethodWithAnnotatedParameter (typeof (DynamicallyAccessedTypeWithRequires)); } - } - static void TestDynamicallyAccessedMembersWithRequires ( - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] Type type) - { + class BaseType + { + [RequiresUnreferencedCode ("Message for --BaseType.VirtualMethodRequires--")] + [RequiresAssemblyFiles ("Message for --BaseType.VirtualMethodRequires--")] + [RequiresDynamicCode ("Message for --BaseType.VirtualMethodRequires--")] + public virtual void VirtualMethodRequires () + { + } + } + + class TypeWhichOverridesMethod : BaseType + { + [RequiresUnreferencedCode ("Message for --TypeWhichOverridesMethod.VirtualMethodRequires--")] + [RequiresAssemblyFiles ("Message for --TypeWhichOverridesMethod.VirtualMethodRequires--")] + [RequiresDynamicCode ("Message for --TypeWhichOverridesMethod.VirtualMethodRequires--")] + public override void VirtualMethodRequires () + { + } + } + + [ExpectedWarning ("IL2026", "TypeWhichOverridesMethod.VirtualMethodRequires()", "--TypeWhichOverridesMethod.VirtualMethodRequires--")] + [ExpectedWarning ("IL3002", "TypeWhichOverridesMethod.VirtualMethodRequires()", "--TypeWhichOverridesMethod.VirtualMethodRequires--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "TypeWhichOverridesMethod.VirtualMethodRequires()", "--TypeWhichOverridesMethod.VirtualMethodRequires--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL2026", "BaseType.VirtualMethodRequires()", "--BaseType.VirtualMethodRequires--")] + [ExpectedWarning ("IL3002", "BaseType.VirtualMethodRequires()", "--BaseType.VirtualMethodRequires--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "BaseType.VirtualMethodRequires()", "--BaseType.VirtualMethodRequires--", ProducedBy = Tool.NativeAot)] + static void TestOverriddenVirtualMethod () + { + MethodWithAnnotatedParameter (typeof (TypeWhichOverridesMethod)); + } + + public static void Test () + { + TestNonVirtualMethod (); + TestOverriddenVirtualMethod (); + } } - [RequiresUnreferencedCode ("Message for --RequiresInDynamicDependency--")] - [RequiresAssemblyFiles ("Message for --RequiresInDynamicDependency--")] - [RequiresDynamicCode ("Message for --RequiresInDynamicDependency--")] - static void RequiresInDynamicDependency () + class AnnotatedGenericParameter { + class TypeWithRequiresMethod + { + [RequiresUnreferencedCode ("--AccessedThroughGenericParameterAnnotation.TypeWithRequiresMethod.MethodWhichRequires--")] + [RequiresDynamicCode ("--AccessedThroughGenericParameterAnnotation.TypeWithRequiresMethod.MethodWhichRequires--")] + [RequiresAssemblyFiles ("--AccessedThroughGenericParameterAnnotation.TypeWithRequiresMethod.MethodWhichRequires--")] + public static void MethodWhichRequires () { } + } + + class TypeWithPublicMethods<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] T> + { + public TypeWithPublicMethods () { } + } + + [ExpectedWarning ("IL2026", "--AccessedThroughGenericParameterAnnotation.TypeWithRequiresMethod.MethodWhichRequires--")] + [ExpectedWarning ("IL3002", "--AccessedThroughGenericParameterAnnotation.TypeWithRequiresMethod.MethodWhichRequires--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "--AccessedThroughGenericParameterAnnotation.TypeWithRequiresMethod.MethodWhichRequires--", ProducedBy = Tool.NativeAot)] + static void TestAccessOnGenericType () + { + new TypeWithPublicMethods (); + } + + static void MethodWithPublicMethods<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] T> () { } + + [ExpectedWarning ("IL2026", "--AccessedThroughGenericParameterAnnotation.TypeWithRequiresMethod.MethodWhichRequires--")] + [ExpectedWarning ("IL3002", "--AccessedThroughGenericParameterAnnotation.TypeWithRequiresMethod.MethodWhichRequires--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "--AccessedThroughGenericParameterAnnotation.TypeWithRequiresMethod.MethodWhichRequires--", ProducedBy = Tool.NativeAot)] + static void TestAccessOnGenericMethod () + { + MethodWithPublicMethods (); + } + + static void MethodWithPublicMethodsInference<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] T> (T instance) { } + + // https://github.com/dotnet/runtime/issues/86032 + // IL2026 should be produced by the analyzer as well, but it has a bug around inferred generic arguments + [ExpectedWarning ("IL2026", "--AccessedThroughGenericParameterAnnotation.TypeWithRequiresMethod.MethodWhichRequires--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--AccessedThroughGenericParameterAnnotation.TypeWithRequiresMethod.MethodWhichRequires--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "--AccessedThroughGenericParameterAnnotation.TypeWithRequiresMethod.MethodWhichRequires--", ProducedBy = Tool.NativeAot)] + static void TestAccessOnGenericMethodWithInferenceOnMethod () + { + MethodWithPublicMethodsInference (new TypeWithRequiresMethod ()); + } + + public static void Test () + { + TestAccessOnGenericType (); + TestAccessOnGenericMethod (); + TestAccessOnGenericMethodWithInferenceOnMethod (); + } } - // https://github.com/dotnet/runtime/issues/83080 - Analyzer doesn't recognize DynamicDependency in any way - [ExpectedWarning ("IL2026", "--RequiresInDynamicDependency--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--RequiresInDynamicDependency--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--RequiresInDynamicDependency--", ProducedBy = Tool.NativeAot)] - [DynamicDependency ("RequiresInDynamicDependency")] - static void TestRequiresInDynamicDependency () + class DynamicDependency { + [RequiresUnreferencedCode ("Message for --RequiresInDynamicDependency--")] + [RequiresAssemblyFiles ("Message for --RequiresInDynamicDependency--")] + [RequiresDynamicCode ("Message for --RequiresInDynamicDependency--")] + static void RequiresInDynamicDependency () + { + } + + // https://github.com/dotnet/runtime/issues/83080 - Analyzer doesn't recognize DynamicDependency in any way + [ExpectedWarning ("IL2026", "--RequiresInDynamicDependency--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--RequiresInDynamicDependency--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "--RequiresInDynamicDependency--", ProducedBy = Tool.NativeAot)] + [DynamicDependency ("RequiresInDynamicDependency")] + public static void Test () + { + } } } } diff --git a/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/AssemblyChecker.cs b/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/AssemblyChecker.cs index 363c089f67f6..9431505a6ec2 100644 --- a/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/AssemblyChecker.cs +++ b/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/AssemblyChecker.cs @@ -248,7 +248,7 @@ protected virtual void VerifyTypeDefinitionKept (TypeDefinition original, TypeDe VerifyInterfaces (original, linked); VerifyPseudoAttributes (original, linked); - VerifyGenericParameters (original, linked); + VerifyGenericParameters (original, linked, compilerGenerated: false); VerifyCustomAttributes (original, linked); VerifySecurityAttributes (original, linked); @@ -537,12 +537,12 @@ protected virtual void VerifyMethodKept (MethodDefinition src, MethodDefinition Assert.Fail ($"Method `{src.FullName}' should have been kept"); VerifyPseudoAttributes (src, linked); - VerifyGenericParameters (src, linked); + VerifyGenericParameters (src, linked, compilerGenerated); if (!compilerGenerated) { VerifyCustomAttributes (src, linked); VerifyCustomAttributes (src.MethodReturnType, linked.MethodReturnType); } - VerifyParameters (src, linked); + VerifyParameters (src, linked, compilerGenerated); VerifySecurityAttributes (src, linked); VerifyArrayInitializers (src, linked); VerifyMethodBody (src, linked); @@ -1056,7 +1056,7 @@ void VerifyDelegateBackingFields (TypeDefinition src, TypeDefinition linked) } } - void VerifyGenericParameters (IGenericParameterProvider src, IGenericParameterProvider linked) + void VerifyGenericParameters (IGenericParameterProvider src, IGenericParameterProvider linked, bool compilerGenerated) { Assert.AreEqual (src.HasGenericParameters, linked.HasGenericParameters); if (src.HasGenericParameters) { @@ -1064,7 +1064,10 @@ void VerifyGenericParameters (IGenericParameterProvider src, IGenericParameterPr // TODO: Verify constraints var srcp = src.GenericParameters[i]; var lnkp = linked.GenericParameters[i]; - VerifyCustomAttributes (srcp, lnkp); + + if (!compilerGenerated) { + VerifyCustomAttributes (srcp, lnkp); + } if (checkNames) { if (srcp.CustomAttributes.Any (attr => attr.AttributeType.Name == nameof (RemovedNameValueAttribute))) { @@ -1078,7 +1081,7 @@ void VerifyGenericParameters (IGenericParameterProvider src, IGenericParameterPr } } - void VerifyParameters (IMethodSignature src, IMethodSignature linked) + void VerifyParameters (IMethodSignature src, IMethodSignature linked, bool compilerGenerated) { Assert.AreEqual (src.HasParameters, linked.HasParameters); if (src.HasParameters) { @@ -1086,7 +1089,9 @@ void VerifyParameters (IMethodSignature src, IMethodSignature linked) var srcp = src.Parameters[i]; var lnkp = linked.Parameters[i]; - VerifyCustomAttributes (srcp, lnkp); + if (!compilerGenerated) { + VerifyCustomAttributes (srcp, lnkp); + } if (checkNames) { if (srcp.CustomAttributes.Any (attr => attr.AttributeType.Name == nameof (RemovedNameValueAttribute)))