From 7606c21f15ae97998038926a6be3fc07046dc44d Mon Sep 17 00:00:00 2001 From: Vitek Karas <10670590+vitek-karas@users.noreply.github.com> Date: Tue, 7 Feb 2023 15:23:05 -0800 Subject: [PATCH] Revert "Fix generic parameter data flow validation in NativeAOT (#81532)" (#81783) This reverts commit e71a4fb10d7ea6b502dd5efe7a8fcefa2b9c1550. --- .../tools/Common/Compiler/DisplayNameHelpers.cs | 5 +- .../Compiler/Dataflow/FlowAnnotations.cs | 34 +- .../Compiler/Dataflow/GenericArgumentDataFlow.cs | 92 +- .../Compiler/Dataflow/MethodBodyScanner.cs | 57 +- .../Dataflow/ReflectionMethodBodyScanner.cs | 69 +- ...rimAnalysisGenericInstantiationAccessPattern.cs | 51 - .../Compiler/Dataflow/TrimAnalysisPatternStore.cs | 17 +- .../TrimAnalysisReflectionAccessPattern.cs | 20 +- .../DependencyAnalysis/ConstructedEETypeNode.cs | 4 +- .../DataflowAnalyzedTypeDefinitionNode.cs | 96 -- .../Compiler/DependencyAnalysis/EETypeNode.cs | 4 +- .../DependencyAnalysis/FieldMetadataNode.cs | 6 - .../GenericDefinitionEETypeNode.cs | 4 +- .../DependencyAnalysis/GenericDictionaryNode.cs | 2 + .../DependencyAnalysis/MethodMetadataNode.cs | 11 - .../Compiler/DependencyAnalysis/NodeFactory.cs | 12 - .../aot/ILCompiler.Compiler/Compiler/Logger.cs | 2 +- .../Compiler/MetadataManager.cs | 6 +- .../Compiler/UsageBasedMetadataManager.cs | 80 +- .../ILCompiler.Compiler/ILCompiler.Compiler.csproj | 2 - .../DataFlow/GenericParameterDataFlow.cs | 892 ------------- .../DataFlow/GenericParameterWarningLocation.cs | 1404 -------------------- .../TestCasesRunner/AssemblyChecker.cs | 39 + .../TestCasesRunner/AssemblyQualifiedToken.cs | 51 - .../TestCasesRunner/ResultChecker.cs | 11 +- .../DependencyInjectionPattern.cs | 146 -- .../nativeaot/SmokeTests/TrimmingBehaviors/Main.cs | 1 - .../TrimmingBehaviors/TrimmingBehaviors.csproj | 1 - 28 files changed, 177 insertions(+), 2942 deletions(-) delete mode 100644 src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/TrimAnalysisGenericInstantiationAccessPattern.cs delete mode 100644 src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/DataflowAnalyzedTypeDefinitionNode.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases/DataFlow/GenericParameterDataFlow.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases/DataFlow/GenericParameterWarningLocation.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/AssemblyQualifiedToken.cs delete mode 100644 src/tests/nativeaot/SmokeTests/TrimmingBehaviors/DependencyInjectionPattern.cs diff --git a/src/coreclr/tools/Common/Compiler/DisplayNameHelpers.cs b/src/coreclr/tools/Common/Compiler/DisplayNameHelpers.cs index 31ae384..df62b98 100644 --- a/src/coreclr/tools/Common/Compiler/DisplayNameHelpers.cs +++ b/src/coreclr/tools/Common/Compiler/DisplayNameHelpers.cs @@ -89,10 +89,7 @@ namespace ILCompiler if (method.Signature.Length > 0) { for (int i = 0; i < method.Signature.Length - 1; i++) - { - TypeDesc instantiatedType = method.Signature[i].InstantiateSignature(method.OwningType.Instantiation, method.Instantiation); - sb.Append(instantiatedType.GetDisplayNameWithoutNamespace()).Append(','); - } + sb.Append(method.Signature[i].GetDisplayNameWithoutNamespace()).Append(','); sb.Append(method.Signature[method.Signature.Length - 1].GetDisplayNameWithoutNamespace()); } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/FlowAnnotations.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/FlowAnnotations.cs index 5804b1b..e724d90 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/FlowAnnotations.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/FlowAnnotations.cs @@ -46,8 +46,8 @@ namespace ILLink.Shared.TrimAnalysis try { method = method.GetTypicalMethodDefinition(); - TypeAnnotations typeAnnotations = GetAnnotations(method.OwningType); - return typeAnnotations.HasGenericParameterAnnotation() || typeAnnotations.TryGetAnnotation(method, out _); + return GetAnnotations(method.OwningType).TryGetAnnotation(method, out var methodAnnotations) + && (methodAnnotations.ReturnParameterAnnotation != DynamicallyAccessedMemberTypes.None || methodAnnotations.ParameterAnnotations != null); } catch (TypeSystemException) { @@ -73,8 +73,7 @@ namespace ILLink.Shared.TrimAnalysis try { field = field.GetTypicalFieldDefinition(); - TypeAnnotations typeAnnotations = GetAnnotations(field.OwningType); - return typeAnnotations.HasGenericParameterAnnotation() || typeAnnotations.TryGetAnnotation(field, out _); + return GetAnnotations(field.OwningType).TryGetAnnotation(field, out _); } catch (TypeSystemException) { @@ -106,31 +105,6 @@ namespace ILLink.Shared.TrimAnalysis } } - public bool HasGenericParameterAnnotation(TypeDesc type) - { - try - { - return GetAnnotations(type.GetTypeDefinition()).HasGenericParameterAnnotation(); - } - catch (TypeSystemException) - { - return false; - } - } - - public bool HasGenericParameterAnnotation(MethodDesc method) - { - try - { - method = method.GetTypicalMethodDefinition(); - return GetAnnotations(method.OwningType).TryGetAnnotation(method, out var annotation) && annotation.GenericParameterAnnotations != null; - } - catch (TypeSystemException) - { - return false; - } - } - internal DynamicallyAccessedMemberTypes GetParameterAnnotation(ParameterProxy param) { MethodDesc method = param.Method.Method.GetTypicalMethodDefinition(); @@ -910,8 +884,6 @@ namespace ILLink.Shared.TrimAnalysis return false; } - - public bool HasGenericParameterAnnotation() => _genericParameterAnnotations != null; } private readonly struct MethodAnnotations diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/GenericArgumentDataFlow.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/GenericArgumentDataFlow.cs index a6b0e5f..555091d 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/GenericArgumentDataFlow.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/GenericArgumentDataFlow.cs @@ -18,83 +18,45 @@ using MultiValue = ILLink.Shared.DataFlow.ValueSet 0) - { - if (dependencies == null) - dependencies = reflectionMarker.Dependencies; - else - dependencies.AddRange(reflectionMarker.Dependencies); - } - } - - public static void ProcessGenericArgumentDataFlow(in DiagnosticContext diagnosticContext, ReflectionMarker reflectionMarker, TypeDesc type) - { - TypeDesc typeDefinition = type.GetTypeDefinition(); - if (typeDefinition != type) - { - ProcessGenericInstantiation(diagnosticContext, reflectionMarker, type.Instantiation, typeDefinition.Instantiation); - } - } - - public static void ProcessGenericArgumentDataFlow(in DiagnosticContext diagnosticContext, ReflectionMarker reflectionMarker, MethodDesc method) - { - MethodDesc typicalMethod = method.GetTypicalMethodDefinition(); - if (typicalMethod != method) - { - ProcessGenericInstantiation(diagnosticContext, reflectionMarker, method.Instantiation, typicalMethod.Instantiation); - } - - ProcessGenericArgumentDataFlow(diagnosticContext, reflectionMarker, method.OwningType); - } - - public static void ProcessGenericArgumentDataFlow(in DiagnosticContext diagnosticContext, ReflectionMarker reflectionMarker, FieldDesc field) - { - ProcessGenericArgumentDataFlow(diagnosticContext, reflectionMarker, field.OwningType); + _origin, + _logger.ShouldSuppressAnalysisWarningsForRequires(_origin.MemberDefinition, DiagnosticUtilities.RequiresUnreferencedCodeAttribute), + _logger); + return RequireDynamicallyAccessedMembers(diagnosticContext, genericArgumentValue, genericParameterValue, genericParameter.GetDisplayName()); } - private static void ProcessGenericInstantiation(in DiagnosticContext diagnosticContext, ReflectionMarker reflectionMarker, Instantiation instantiation, Instantiation typicalInstantiation) + private DependencyList RequireDynamicallyAccessedMembers( + in DiagnosticContext diagnosticContext, + in MultiValue value, + ValueWithDynamicallyAccessedMembers targetValue, + string reason) { - for (int i = 0; i < instantiation.Length; i++) - { - var genericParameter = (GenericParameterDesc)typicalInstantiation[i]; - if (reflectionMarker.Annotations.GetGenericParameterAnnotation(genericParameter) != default) - { - var genericParameterValue = reflectionMarker.Annotations.GetGenericParameterValue(genericParameter); - Debug.Assert(genericParameterValue.DynamicallyAccessedMemberTypes != DynamicallyAccessedMemberTypes.None); - MultiValue genericArgumentValue = reflectionMarker.Annotations.GetTypeValueFromGenericArgument(instantiation[i]); - var requireDynamicallyAccessedMembersAction = new RequireDynamicallyAccessedMembersAction(reflectionMarker, diagnosticContext, genericParameter.GetDisplayName()); - requireDynamicallyAccessedMembersAction.Invoke(genericArgumentValue, genericParameterValue); - } - } + var reflectionMarker = new ReflectionMarker(_logger, _factory, _annotations, typeHierarchyDataFlowOrigin: null, enabled: true); + var requireDynamicallyAccessedMembersAction = new RequireDynamicallyAccessedMembersAction(reflectionMarker, diagnosticContext, reason); + requireDynamicallyAccessedMembersAction.Invoke(value, targetValue); + return reflectionMarker.Dependencies; } } } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/MethodBodyScanner.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/MethodBodyScanner.cs index fa83eca..b9d09db 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/MethodBodyScanner.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/MethodBodyScanner.cs @@ -800,7 +800,7 @@ namespace ILCompiler.Dataflow StackSlot retValue = PopUnknown(currentStack, 1, methodBody, offset); // If the return value is a reference, treat it as the value itself for now // We can handle ref return values better later - ReturnValue = MultiValueLattice.Meet(ReturnValue, DereferenceValue(methodBody, offset, retValue.Value, locals, ref interproceduralState)); + ReturnValue = MultiValueLattice.Meet(ReturnValue, DereferenceValue(retValue.Value, locals, ref interproceduralState)); ValidateNoReferenceToReference(locals, methodBody, offset); } ClearStack(ref currentStack); @@ -947,24 +947,23 @@ namespace ILCompiler.Dataflow var nullableDam = new RuntimeTypeHandleForNullableValueWithDynamicallyAccessedMembers(new TypeProxy(type), new RuntimeTypeHandleForGenericParameterValue(genericParam)); currentStack.Push(new StackSlot(nullableDam)); - break; + return; case MetadataType underlyingType: var nullableType = new RuntimeTypeHandleForNullableSystemTypeValue(new TypeProxy(type), new SystemTypeValue(underlyingType)); currentStack.Push(new StackSlot(nullableType)); - break; + return; default: PushUnknown(currentStack); - break; + return; } } else { var typeHandle = new RuntimeTypeHandleValue(new TypeProxy(type)); currentStack.Push(new StackSlot(typeHandle)); + return; } } - - HandleTypeReflectionAccess(methodBody, offset, type); } else if (operand is MethodDesc method) { @@ -1027,7 +1026,7 @@ namespace ILCompiler.Dataflow StoreMethodLocalValue(locals, source, localReference.LocalIndex, curBasicBlock); break; case FieldReferenceValue fieldReference - when HandleGetField(method, offset, fieldReference.FieldDefinition).AsSingleValue() is FieldValue fieldValue: + when GetFieldValue(fieldReference.FieldDefinition).AsSingleValue() is FieldValue fieldValue: HandleStoreField(method, offset, fieldValue, source); break; case ParameterReferenceValue parameterReference @@ -1039,7 +1038,7 @@ namespace ILCompiler.Dataflow HandleStoreMethodReturnValue(method, offset, methodReturnValue, source); break; case FieldValue fieldValue: - HandleStoreField(method, offset, fieldValue, DereferenceValue(method, offset, source, locals, ref ipState)); + HandleStoreField(method, offset, fieldValue, DereferenceValue(source, locals, ref ipState)); break; case IValueWithStaticType valueWithStaticType: if (valueWithStaticType.StaticType is not null && FlowAnnotations.IsTypeInterestingForDataflow(valueWithStaticType.StaticType)) @@ -1058,25 +1057,7 @@ namespace ILCompiler.Dataflow } - /// - /// HandleGetField is called every time the scanner needs to represent a value of the field - /// either as a source or target. It is not called when just a reference to field is created, - /// But if such reference is dereferenced then it will get called. - /// It is NOT called for hoisted locals. - /// - /// - /// There should be no need to perform checks for hoisted locals. All of our reflection checks are based - /// on an assumption that problematic things happen because of running code. Doing things purely in the type system - /// (declaring new types which are never instantiated, declaring fields which are never assigned to, ...) - /// don't cause problems (or better way, they won't show observable behavioral differences). - /// Typically that would mean that accessing fields is also an uninteresting operation, unfortunately - /// static fields access can cause execution of static .cctor and that is running code -> possible problems. - /// So we have to track accesses in that case. - /// Hoisted locals are fields on closure classes/structs which should not have static .ctors, so we don't - /// need to track those. It makes the design a bit cleaner because hoisted locals are purely handled in here - /// and don't leak over to the reflection handling code in any way. - /// - protected abstract MultiValue HandleGetField(MethodIL methodBody, int offset, FieldDesc field); + protected abstract MultiValue GetFieldValue(FieldDesc field); private void ScanLdfld( MethodIL methodBody, @@ -1102,7 +1083,7 @@ namespace ILCompiler.Dataflow } else { - value = HandleGetField(methodBody, offset, field); + value = GetFieldValue(field); } currentStack.Push(new StackSlot(value)); } @@ -1138,7 +1119,7 @@ namespace ILCompiler.Dataflow return; } - foreach (var value in HandleGetField(methodBody, offset, field)) + foreach (var value in GetFieldValue(field)) { // GetFieldValue may return different node types, in which case they can't be stored to. // At least not yet. @@ -1146,7 +1127,7 @@ namespace ILCompiler.Dataflow continue; // Incomplete handling of ref fields -- if we're storing a reference to a value, pretend it's just the value - MultiValue valueToStore = DereferenceValue(methodBody, offset, valueToStoreSlot.Value, locals, ref interproceduralState); + MultiValue valueToStore = DereferenceValue(valueToStoreSlot.Value, locals, ref interproceduralState); HandleStoreField(methodBody, offset, fieldValue, valueToStore); } @@ -1182,12 +1163,7 @@ namespace ILCompiler.Dataflow return methodParams; } - internal MultiValue DereferenceValue( - MethodIL methodBody, - int offset, - MultiValue maybeReferenceValue, - ValueBasicBlockPair?[] locals, - ref InterproceduralState interproceduralState) + internal MultiValue DereferenceValue(MultiValue maybeReferenceValue, ValueBasicBlockPair?[] locals, ref InterproceduralState interproceduralState) { MultiValue dereferencedValue = MultiValueLattice.Top; foreach (var value in maybeReferenceValue) @@ -1199,7 +1175,7 @@ namespace ILCompiler.Dataflow dereferencedValue, CompilerGeneratedState.IsHoistedLocal(fieldReferenceValue.FieldDefinition) ? interproceduralState.GetHoistedLocal(new HoistedLocalKey(fieldReferenceValue.FieldDefinition)) - : HandleGetField(methodBody, offset, fieldReferenceValue.FieldDefinition)); + : GetFieldValue(fieldReferenceValue.FieldDefinition)); break; case ParameterReferenceValue parameterReferenceValue: dereferencedValue = MultiValue.Meet( @@ -1249,11 +1225,6 @@ namespace ILCompiler.Dataflow } /// - /// Called when type is accessed directly (basically only ldtoken) - /// - protected abstract void HandleTypeReflectionAccess(MethodIL methodBody, int offset, TypeDesc accessedType); - - /// /// Called to handle reflection access to a method without any other specifics (ldtoken or ldftn for example) /// protected abstract void HandleMethodReflectionAccess(MethodIL methodBody, int offset, MethodDesc accessedMethod); @@ -1289,7 +1260,7 @@ namespace ILCompiler.Dataflow var dereferencedMethodParams = new List(); foreach (var argument in methodArguments) - dereferencedMethodParams.Add(DereferenceValue(callingMethodBody, offset, argument, locals, ref interproceduralState)); + dereferencedMethodParams.Add(DereferenceValue(argument, locals, ref interproceduralState)); MultiValue methodReturnValue; bool handledFunction = HandleCall( callingMethodBody, diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReflectionMethodBodyScanner.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReflectionMethodBodyScanner.cs index 7db5379..7a73ba4 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReflectionMethodBodyScanner.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReflectionMethodBodyScanner.cs @@ -139,19 +139,7 @@ namespace ILCompiler.Dataflow private MethodParameterValue GetMethodParameterValue(ParameterProxy parameter, DynamicallyAccessedMemberTypes dynamicallyAccessedMemberTypes) => _annotations.GetMethodParameterValue(parameter, dynamicallyAccessedMemberTypes); - /// - /// HandleGetField is called every time the scanner needs to represent a value of the field - /// either as a source or target. It is not called when just a reference to field is created, - /// But if such reference is dereferenced then it will get called. - /// - protected override MultiValue HandleGetField(MethodIL methodBody, int offset, FieldDesc field) - { - _origin = _origin.WithInstructionOffset(methodBody, offset); - - ProcessGenericArgumentDataFlow(field); - - return _annotations.GetFieldValue(field); - } + protected override MultiValue GetFieldValue(FieldDesc field) => _annotations.GetFieldValue(field); private void HandleStoreValueWithDynamicallyAccessedMembers(MethodIL methodBody, int offset, ValueWithDynamicallyAccessedMembers targetValue, MultiValue sourceValue, string reason) { @@ -172,33 +160,16 @@ namespace ILCompiler.Dataflow protected override void HandleStoreMethodReturnValue(MethodIL methodBody, int offset, MethodReturnValue returnValue, MultiValue valueToStore) => HandleStoreValueWithDynamicallyAccessedMembers(methodBody, offset, returnValue, valueToStore, returnValue.Method.GetDisplayName()); - protected override void HandleTypeReflectionAccess(MethodIL methodBody, int offset, TypeDesc accessedType) - { - // Note that ldtoken alone is technically a reflection access to the type - // it doesn't lead to full reflection marking of the type - // since we implement full dataflow for type values and accesses to them. - _origin = _origin.WithInstructionOffset(methodBody, offset); - - // Only check for generic instantiations. - ProcessGenericArgumentDataFlow(accessedType); - } - protected override void HandleMethodReflectionAccess(MethodIL methodBody, int offset, MethodDesc accessedMethod) { _origin = _origin.WithInstructionOffset(methodBody, offset); - TrimAnalysisPatterns.Add(new TrimAnalysisReflectionAccessPattern(accessedMethod, _origin)); - - ProcessGenericArgumentDataFlow(accessedMethod); } protected override void HandleFieldReflectionAccess(MethodIL methodBody, int offset, FieldDesc accessedField) { _origin = _origin.WithInstructionOffset(methodBody, offset); - TrimAnalysisPatterns.Add(new TrimAnalysisReflectionAccessPattern(accessedField, _origin)); - - ProcessGenericArgumentDataFlow(accessedField); } public override bool HandleCall(MethodIL callingMethodBody, MethodDesc calledMethod, ILOpcode operation, int offset, ValueNodeList methodParams, out MultiValue methodReturnValue) @@ -230,8 +201,6 @@ namespace ILCompiler.Dataflow _origin )); - ProcessGenericArgumentDataFlow(calledMethod); - var diagnosticContext = new DiagnosticContext(_origin, diagnosticsEnabled: false, _logger); return HandleCall( callingMethodBody, @@ -665,42 +634,6 @@ namespace ILCompiler.Dataflow TrimAnalysisPatterns.Add(new TrimAnalysisAssignmentPattern(value, targetValue, origin, reason)); } - private void ProcessGenericArgumentDataFlow(MethodDesc method) - { - // We only need to validate static methods and then all generic methods - // Instance non-generic methods don't need validation because the creation of the instance - // is the place where the validation will happen. - if (!method.Signature.IsStatic && !method.HasInstantiation && !method.IsConstructor) - return; - - if ((method.HasInstantiation && _annotations.HasGenericParameterAnnotation(method)) || - (method.OwningType.HasInstantiation && _annotations.HasGenericParameterAnnotation(method.OwningType))) - { - TrimAnalysisPatterns.Add(new TrimAnalysisGenericInstantiationAccessPattern(method, _origin)); - } - } - - private void ProcessGenericArgumentDataFlow(FieldDesc field) - { - // We only need to validate static field accesses, instance field accesses don't need generic parameter validation - // because the create of the instance would do that instead. - if (!field.IsStatic) - return; - - if (field.OwningType.HasInstantiation && _annotations.HasGenericParameterAnnotation(field.OwningType)) - { - TrimAnalysisPatterns.Add(new TrimAnalysisGenericInstantiationAccessPattern(field, _origin)); - } - } - - private void ProcessGenericArgumentDataFlow(TypeDesc type) - { - if (type.HasInstantiation && _annotations.HasGenericParameterAnnotation(type)) - { - TrimAnalysisPatterns.Add(new TrimAnalysisGenericInstantiationAccessPattern(type, _origin)); - } - } - private static bool IsPInvokeDangerous(MethodDesc calledMethod, out bool comDangerousMethod, out bool aotUnsafeDelegate) { if (!calledMethod.IsPInvoke) diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/TrimAnalysisGenericInstantiationAccessPattern.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/TrimAnalysisGenericInstantiationAccessPattern.cs deleted file mode 100644 index a9a7bbb..0000000 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/TrimAnalysisGenericInstantiationAccessPattern.cs +++ /dev/null @@ -1,51 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using ILCompiler.Logging; -using ILLink.Shared.TrimAnalysis; -using Internal.TypeSystem; - -#nullable enable - -namespace ILCompiler.Dataflow -{ - public readonly record struct TrimAnalysisGenericInstantiationAccessPattern - { - public TypeSystemEntity Entity { init; get; } - public MessageOrigin Origin { init; get; } - - internal TrimAnalysisGenericInstantiationAccessPattern(TypeSystemEntity entity, MessageOrigin origin) - { - Entity = entity; - Origin = origin; - } - - // No Merge - there's nothing to merge since this pattern is uniquely identified by both the origin and the entity - // and there's only one way to "access" a generic instantiation. - - public void MarkAndProduceDiagnostics(ReflectionMarker reflectionMarker, Logger logger) - { - var diagnosticContext = new DiagnosticContext( - Origin, - logger.ShouldSuppressAnalysisWarningsForRequires(Origin.MemberDefinition, DiagnosticUtilities.RequiresUnreferencedCodeAttribute), - logger.ShouldSuppressAnalysisWarningsForRequires(Origin.MemberDefinition, DiagnosticUtilities.RequiresDynamicCodeAttribute), - logger.ShouldSuppressAnalysisWarningsForRequires(Origin.MemberDefinition, DiagnosticUtilities.RequiresAssemblyFilesAttribute), - logger); - - switch (Entity) - { - case TypeDesc type: - GenericArgumentDataFlow.ProcessGenericArgumentDataFlow(diagnosticContext, reflectionMarker, type); - break; - - case MethodDesc method: - GenericArgumentDataFlow.ProcessGenericArgumentDataFlow(diagnosticContext, reflectionMarker, method); - break; - - case FieldDesc field: - GenericArgumentDataFlow.ProcessGenericArgumentDataFlow(diagnosticContext, reflectionMarker, field); - break; - } - } - } -} diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/TrimAnalysisPatternStore.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/TrimAnalysisPatternStore.cs index a241f38..85c9aa7 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/TrimAnalysisPatternStore.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/TrimAnalysisPatternStore.cs @@ -16,7 +16,6 @@ namespace ILCompiler.Dataflow private readonly Dictionary<(MessageOrigin, bool), TrimAnalysisAssignmentPattern> AssignmentPatterns; private readonly Dictionary MethodCallPatterns; private readonly Dictionary<(MessageOrigin, TypeSystemEntity), TrimAnalysisReflectionAccessPattern> ReflectionAccessPatterns; - private readonly Dictionary<(MessageOrigin, TypeSystemEntity), TrimAnalysisGenericInstantiationAccessPattern> GenericInstantiations; private readonly ValueSetLattice Lattice; private readonly Logger _logger; @@ -25,7 +24,6 @@ namespace ILCompiler.Dataflow AssignmentPatterns = new Dictionary<(MessageOrigin, bool), TrimAnalysisAssignmentPattern>(); MethodCallPatterns = new Dictionary(); ReflectionAccessPatterns = new Dictionary<(MessageOrigin, TypeSystemEntity), TrimAnalysisReflectionAccessPattern>(); - GenericInstantiations = new Dictionary<(MessageOrigin, TypeSystemEntity), TrimAnalysisGenericInstantiationAccessPattern>(); Lattice = lattice; _logger = logger; } @@ -62,16 +60,8 @@ namespace ILCompiler.Dataflow { ReflectionAccessPatterns.TryAdd((pattern.Origin, pattern.Entity), pattern); - // No Merge - there's nothing to merge since this pattern is uniquely identified by both the origin and the entity - // and there's only one way to "access" a generic instantiation. - } - - public void Add(TrimAnalysisGenericInstantiationAccessPattern pattern) - { - GenericInstantiations.TryAdd((pattern.Origin, pattern.Entity), pattern); - - // No Merge - there's nothing to merge since this pattern is uniquely identified by both the origin and the entity - // and there's only one way to "access" a generic instantiation. + // No Merge - there's nothing to merge since this pattern is unequily identified by both the origin and the entity + // and there's only one way to "reflection access" an entity. } public void MarkAndProduceDiagnostics(ReflectionMarker reflectionMarker) @@ -84,9 +74,6 @@ namespace ILCompiler.Dataflow foreach (var pattern in ReflectionAccessPatterns.Values) pattern.MarkAndProduceDiagnostics(reflectionMarker, _logger); - - foreach (var pattern in GenericInstantiations.Values) - pattern.MarkAndProduceDiagnostics(reflectionMarker, _logger); } } } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/TrimAnalysisReflectionAccessPattern.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/TrimAnalysisReflectionAccessPattern.cs index 8f40b94..8a07621 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/TrimAnalysisReflectionAccessPattern.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/TrimAnalysisReflectionAccessPattern.cs @@ -1,12 +1,9 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System.Diagnostics; using ILCompiler.Logging; using Internal.TypeSystem; -#nullable enable - namespace ILCompiler.Dataflow { public readonly record struct TrimAnalysisReflectionAccessPattern @@ -20,25 +17,12 @@ namespace ILCompiler.Dataflow Origin = origin; } - // No Merge - there's nothing to merge since this pattern is uniquely identified by both the origin and the entity + // No Merge - there's nothing to merge since this pattern is unequily identified by both the origin and the entity // and there's only one way to "reflection access" an entity. public void MarkAndProduceDiagnostics(ReflectionMarker reflectionMarker, Logger logger) { - switch (Entity) - { - case MethodDesc method: - reflectionMarker.CheckAndWarnOnReflectionAccess(Origin, method); - break; - - case FieldDesc field: - reflectionMarker.CheckAndWarnOnReflectionAccess(Origin, field); - break; - - default: - Debug.Fail($"Unsupported entity for reflection access pattern: {Entity}"); - break; - } + reflectionMarker.CheckAndWarnOnReflectionAccess(Origin, Entity); } } } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ConstructedEETypeNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ConstructedEETypeNode.cs index 1e9e314..6d734d9 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ConstructedEETypeNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ConstructedEETypeNode.cs @@ -75,8 +75,8 @@ namespace ILCompiler.DependencyAnalysis } } - // Ask the metadata manager if we have any dependencies due to the presence of the EEType. - factory.MetadataManager.GetDependenciesDueToEETypePresence(ref dependencyList, factory, _type); + // Ask the metadata manager if we have any dependencies due to reflectability. + factory.MetadataManager.GetDependenciesDueToReflectability(ref dependencyList, factory, _type); factory.InteropStubManager.AddInterestingInteropConstructedTypeDependencies(ref dependencyList, factory, _type); diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/DataflowAnalyzedTypeDefinitionNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/DataflowAnalyzedTypeDefinitionNode.cs deleted file mode 100644 index b350186..0000000 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/DataflowAnalyzedTypeDefinitionNode.cs +++ /dev/null @@ -1,96 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Collections.Generic; -using System.Diagnostics; - -using Internal.TypeSystem; - -using ILCompiler.Dataflow; -using ILCompiler.DependencyAnalysisFramework; - -using ILLink.Shared.TrimAnalysis; -using ILCompiler.Logging; - -namespace ILCompiler.DependencyAnalysis -{ - public class DataflowAnalyzedTypeDefinitionNode : DependencyNodeCore - { - private readonly TypeDesc _typeDefinition; - - public DataflowAnalyzedTypeDefinitionNode(TypeDesc typeDefinition) - { - Debug.Assert(typeDefinition.IsTypeDefinition); - _typeDefinition = typeDefinition; - } - - public static void GetDependencies(ref DependencyList dependencies, NodeFactory factory, FlowAnnotations flowAnnotations, TypeDesc type) - { - bool foundGenericParameterAnnotation = false; - - type = type.GetTypeDefinition(); - - try - { - if (type.HasBaseType) - { - foundGenericParameterAnnotation |= IsTypeWithGenericParameterAnnotations(flowAnnotations, type.BaseType); - } - - if (type is MetadataType metadataType) - { - foreach (var interfaceType in metadataType.ExplicitlyImplementedInterfaces) - { - foundGenericParameterAnnotation |= IsTypeWithGenericParameterAnnotations(flowAnnotations, interfaceType); - } - } - } - catch (TypeSystemException) - { - // Wasn't able to do dataflow because of missing references or something like that. - // This likely won't compile either, so we don't care about missing dependencies. - } - - if (foundGenericParameterAnnotation) - { - dependencies ??= new DependencyList(); - dependencies.Add(factory.DataflowAnalyzedTypeDefinition(type), "Generic parameter dataflow"); - } - - static bool IsTypeWithGenericParameterAnnotations(FlowAnnotations flowAnnotations, TypeDesc type) - => type.HasInstantiation && flowAnnotations.HasGenericParameterAnnotation(type); - } - - public override IEnumerable GetStaticDependencies(NodeFactory factory) - { - DependencyList dependencies = null; - - if (_typeDefinition.HasBaseType) - { - GenericArgumentDataFlow.ProcessGenericArgumentDataFlow(ref dependencies, factory, new MessageOrigin(_typeDefinition), _typeDefinition.BaseType, _typeDefinition); - } - - if (_typeDefinition is MetadataType metadataType) - { - foreach (var interfaceType in metadataType.ExplicitlyImplementedInterfaces) - { - GenericArgumentDataFlow.ProcessGenericArgumentDataFlow(ref dependencies, factory, new MessageOrigin(_typeDefinition), interfaceType, _typeDefinition); - } - } - - return dependencies; - } - - protected override string GetName(NodeFactory factory) - { - return "Dataflow analysis for type definition " + _typeDefinition.ToString(); - } - - public override bool InterestingForDynamicDependencyAnalysis => false; - public override bool HasDynamicDependencies => false; - public override bool HasConditionalStaticDependencies => false; - public override bool StaticDependenciesAreComputed => true; - public override IEnumerable GetConditionalStaticDependencies(NodeFactory context) => null; - public override IEnumerable SearchDynamicDependencies(List> markedNodes, int firstNode, NodeFactory context) => null; - } -} diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/EETypeNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/EETypeNode.cs index 781a633..6f9aebf 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/EETypeNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/EETypeNode.cs @@ -596,8 +596,8 @@ namespace ILCompiler.DependencyAnalysis if (!ConstructedEETypeNode.CreationAllowed(_type)) { // If necessary MethodTable is the highest load level for this type, ask the metadata manager - // if we have any dependencies due to presence of the EEType. - factory.MetadataManager.GetDependenciesDueToEETypePresence(ref dependencies, factory, _type); + // if we have any dependencies due to reflectability. + factory.MetadataManager.GetDependenciesDueToReflectability(ref dependencies, factory, _type); // If necessary MethodTable is the highest load level, consider this a module use if(_type is MetadataType mdType) diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/FieldMetadataNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/FieldMetadataNode.cs index 325a7bb..3c98314 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/FieldMetadataNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/FieldMetadataNode.cs @@ -3,9 +3,7 @@ using System.Collections.Generic; -using ILCompiler.Dataflow; using ILCompiler.DependencyAnalysisFramework; -using ILCompiler.Logging; using Internal.TypeSystem; @@ -45,10 +43,6 @@ namespace ILCompiler.DependencyAnalysis if (_field is EcmaField ecmaField) { DynamicDependencyAttributesOnEntityNode.AddDependenciesDueToDynamicDependencyAttribute(ref dependencies, factory, ecmaField); - - // On a reflectable field, perform generic data flow for the field's type - // This is a compensation for the DI issue described in https://github.com/dotnet/runtime/issues/81358 - GenericArgumentDataFlow.ProcessGenericArgumentDataFlow(ref dependencies, factory, new MessageOrigin(_field), ecmaField.FieldType, ecmaField.OwningType); } return dependencies; diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericDefinitionEETypeNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericDefinitionEETypeNode.cs index 904475d..f6397e0 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericDefinitionEETypeNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericDefinitionEETypeNode.cs @@ -24,8 +24,8 @@ namespace ILCompiler.DependencyAnalysis { DependencyList dependencyList = null; - // Ask the metadata manager if we have any dependencies due to the presence of the EEType. - factory.MetadataManager.GetDependenciesDueToEETypePresence(ref dependencyList, factory, _type); + // Ask the metadata manager if we have any dependencies due to reflectability. + factory.MetadataManager.GetDependenciesDueToReflectability(ref dependencyList, factory, _type); return dependencyList; } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericDictionaryNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericDictionaryNode.cs index bcd3797..c6c63fa6 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericDictionaryNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericDictionaryNode.cs @@ -142,6 +142,8 @@ namespace ILCompiler.DependencyAnalysis } } + factory.MetadataManager.GetDependenciesForGenericDictionary(ref result, factory, _owningType); + return result; } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/MethodMetadataNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/MethodMetadataNode.cs index d29fefd..f52615d 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/MethodMetadataNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/MethodMetadataNode.cs @@ -3,9 +3,7 @@ using System.Collections.Generic; -using ILCompiler.Dataflow; using ILCompiler.DependencyAnalysisFramework; -using ILCompiler.Logging; using Internal.TypeSystem; @@ -53,15 +51,6 @@ namespace ILCompiler.DependencyAnalysis if (_method is EcmaMethod ecmaMethod) { DynamicDependencyAttributesOnEntityNode.AddDependenciesDueToDynamicDependencyAttribute(ref dependencies, factory, ecmaMethod); - - // On a reflectable method, perform generic data flow for the return type and all the parameter types - // This is a compensation for the DI issue described in https://github.com/dotnet/runtime/issues/81358 - GenericArgumentDataFlow.ProcessGenericArgumentDataFlow(ref dependencies, factory, new MessageOrigin(_method), _method.Signature.ReturnType, _method); - - foreach (TypeDesc parameterType in _method.Signature) - { - GenericArgumentDataFlow.ProcessGenericArgumentDataFlow(ref dependencies, factory, new MessageOrigin(_method), parameterType, _method); - } } return dependencies; diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NodeFactory.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NodeFactory.cs index 37400c7..ba0f5be 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NodeFactory.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NodeFactory.cs @@ -378,11 +378,6 @@ namespace ILCompiler.DependencyAnalysis return new DataflowAnalyzedMethodNode(il.MethodIL); }); - _dataflowAnalyzedTypeDefinitions = new NodeCache((TypeDesc type) => - { - return new DataflowAnalyzedTypeDefinitionNode(type); - }); - _dynamicDependencyAttributesOnEntities = new NodeCache((TypeSystemEntity entity) => { return new DynamicDependencyAttributesOnEntityNode(entity); @@ -714,13 +709,6 @@ namespace ILCompiler.DependencyAnalysis return _dataflowAnalyzedMethods.GetOrAdd(new MethodILKey(methodIL)); } - private NodeCache _dataflowAnalyzedTypeDefinitions; - - public DataflowAnalyzedTypeDefinitionNode DataflowAnalyzedTypeDefinition(TypeDesc type) - { - return _dataflowAnalyzedTypeDefinitions.GetOrAdd(type); - } - private NodeCache _dynamicDependencyAttributesOnEntities; public DynamicDependencyAttributesOnEntityNode DynamicDependencyAttributesOnEntity(TypeSystemEntity entity) diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Logger.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Logger.cs index 52bc74e..5ddb121 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Logger.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Logger.cs @@ -147,7 +147,7 @@ namespace ILCompiler internal bool IsWarningSuppressed(int code, MessageOrigin origin) { // This is causing too much noise - // https://github.com/dotnet/runtime/issues/81156 + // https://github.com/dotnet/runtimelab/issues/1591 if (code == 2110 || code == 2111 || code == 2113 || code == 2115) return true; diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/MetadataManager.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/MetadataManager.cs index f848eb3..19d8a8a 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/MetadataManager.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/MetadataManager.cs @@ -449,7 +449,7 @@ namespace ILCompiler /// /// This method is an extension point that can provide additional metadata-based dependencies to generated EETypes. /// - public virtual void GetDependenciesDueToEETypePresence(ref DependencyList dependencies, NodeFactory factory, TypeDesc type) + public void GetDependenciesDueToReflectability(ref DependencyList dependencies, NodeFactory factory, TypeDesc type) { MetadataCategory category = GetMetadataCategory(type); @@ -907,6 +907,10 @@ namespace ILCompiler { } + public virtual void GetDependenciesForGenericDictionary(ref DependencyList dependencies, NodeFactory factory, TypeDesc type) + { + } + public virtual void NoteOverridingMethod(MethodDesc baseMethod, MethodDesc overridingMethod) { } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/UsageBasedMetadataManager.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/UsageBasedMetadataManager.cs index 95f60ca..1209299 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/UsageBasedMetadataManager.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/UsageBasedMetadataManager.cs @@ -380,13 +380,6 @@ namespace ILCompiler return false; } - public override void GetDependenciesDueToEETypePresence(ref DependencyList dependencies, NodeFactory factory, TypeDesc type) - { - base.GetDependenciesDueToEETypePresence(ref dependencies, factory, type); - - DataflowAnalyzedTypeDefinitionNode.GetDependencies(ref dependencies, factory, FlowAnnotations, type); - } - public override bool HasConditionalDependenciesDueToEETypePresence(TypeDesc type) { // Note: these are duplicated with the checks in GetConditionalDependenciesDueToEETypePresence @@ -559,10 +552,27 @@ namespace ILCompiler if (scanReflection) { - if (methodIL != null && Dataflow.ReflectionMethodBodyScanner.RequiresReflectionMethodBodyScannerForMethodBody(FlowAnnotations, method)) + if (methodIL != null && FlowAnnotations.RequiresDataflowAnalysis(method)) { AddDataflowDependency(ref dependencies, factory, methodIL, "Method has annotated parameters"); } + + if ((method.HasInstantiation && !method.IsCanonicalMethod(CanonicalFormKind.Any))) + { + MethodDesc typicalMethod = method.GetTypicalMethodDefinition(); + Debug.Assert(typicalMethod != method); + + GetFlowDependenciesForInstantiation(ref dependencies, factory, method.Instantiation, typicalMethod.Instantiation, method); + } + + TypeDesc owningType = method.OwningType; + if (owningType.HasInstantiation && !owningType.IsCanonicalSubtype(CanonicalFormKind.Any)) + { + TypeDesc owningTypeDefinition = owningType.GetTypeDefinition(); + Debug.Assert(owningType != owningTypeDefinition); + + GetFlowDependenciesForInstantiation(ref dependencies, factory, owningType.Instantiation, owningTypeDefinition.Instantiation, owningType); + } } if (method.GetTypicalMethodDefinition() is Internal.TypeSystem.Ecma.EcmaMethod ecmaMethod) @@ -743,8 +753,52 @@ namespace ILCompiler return null; } + private void GetFlowDependenciesForInstantiation(ref DependencyList dependencies, NodeFactory factory, Instantiation instantiation, Instantiation typicalInstantiation, TypeSystemEntity source) + { + for (int i = 0; i < instantiation.Length; i++) + { + var genericParameter = (GenericParameterDesc)typicalInstantiation[i]; + if (FlowAnnotations.GetGenericParameterAnnotation(genericParameter) != default) + { + try + { + var deps = (new ILCompiler.Dataflow.GenericArgumentDataFlow(Logger, factory, FlowAnnotations, new Logging.MessageOrigin(source))).ProcessGenericArgumentDataFlow(genericParameter, instantiation[i]); + if (deps.Count > 0) + { + if (dependencies == null) + dependencies = deps; + else + dependencies.AddRange(deps); + } + } + catch (TypeSystemException) + { + // Wasn't able to do dataflow because of missing references or something like that. + // This likely won't compile either, so we don't care about missing dependencies. + } + } + } + } + public override void GetDependenciesForGenericDictionary(ref DependencyList dependencies, NodeFactory factory, MethodDesc method) { + TypeDesc owningType = method.OwningType; + + if (FlowAnnotations.HasAnyAnnotations(owningType)) + { + MethodDesc typicalMethod = method.GetTypicalMethodDefinition(); + Debug.Assert(typicalMethod != method); + + GetFlowDependenciesForInstantiation(ref dependencies, factory, method.Instantiation, typicalMethod.Instantiation, method); + + if (owningType.HasInstantiation) + { + // Since this also introduces a new type instantiation into the system, collect the dependencies for that too. + // We might not see the instantiated type elsewhere. + GetFlowDependenciesForInstantiation(ref dependencies, factory, owningType.Instantiation, owningType.GetTypeDefinition().Instantiation, method); + } + } + // Presence of code might trigger the reflectability dependencies. if ((_generationOptions & UsageBasedMetadataGenerationOptions.CreateReflectableArtifacts) != 0) { @@ -752,6 +806,16 @@ namespace ILCompiler } } + public override void GetDependenciesForGenericDictionary(ref DependencyList dependencies, NodeFactory factory, TypeDesc type) + { + if (FlowAnnotations.HasAnyAnnotations(type)) + { + TypeDesc typeDefinition = type.GetTypeDefinition(); + Debug.Assert(type != typeDefinition); + GetFlowDependenciesForInstantiation(ref dependencies, factory, type.Instantiation, typeDefinition.Instantiation, type); + } + } + public bool GeneratesAttributeMetadata(TypeDesc attributeType) { var ecmaType = attributeType.GetTypeDefinition() as EcmaType; diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/ILCompiler.Compiler.csproj b/src/coreclr/tools/aot/ILCompiler.Compiler/ILCompiler.Compiler.csproj index 631d804..0cc8c90 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/ILCompiler.Compiler.csproj +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/ILCompiler.Compiler.csproj @@ -379,7 +379,6 @@ - @@ -388,7 +387,6 @@ - diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases/DataFlow/GenericParameterDataFlow.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases/DataFlow/GenericParameterDataFlow.cs deleted file mode 100644 index dace9d1..0000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases/DataFlow/GenericParameterDataFlow.cs +++ /dev/null @@ -1,892 +0,0 @@ -// Copyright (c) .NET Foundation and contributors. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -using System; -using System.Diagnostics.CodeAnalysis; -using System.Reflection; -using Mono.Linker.Tests.Cases.Expectations.Assertions; -using Mono.Linker.Tests.Cases.Expectations.Helpers; -using BindingFlags = System.Reflection.BindingFlags; - -namespace Mono.Linker.Tests.Cases.DataFlow -{ - // NativeAOT differences in behavior: - // - // See the description on top of GenericParameterWarningLocation for the expected differences in behavior - // for NativeAOT. - // The tests affected by this are marked with "NativeAOT_StorageSpaceType" - // - - [SkipKeptItemsValidation] - [ExpectedNoWarnings] - public class GenericParameterDataFlow - { - public static void Main () - { - TestSingleGenericParameterOnType (); - TestMultipleGenericParametersOnType (); - TestBaseTypeGenericRequirements (); - TestDeepNestedTypesWithGenerics (); - TestInterfaceTypeGenericRequirements (); - TestTypeGenericRequirementsOnMembers (); - TestPartialInstantiationTypes (); - - TestSingleGenericParameterOnMethod (); - TestMultipleGenericParametersOnMethod (); - TestMethodGenericParametersViaInheritance (); - - TestNewConstraintSatisfiesParameterlessConstructor (); - TestStructConstraintSatisfiesParameterlessConstructor (); - TestUnmanagedConstraintSatisfiesParameterlessConstructor (); - - TestGenericParameterFlowsToField (); - TestGenericParameterFlowsToReturnValue (); - - TestNoWarningsInRUCMethod (); - TestNoWarningsInRUCType (); - } - - static void TestSingleGenericParameterOnType () - { - TypeRequiresNothing.Test (); - TypeRequiresPublicFields.Test (); - TypeRequiresPublicMethods.Test (); - TypeRequiresPublicFieldsPassThrough.Test (); - TypeRequiresNothingPassThrough.Test (); - } - - static void TestGenericParameterFlowsToReturnValue () - { - _ = TypeRequiresPublicFields.ReturnRequiresPublicFields (); - _ = TypeRequiresPublicFields.ReturnRequiresPublicMethods (); - _ = TypeRequiresPublicFields.ReturnRequiresNothing (); - } - - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] - static Type FieldRequiresPublicFields; - - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] - static Type FieldRequiresPublicMethods; - - static Type FieldRequiresNothing; - - - class TypeRequiresPublicFields< - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] T> - { - [ExpectedWarning ("IL2087", "'" + nameof (T) + "'", nameof (TypeRequiresPublicFields), nameof (DataFlowTypeExtensions.RequiresPublicMethods))] - public static void Test () - { - typeof (T).RequiresPublicFields (); - typeof (T).RequiresPublicMethods (); - typeof (T).RequiresNone (); - } - - [RequiresUnreferencedCode ("message")] - public static void RUCTest () - { - typeof (T).RequiresPublicMethods (); - } - - [ExpectedWarning ("IL2089", "'" + nameof (T) + "'", nameof (TypeRequiresPublicFields), nameof (FieldRequiresPublicMethods))] - public static void TestFields () - { - FieldRequiresPublicFields = typeof (T); - FieldRequiresPublicMethods = typeof (T); - FieldRequiresNothing = typeof (T); - } - - [return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] - public static Type ReturnRequiresPublicFields () - { - return typeof (T); - } - - [ExpectedWarning ("IL2088", "'" + nameof (T) + "'", nameof (TypeRequiresPublicFields), nameof (ReturnRequiresPublicMethods))] - [return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] - public static Type ReturnRequiresPublicMethods () - { - return typeof (T); - } - public static Type ReturnRequiresNothing () - { - return typeof (T); - } - } - - class TypeRequiresPublicMethods< - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] T> - { - [ExpectedWarning ("IL2087", nameof (DataFlowTypeExtensions.RequiresPublicFields))] - public static void Test () - { - typeof (T).RequiresPublicFields (); - typeof (T).RequiresPublicMethods (); - typeof (T).RequiresNone (); - } - } - - class TypeRequiresNothing - { - [ExpectedWarning ("IL2087", nameof (DataFlowTypeExtensions.RequiresPublicFields))] - [ExpectedWarning ("IL2087", nameof (DataFlowTypeExtensions.RequiresPublicMethods))] - public static void Test () - { - typeof (T).RequiresPublicFields (); - typeof (T).RequiresPublicMethods (); - typeof (T).RequiresNone (); - } - } - - class TypeRequiresPublicFieldsPassThrough< - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TSource> - { - [ExpectedWarning ("IL2091", nameof (TSource), - "Mono.Linker.Tests.Cases.DataFlow.GenericParameterDataFlow.TypeRequiresPublicFieldsPassThrough", - "T", - "Mono.Linker.Tests.Cases.DataFlow.GenericParameterDataFlow.TypeRequiresPublicMethods")] - public static void Test () - { - TypeRequiresPublicFields.Test (); - TypeRequiresPublicMethods.Test (); - TypeRequiresNothing.Test (); - } - } - - class TypeRequiresNothingPassThrough - { - [ExpectedWarning ("IL2091", nameof (TypeRequiresPublicFields))] - [ExpectedWarning ("IL2091", nameof (TypeRequiresPublicMethods))] - public static void Test () - { - TypeRequiresPublicFields.Test (); - TypeRequiresPublicMethods.Test (); - TypeRequiresNothing.Test (); - } - } - - static void TestBaseTypeGenericRequirements () - { - new DerivedTypeWithInstantiatedGenericOnBase (); - new DerivedTypeWithInstantiationOverSelfOnBase (); - new DerivedTypeWithOpenGenericOnBase (); - TestDerivedTypeWithOpenGenericOnBaseWithRUCOnBase (); - TestDerivedTypeWithOpenGenericOnBaseWithRUCOnDerived (); - new DerivedTypeWithOpenGenericOnBaseWithRequirements (); - } - - /// - /// Adding a comment to verify that analyzer doesn't null ref when trying to analyze - /// generic parameter in cref comments on a class - /// - /// - class GenericBaseTypeWithRequirements<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] T> - { - public GenericBaseTypeWithRequirements () - { - typeof (T).RequiresPublicFields (); - } - } - - class DerivedTypeWithInstantiatedGenericOnBase : GenericBaseTypeWithRequirements - { - } - - class DerivedTypeWithInstantiationOverSelfOnBase : GenericBaseTypeWithRequirements - { - } - - [ExpectedWarning ("IL2091", nameof (GenericBaseTypeWithRequirements))] - class DerivedTypeWithOpenGenericOnBase : GenericBaseTypeWithRequirements - { - // Analyzer does not see the base class constructor - [ExpectedWarning ("IL2091", nameof (GenericBaseTypeWithRequirements), ProducedBy = ProducedBy.Trimmer | ProducedBy.NativeAot)] - public DerivedTypeWithOpenGenericOnBase () { } - } - - static void TestDerivedTypeWithOpenGenericOnBaseWithRUCOnBase () - { - new DerivedTypeWithOpenGenericOnBaseWithRUCOnBase (); - } - - // https://github.com/dotnet/runtime/issues/81158 - [ExpectedWarning ("IL2109", nameof (BaseTypeWithOpenGenericDAMTAndRUC), ProducedBy = ProducedBy.Trimmer | ProducedBy.Analyzer)] - [ExpectedWarning ("IL2091", nameof (BaseTypeWithOpenGenericDAMTAndRUC))] - class DerivedTypeWithOpenGenericOnBaseWithRUCOnBase : BaseTypeWithOpenGenericDAMTAndRUC - { - [ExpectedWarning ("IL2091", nameof (DerivedTypeWithOpenGenericOnBaseWithRUCOnBase), ProducedBy = ProducedBy.Trimmer | ProducedBy.NativeAot)] - [ExpectedWarning ("IL2026", nameof (BaseTypeWithOpenGenericDAMTAndRUC), ProducedBy = ProducedBy.Trimmer | ProducedBy.NativeAot)] - public DerivedTypeWithOpenGenericOnBaseWithRUCOnBase () { } - } - - [RequiresUnreferencedCode ("RUC")] - class BaseTypeWithOpenGenericDAMTAndRUC<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)] T> { } - - - [ExpectedWarning ("IL2026", nameof (DerivedTypeWithOpenGenericOnBaseWithRUCOnDerived))] - static void TestDerivedTypeWithOpenGenericOnBaseWithRUCOnDerived () - { - new DerivedTypeWithOpenGenericOnBaseWithRUCOnDerived (); - } - [ExpectedWarning ("IL2091", nameof (BaseTypeWithOpenGenericDAMT))] - [RequiresUnreferencedCode ("RUC")] - class DerivedTypeWithOpenGenericOnBaseWithRUCOnDerived : BaseTypeWithOpenGenericDAMT - { - } - - class BaseTypeWithOpenGenericDAMT<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)] T> { } - - - class DerivedTypeWithOpenGenericOnBaseWithRequirements<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] T> - : GenericBaseTypeWithRequirements - { - } - - static void TestMultipleGenericParametersOnType () - { - MultipleTypesWithDifferentRequirements.TestMultiple (); - MultipleTypesWithDifferentRequirements.TestFields (); - MultipleTypesWithDifferentRequirements.TestMethods (); - MultipleTypesWithDifferentRequirements.TestBoth (); - MultipleTypesWithDifferentRequirements.TestNothing (); - } - - class MultipleTypesWithDifferentRequirements< - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TFields, - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TMethods, - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.PublicMethods)] TBoth, - TNothing> - { - public static void TestMultiple () - { - typeof (TFields).RequiresPublicFields (); - typeof (TMethods).RequiresPublicMethods (); - typeof (TBoth).RequiresPublicFields (); - typeof (TBoth).RequiresPublicMethods (); - typeof (TFields).RequiresNone (); - typeof (TMethods).RequiresNone (); - typeof (TBoth).RequiresNone (); - typeof (TNothing).RequiresNone (); - } - - [ExpectedWarning ("IL2087", nameof (DataFlowTypeExtensions.RequiresPublicMethods))] - public static void TestFields () - { - typeof (TFields).RequiresPublicFields (); - typeof (TFields).RequiresPublicMethods (); - typeof (TFields).RequiresNone (); - } - - [ExpectedWarning ("IL2087", nameof (DataFlowTypeExtensions.RequiresPublicFields))] - public static void TestMethods () - { - typeof (TMethods).RequiresPublicFields (); - typeof (TMethods).RequiresPublicMethods (); - typeof (TMethods).RequiresNone (); - } - - public static void TestBoth () - { - typeof (TBoth).RequiresPublicFields (); - typeof (TBoth).RequiresPublicMethods (); - typeof (TBoth).RequiresNone (); - } - - [ExpectedWarning ("IL2087", nameof (DataFlowTypeExtensions.RequiresPublicFields))] - [ExpectedWarning ("IL2087", nameof (DataFlowTypeExtensions.RequiresPublicMethods))] - public static void TestNothing () - { - typeof (TNothing).RequiresPublicFields (); - typeof (TNothing).RequiresPublicMethods (); - typeof (TNothing).RequiresNone (); - } - } - - static void TestDeepNestedTypesWithGenerics () - { - RootTypeWithRequirements.InnerTypeWithNoAddedGenerics.TestAccess (); - } - - class RootTypeWithRequirements<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TRoot> - { - public class InnerTypeWithNoAddedGenerics - { - [ExpectedWarning ("IL2087", nameof (TRoot), - "Mono.Linker.Tests.Cases.DataFlow.GenericParameterDataFlow.RootTypeWithRequirements", - "type", - "DataFlowTypeExtensions.RequiresPublicMethods(Type)")] - public static void TestAccess () - { - typeof (TRoot).RequiresPublicFields (); - typeof (TRoot).RequiresPublicMethods (); - } - } - } - - static void TestInterfaceTypeGenericRequirements () - { - IGenericInterfaceTypeWithRequirements instance = new InterfaceImplementationTypeWithInstantiatedGenericOnBase (); - new InterfaceImplementationTypeWithInstantiationOverSelfOnBase (); - new InterfaceImplementationTypeWithOpenGenericOnBase (); - new InterfaceImplementationTypeWithOpenGenericOnBaseWithRequirements (); - - RecursiveGenericWithInterfacesRequirement.Test (); - } - - interface IGenericInterfaceTypeWithRequirements<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] T> - { - } - - class InterfaceImplementationTypeWithInstantiatedGenericOnBase : IGenericInterfaceTypeWithRequirements - { - } - - interface IGenericInterfaceTypeWithRequiresAll<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)] T> - { - } - - class InterfaceImplementationTypeWithInstantiationOverSelfOnBase : IGenericInterfaceTypeWithRequiresAll - { - } - - [ExpectedWarning ("IL2091", nameof (IGenericInterfaceTypeWithRequirements))] - class InterfaceImplementationTypeWithOpenGenericOnBase : IGenericInterfaceTypeWithRequirements - { - } - class InterfaceImplementationTypeWithOpenGenericOnBaseWithRequirements<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] T> - : IGenericInterfaceTypeWithRequirements - { - } - - class RecursiveGenericWithInterfacesRequirement - { - interface IFace<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.Interfaces)] T> - { - } - - class TestType : IFace - { - } - - public static void Test () - { - var a = typeof (IFace); - var t = new TestType (); - } - } - - static void TestTypeGenericRequirementsOnMembers () - { - // Basically just root everything we need to test - var instance = new TypeGenericRequirementsOnMembers (); - - _ = instance.PublicFieldsField; - _ = instance.PublicMethodsField; - - _ = instance.PublicFieldsProperty; - instance.PublicFieldsProperty = null; - _ = instance.PublicMethodsProperty; - instance.PublicMethodsProperty = null; - - instance.PublicFieldsMethodParameter (null); - instance.PublicMethodsMethodParameter (null); - - instance.PublicFieldsMethodReturnValue (); - instance.PublicMethodsMethodReturnValue (); - - instance.PublicFieldsMethodLocalVariable (); - instance.PublicMethodsMethodLocalVariable (); - } - - class TypeGenericRequirementsOnMembers<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TOuter> - { - public TypeRequiresPublicFields PublicFieldsField; - - [ExpectedWarning ("IL2091", nameof (TypeRequiresPublicMethods), ProducedBy = ProducedBy.Trimmer | ProducedBy.Analyzer)] // NativeAOT_StorageSpaceType - public TypeRequiresPublicMethods PublicMethodsField; - - public TypeRequiresPublicFields PublicFieldsProperty { - get; - set; - } - - [ExpectedWarning ("IL2091", nameof (TypeGenericRequirementsOnMembers), ProducedBy = ProducedBy.Analyzer)] - public TypeRequiresPublicMethods PublicMethodsProperty { - [ExpectedWarning ("IL2091", nameof (TypeRequiresPublicMethods), ProducedBy = ProducedBy.Trimmer)] // NativeAOT_StorageSpaceType - get => null; - [ExpectedWarning ("IL2091", nameof (TypeRequiresPublicMethods), ProducedBy = ProducedBy.Trimmer)] // NativeAOT_StorageSpaceType - set { } - } - - public void PublicFieldsMethodParameter (TypeRequiresPublicFields param) { } - [ExpectedWarning ("IL2091", nameof (TypeRequiresPublicMethods), ProducedBy = ProducedBy.Trimmer | ProducedBy.Analyzer)] // NativeAOT_StorageSpaceType - public void PublicMethodsMethodParameter (TypeRequiresPublicMethods param) { } - - public TypeRequiresPublicFields PublicFieldsMethodReturnValue () { return null; } - - [ExpectedWarning ("IL2091", nameof (TypeRequiresPublicMethods), ProducedBy = ProducedBy.Trimmer)] // NativeAOT_StorageSpaceType - [ExpectedWarning ("IL2091", nameof (TypeRequiresPublicMethods), ProducedBy = ProducedBy.Trimmer | ProducedBy.Analyzer)] // NativeAOT_StorageSpaceType - public TypeRequiresPublicMethods PublicMethodsMethodReturnValue () { return null; } - - public void PublicFieldsMethodLocalVariable () - { - TypeRequiresPublicFields t = null; - } - - [ExpectedWarning ("IL2091", nameof (TypeRequiresPublicMethods), ProducedBy = ProducedBy.Trimmer | ProducedBy.Analyzer)] // NativeAOT_StorageSpaceType - public void PublicMethodsMethodLocalVariable () - { - TypeRequiresPublicMethods t = null; - } - } - - static void TestPartialInstantiationTypes () - { - _ = new PartialyInstantiatedFields (); - _ = new FullyInstantiatedOverPartiallyInstantiatedFields (); - _ = new PartialyInstantiatedMethods (); - _ = new FullyInstantiatedOverPartiallyInstantiatedMethods (); - } - - class BaseForPartialInstantiation< - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TFields, - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TMethods> - { - } - - class PartialyInstantiatedFields<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TOuter> - : BaseForPartialInstantiation - { - } - - class FullyInstantiatedOverPartiallyInstantiatedFields - : PartialyInstantiatedFields - { - } - - [ExpectedWarning ("IL2091", nameof (BaseForPartialInstantiation), "'TMethods'")] - class PartialyInstantiatedMethods<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TOuter> - : BaseForPartialInstantiation - { - // Analyzer does not see the base class constructor - [ExpectedWarning ("IL2091", nameof (BaseForPartialInstantiation), "'TMethods'", ProducedBy = ProducedBy.Trimmer | ProducedBy.NativeAot)] - public PartialyInstantiatedMethods () { } - } - - class FullyInstantiatedOverPartiallyInstantiatedMethods - : PartialyInstantiatedMethods - { - } - - static void TestSingleGenericParameterOnMethod () - { - MethodRequiresPublicFields (); - MethodRequiresPublicMethods (); - MethodRequiresNothing (); - MethodRequiresPublicFieldsPassThrough (); - MethodRequiresNothingPassThrough (); - } - - /// - /// Adding a comment to verify that analyzer doesn't null ref when trying to analyze - /// generic parameter comments on a method - /// - /// - [ExpectedWarning ("IL2087", nameof (DataFlowTypeExtensions.RequiresPublicMethods))] - static void MethodRequiresPublicFields< - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] T> () - { - typeof (T).RequiresPublicFields (); - typeof (T).RequiresPublicMethods (); - typeof (T).RequiresNone (); - } - - [ExpectedWarning ("IL2087", nameof (DataFlowTypeExtensions.RequiresPublicFields))] - static void MethodRequiresPublicMethods< - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] T> () - { - typeof (T).RequiresPublicFields (); - typeof (T).RequiresPublicMethods (); - typeof (T).RequiresNone (); - } - - [RequiresUnreferencedCode ("message")] - static void RUCMethodRequiresPublicMethods< - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] T> () - { - typeof (T).RequiresPublicFields (); - } - - [ExpectedWarning ("IL2087", nameof (DataFlowTypeExtensions.RequiresPublicFields))] - [ExpectedWarning ("IL2087", nameof (DataFlowTypeExtensions.RequiresPublicMethods))] - static void MethodRequiresNothing () - { - typeof (T).RequiresPublicFields (); - typeof (T).RequiresPublicMethods (); - typeof (T).RequiresNone (); - } - - [ExpectedWarning ("IL2091", nameof (MethodRequiresPublicMethods), "'T'")] - static void MethodRequiresPublicFieldsPassThrough< - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] T> () - { - MethodRequiresPublicFields (); - MethodRequiresPublicMethods (); - MethodRequiresNothing (); - } - - [ExpectedWarning ("IL2091", nameof (MethodRequiresPublicFields), "'T'")] - [ExpectedWarning ("IL2091", nameof (MethodRequiresPublicMethods), "'T'")] - static void MethodRequiresNothingPassThrough () - { - MethodRequiresPublicFields (); - MethodRequiresPublicMethods (); - MethodRequiresNothing (); - } - - static void TestMultipleGenericParametersOnMethod () - { - MethodMultipleWithDifferentRequirements_TestMultiple (); - MethodMultipleWithDifferentRequirements_TestFields (); - MethodMultipleWithDifferentRequirements_TestMethods (); - MethodMultipleWithDifferentRequirements_TestBoth (); - MethodMultipleWithDifferentRequirements_TestNothing (); - } - - static void MethodMultipleWithDifferentRequirements_TestMultiple< - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TFields, - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TMethods, - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.PublicMethods)] TBoth, - TNothing> () - { - typeof (TFields).RequiresPublicFields (); ; - typeof (TMethods).RequiresPublicMethods (); - typeof (TBoth).RequiresPublicFields (); ; - typeof (TBoth).RequiresPublicMethods (); - typeof (TFields).RequiresNone (); - typeof (TMethods).RequiresNone (); - typeof (TBoth).RequiresNone (); - typeof (TNothing).RequiresNone (); - } - - [ExpectedWarning ("IL2087", nameof (DataFlowTypeExtensions.RequiresPublicMethods))] - static void MethodMultipleWithDifferentRequirements_TestFields< - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TFields, - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TMethods, - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.PublicMethods)] TBoth, - TNothing> () - { - typeof (TFields).RequiresPublicFields (); ; - typeof (TFields).RequiresPublicMethods (); - typeof (TFields).RequiresNone (); - } - - [ExpectedWarning ("IL2087", nameof (DataFlowTypeExtensions.RequiresPublicFields))] - static void MethodMultipleWithDifferentRequirements_TestMethods< - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TFields, - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TMethods, - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.PublicMethods)] TBoth, - TNothing> () - { - typeof (TMethods).RequiresPublicFields (); - typeof (TMethods).RequiresPublicMethods (); - typeof (TMethods).RequiresNone (); - } - - static void MethodMultipleWithDifferentRequirements_TestBoth< - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TFields, - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TMethods, - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.PublicMethods)] TBoth, - TNothing> () - { - typeof (TBoth).RequiresPublicFields (); - typeof (TBoth).RequiresPublicMethods (); - typeof (TBoth).RequiresNone (); - } - - [ExpectedWarning ("IL2087", nameof (DataFlowTypeExtensions.RequiresPublicFields))] - [ExpectedWarning ("IL2087", nameof (DataFlowTypeExtensions.RequiresPublicMethods))] - static void MethodMultipleWithDifferentRequirements_TestNothing< - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TFields, - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TMethods, - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.PublicMethods)] TBoth, - TNothing> () - { - typeof (TNothing).RequiresPublicFields (); - typeof (TNothing).RequiresPublicMethods (); - typeof (TNothing).RequiresNone (); - } - - static void TestMethodGenericParametersViaInheritance () - { - TypeWithInstantiatedGenericMethodViaGenericParameter.StaticRequiresPublicFields (); - TypeWithInstantiatedGenericMethodViaGenericParameter.StaticRequiresPublicFieldsNonGeneric (); - - TypeWithInstantiatedGenericMethodViaGenericParameter.StaticPartialInstantiation (); - TypeWithInstantiatedGenericMethodViaGenericParameter.StaticPartialInstantiationUnrecognized (); - - var instance = new TypeWithInstantiatedGenericMethodViaGenericParameter (); - - instance.InstanceRequiresPublicFields (); - instance.InstanceRequiresPublicFieldsNonGeneric (); - - instance.VirtualRequiresPublicFields (); - instance.VirtualRequiresPublicMethods (); - - instance.CallInterface (); - - IInterfaceWithGenericMethod interfaceInstance = (IInterfaceWithGenericMethod) instance; - interfaceInstance.InterfaceRequiresPublicFields (); - interfaceInstance.InterfaceRequiresPublicMethods (); - } - - class BaseTypeWithGenericMethod - { - public static void StaticRequiresPublicFields<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] T> () - => typeof (T).RequiresPublicFields (); - public void InstanceRequiresPublicFields<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] T> () - => typeof (T).RequiresPublicFields (); - public virtual void VirtualRequiresPublicFields<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] T> () - => typeof (T).RequiresPublicFields (); - - public static void StaticRequiresPublicMethods<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] T> () - => typeof (T).RequiresPublicMethods (); - public void InstanceRequiresPublicMethods<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] T> () - => typeof (T).RequiresPublicMethods (); - public virtual void VirtualRequiresPublicMethods<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] T> () - => typeof (T).RequiresPublicMethods (); - - public static void StaticRequiresMultipleGenericParams< - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TFields, - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TMethods> () - { - typeof (TFields).RequiresPublicFields (); - typeof (TMethods).RequiresPublicMethods (); - } - } - - interface IInterfaceWithGenericMethod - { - void InterfaceRequiresPublicFields<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] T> (); - void InterfaceRequiresPublicMethods<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] T> (); - } - - - class TypeWithInstantiatedGenericMethodViaGenericParameter<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TOuter> - : BaseTypeWithGenericMethod, IInterfaceWithGenericMethod - { - [ExpectedWarning ("IL2091", - "'TInner'", - "Mono.Linker.Tests.Cases.DataFlow.GenericParameterDataFlow.TypeWithInstantiatedGenericMethodViaGenericParameter.StaticRequiresPublicFields()", - "'T'", - "Mono.Linker.Tests.Cases.DataFlow.GenericParameterDataFlow.BaseTypeWithGenericMethod.StaticRequiresPublicMethods()")] - public static void StaticRequiresPublicFields<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TInner> () - { - StaticRequiresPublicFields (); - StaticRequiresPublicMethods (); - } - - [ExpectedWarning ("IL2091", - "'TOuter'", - "Mono.Linker.Tests.Cases.DataFlow.GenericParameterDataFlow.TypeWithInstantiatedGenericMethodViaGenericParameter", - "'T'", - "Mono.Linker.Tests.Cases.DataFlow.GenericParameterDataFlow.BaseTypeWithGenericMethod.StaticRequiresPublicMethods()")] - public static void StaticRequiresPublicFieldsNonGeneric () - { - StaticRequiresPublicFields (); - StaticRequiresPublicMethods (); - } - - public static void StaticPartialInstantiation () - { - StaticRequiresMultipleGenericParams (); - } - - [ExpectedWarning ("IL2091", - nameof (TOuter), - "Mono.Linker.Tests.Cases.DataFlow.GenericParameterDataFlow.TypeWithInstantiatedGenericMethodViaGenericParameter", - "TMethods", - "Mono.Linker.Tests.Cases.DataFlow.GenericParameterDataFlow.BaseTypeWithGenericMethod.StaticRequiresMultipleGenericParams()", - ProducedBy = ProducedBy.Analyzer)] - [ExpectedWarning ("IL2091", - "'TOuter'", - "Mono.Linker.Tests.Cases.DataFlow.GenericParameterDataFlow.TypeWithInstantiatedGenericMethodViaGenericParameter", - "'TMethods'", - "Mono.Linker.Tests.Cases.DataFlow.GenericParameterDataFlow.BaseTypeWithGenericMethod.StaticRequiresMultipleGenericParams", - ProducedBy = ProducedBy.Trimmer | ProducedBy.NativeAot)] - public static void StaticPartialInstantiationUnrecognized () - { - StaticRequiresMultipleGenericParams (); - } - - [ExpectedWarning ("IL2091", - "'TInner'", - "Mono.Linker.Tests.Cases.DataFlow.GenericParameterDataFlow.TypeWithInstantiatedGenericMethodViaGenericParameter", "InstanceRequiresPublicFields", - "'T'", - "Mono.Linker.Tests.Cases.DataFlow.GenericParameterDataFlow.BaseTypeWithGenericMethod.InstanceRequiresPublicMethods")] - public void InstanceRequiresPublicFields<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TInner> () - { - InstanceRequiresPublicFields (); - InstanceRequiresPublicMethods (); - } - - [ExpectedWarning ("IL2091", - "'TOuter'", - "Mono.Linker.Tests.Cases.DataFlow.GenericParameterDataFlow.TypeWithInstantiatedGenericMethodViaGenericParameter", - "'T'", - "Mono.Linker.Tests.Cases.DataFlow.GenericParameterDataFlow.BaseTypeWithGenericMethod.InstanceRequiresPublicMethods")] - public void InstanceRequiresPublicFieldsNonGeneric () - { - InstanceRequiresPublicFields (); - InstanceRequiresPublicMethods (); - } - - public override void VirtualRequiresPublicFields<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] T> () - { - typeof (T).RequiresPublicFields (); - } - - public override void VirtualRequiresPublicMethods<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] T> () - { - typeof (T).RequiresPublicMethods (); - } - - public void InterfaceRequiresPublicFields<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] T> () - { - typeof (T).RequiresPublicFields (); ; - } - - public void InterfaceRequiresPublicMethods<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] T> () - { - typeof (T).RequiresPublicMethods (); - } - - [ExpectedWarning ("IL2091", - "'TOuter'", - "Mono.Linker.Tests.Cases.DataFlow.GenericParameterDataFlow.TypeWithInstantiatedGenericMethodViaGenericParameter", - "'T'", - "Mono.Linker.Tests.Cases.DataFlow.GenericParameterDataFlow.IInterfaceWithGenericMethod.InterfaceRequiresPublicMethods")] - public void CallInterface () - { - IInterfaceWithGenericMethod interfaceInstance = (IInterfaceWithGenericMethod) this; - interfaceInstance.InterfaceRequiresPublicFields (); - interfaceInstance.InterfaceRequiresPublicMethods (); - } - } - - static void TestNewConstraintSatisfiesParameterlessConstructor () where T : new() - { - RequiresParameterlessConstructor (); - } - - static void TestStructConstraintSatisfiesParameterlessConstructor () where T : struct - { - RequiresParameterlessConstructor (); - } - static void TestUnmanagedConstraintSatisfiesParameterlessConstructor () where T : unmanaged - { - RequiresParameterlessConstructor (); - } - - static void RequiresParameterlessConstructor<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] T> () - { - } - - // Warn about calls to static methods: - [ExpectedWarning ("IL2026", "TypeRequiresPublicFields", "RUCTest()", "message")] - [ExpectedWarning ("IL2026", "RUCMethodRequiresPublicMethods", "message")] - // And about type/method generic parameters on the RUC methods: - [ExpectedWarning ("IL2091", "TypeRequiresPublicFields")] - [ExpectedWarning ("IL2091", "RUCMethodRequiresPublicMethods")] - static void TestNoWarningsInRUCMethod () - { - TypeRequiresPublicFields.RUCTest (); - RUCMethodRequiresPublicMethods (); - } - - // Warn about calls to the static methods and the ctor on the RUC type: - [ExpectedWarning ("IL2026", "StaticMethod", "message")] - [ExpectedWarning ("IL2026", "StaticMethodRequiresPublicMethods", "message")] - [ExpectedWarning ("IL2026", "StaticMethodRequiresPublicMethods", "message")] - [ExpectedWarning ("IL2026", "StaticMethodRequiresPublicMethods", "message")] - [ExpectedWarning ("IL2026", "RUCTypeRequiresPublicFields", "message")] - // And about method generic parameters: - [ExpectedWarning ("IL2091", "InstanceMethodRequiresPublicMethods")] - [ExpectedWarning ("IL2091", "StaticMethodRequiresPublicMethods")] - [ExpectedWarning ("IL2091", "StaticMethodRequiresPublicMethods")] - [ExpectedWarning ("IL2091", "VirtualMethodRequiresPublicMethods")] - // And about type generic parameters: (one for each reference to the type): - [ExpectedWarning ("IL2091", "RUCTypeRequiresPublicFields")] // StaticMethod - [ExpectedWarning ("IL2091", "RUCTypeRequiresPublicFields")] // StaticMethodRequiresPublicMethods - [ExpectedWarning ("IL2091", "RUCTypeRequiresPublicFields")] // StaticMethodRequiresPublicMethods - [ExpectedWarning ("IL2091", "RUCTypeRequiresPublicFields")] // RUCTypeRequiresPublicFields ctor - [ExpectedWarning ("IL2091", "RUCTypeRequiresPublicFields", ProducedBy = ProducedBy.Trimmer)] // RUCTypeRequiresPublicFields local, // NativeAOT_StorageSpaceType - [ExpectedWarning ("IL2091", "RUCTypeRequiresPublicFields", ProducedBy = ProducedBy.Trimmer)] // InstanceMethod, // NativeAOT_StorageSpaceType - [ExpectedWarning ("IL2091", "RUCTypeRequiresPublicFields", ProducedBy = ProducedBy.Trimmer | ProducedBy.NativeAot)] // InstanceMethodRequiresPublicMethods - [ExpectedWarning ("IL2091", "RUCTypeRequiresPublicFields", ProducedBy = ProducedBy.Trimmer)] // VirtualMethod, // NativeAOT_StorageSpaceType - [ExpectedWarning ("IL2091", "RUCTypeRequiresPublicFields", ProducedBy = ProducedBy.Trimmer | ProducedBy.NativeAot)] // VirtualMethodRequiresPublicMethods - static void TestNoWarningsInRUCType () - { - RUCTypeRequiresPublicFields.StaticMethod (); - RUCTypeRequiresPublicFields.StaticMethodRequiresPublicMethods (); - RUCTypeRequiresPublicFields.StaticMethodRequiresPublicMethods (); - RUCTypeRequiresPublicFields.StaticMethodRequiresPublicMethods (); - var rucType = new RUCTypeRequiresPublicFields (); - rucType.InstanceMethod (); - rucType.InstanceMethodRequiresPublicMethods (); - rucType.VirtualMethod (); - rucType.VirtualMethodRequiresPublicMethods (); - } - - [RequiresUnreferencedCode ("message")] - public class RUCTypeRequiresPublicFields< - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] T> - { - public static void StaticMethod () - { - typeof (T).RequiresPublicMethods (); - } - - public static void StaticMethodRequiresPublicMethods< - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] U> () - { - typeof (U).RequiresPublicFields (); - } - - public void InstanceMethod () - { - typeof (T).RequiresPublicMethods (); - } - - public void InstanceMethodRequiresPublicMethods< - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] U> () - { - typeof (U).RequiresPublicFields (); - } - - public virtual void VirtualMethod () - { - typeof (T).RequiresPublicMethods (); - } - - public virtual void VirtualMethodRequiresPublicMethods< - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] U> () - { - typeof (U).RequiresPublicFields (); - } - } - - static void TestGenericParameterFlowsToField () - { - TypeRequiresPublicFields.TestFields (); - } - - public class TestType - { - } - public struct TestStruct - { - } - - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases/DataFlow/GenericParameterWarningLocation.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases/DataFlow/GenericParameterWarningLocation.cs deleted file mode 100644 index b3f81f9..0000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases/DataFlow/GenericParameterWarningLocation.cs +++ /dev/null @@ -1,1404 +0,0 @@ -// Copyright (c) .NET Foundation and contributors. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -using System; -using System.Diagnostics.CodeAnalysis; -using System.Linq.Expressions; -using System.Security.Policy; -using Mono.Linker.Tests.Cases.Expectations.Assertions; -using Mono.Linker.Tests.Cases.Expectations.Helpers; - -namespace Mono.Linker.Tests.Cases.DataFlow -{ - // NativeAOT differences in behavior: - // - // Validation of generic parameters only matters if the instantiation can be used to run code with the substituted type. - // So for generic methods the validation has to happen basically always (since any access to the method can lead to the code - // of the method executing eventually). - // For generic types though the situation is different. Code on the type can only run if the type is instantiated (new) - // or if static members are accessed on it (method calls, or fields accesses both can lead to static .cctor execution). - // Others usages of the type cannot themselves lead to code execution in the type, and thus don't need to be validated. - // Currently linker and analyzer both validate every time there's a type occurrence in the code. - // NativeAOT on the other hand only validates the cases which can lead to code execution (this is partially because the compiler - // doesn't care about the type in other situations really). - // So for example local variables of a given type, or method parameters of that type alone will not cause code execution - // inside that type and thus won't be validated by NativeAOT compiler. - // - // Below this explanation/fact is referred to as "NativeAOT_StorageSpaceType" - // Storage space - declaring a storage space as having a specific type doesn't in itself do anything with that type as per - // the above description. - - [SkipKeptItemsValidation] - [ExpectedNoWarnings] - public class GenericParameterWarningLocation - { - public static void Main () - { - TypeInheritance.Test (); - TypeImplementingInterface.Test (); - MethodParametersAndReturn.Test (); - MethodParametersAndReturnAccessedViaReflection.Test (); - FieldDefinition.Test (); - FieldDefinitionViaReflection.Test (); - PropertyDefinition.Test (); - MethodBody.Test (); - GenericAttributes.Test (); - } - - class TypeInheritance - { - class BaseWithPublicMethods<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> - { - public static void GetMethods () - { - typeof (TPublicMethods).GetMethods (); - } - } - - class BaseWithTwo< - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods, - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TPublicFields> - { } - - // No warning - annotations applied - class DerivedWithSpecificType : BaseWithPublicMethods { } - - // No warning - annotations match - class DerivedWithMatchingAnnotation<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods)] TAllMethods> - : BaseWithPublicMethods - { } - - [ExpectedWarning ("IL2091")] - class DerivedWithNoAnnotations - : BaseWithPublicMethods - { - [ExpectedWarning ("IL2091")] // Compiler generates an implicit call to BaseWithPublicMethods..ctor - public DerivedWithNoAnnotations () { } - } - - [ExpectedWarning ("IL2091")] - class DerivedWithMismatchAnnotation<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TPublicFields> - : BaseWithPublicMethods - { } - - [ExpectedWarning ("IL2091", nameof (DynamicallyAccessedMemberTypes.PublicMethods))] - class DerivedWithOneMismatch<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TPublicFields> - : BaseWithTwo - { } - - class DerivedWithTwoMatching< - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TPublicFields, - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> - : BaseWithTwo - { } - - [ExpectedWarning ("IL2091")] - class DerivedWithOnlyStaticMethodReference : BaseWithPublicMethods - { - // The method body in this case looks like: - // BaseWithPublicMethods.GetMethods () - // The type instantiation needs to be validated and in this case it produces a warning. - // This is no different from the same code being part of a completely unrelated method/class. - // So the fact that this is in derived class has no impact on the validation in this case. - [ExpectedWarning ("IL2091")] - public static void GetDerivedMethods () => GetMethods (); - } - - [ExpectedWarning ("IL2091")] - static void TestWithUnannotatedTypeArgument () - { - object a; - a = new DerivedWithMatchingAnnotation (); // IL2091 due to the instantiation - a = new DerivedWithNoAnnotations (); - } - - public static void Test () - { - Type t; - t = typeof (DerivedWithSpecificType); - t = typeof (DerivedWithMatchingAnnotation<>); - t = typeof (DerivedWithNoAnnotations<>); - t = typeof (DerivedWithMismatchAnnotation<>); - t = typeof (DerivedWithOneMismatch<>); - t = typeof (DerivedWithTwoMatching<,>); - - // Also try exact instantiations - object a; - a = new DerivedWithMatchingAnnotation (); - a = new DerivedWithMatchingAnnotation (); - - // Also try with unannotated type parameter - TestWithUnannotatedTypeArgument (); - - DerivedWithOnlyStaticMethodReference.GetDerivedMethods (); - } - } - - class TypeImplementingInterface - { - interface IWithPublicMethods<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> { } - - interface IWithPublicFields<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TPublicFields> { } - - // No warning - annotations applied - class ImplementsWithSpecificType : IWithPublicMethods, IWithPublicFields { } - - // No warning - matching annotations - class ImplementsWithMatchingAnnotation<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)] TAll> - : IWithPublicMethods, IWithPublicFields - { } - - [ExpectedWarning ("IL2091", nameof (DynamicallyAccessedMemberTypes.PublicFields))] - class ImplementsWithOneMismatch<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> - : IWithPublicMethods, IWithPublicFields - { } - - [ExpectedWarning ("IL2091", nameof (DynamicallyAccessedMemberTypes.PublicMethods))] - [ExpectedWarning ("IL2091", nameof (DynamicallyAccessedMemberTypes.PublicFields))] - class ImplementsWithTwoMismatches< - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods, - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TPublicFields> - : IWithPublicMethods, IWithPublicFields - { } - - public static void Test () - { - // Instantiate the types - new ImplementsWithSpecificType (); - new ImplementsWithMatchingAnnotation (); - new ImplementsWithOneMismatch (); - new ImplementsWithTwoMismatches (); - - // Also reference the interfaces, otherwise they could be trimmed - Type t; - t = typeof (IWithPublicMethods<>); - t = typeof (IWithPublicFields<>); - } - } - - //.NativeAOT: Method parameter types are not interesting until something creates an instance of them - // so there's no need to validate generic arguments. See comment at the top of the file for more details. - class MethodParametersAndReturn - { - class TypeWithPublicMethods<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> - { } - - interface IWithTwo< - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods, - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TPublicFields> - { } - - static void MethodWithSpecificType (TypeWithPublicMethods one, IWithTwo two) { } - - [ExpectedWarning ("IL2091", ProducedBy = ProducedBy.Trimmer | ProducedBy.Analyzer)] // NativeAOT_StorageSpaceType - static void MethodWithOneMismatch (TypeWithPublicMethods one) { } - - [ExpectedWarning ("IL2091", nameof (IWithTwo), ProducedBy = ProducedBy.Trimmer | ProducedBy.Analyzer)] // NativeAOT_StorageSpaceType - [ExpectedWarning ("IL2091", nameof (TypeWithPublicMethods), ProducedBy = ProducedBy.Trimmer | ProducedBy.Analyzer)] // NativeAOT_StorageSpaceType - static void MethodWithTwoMismatches< - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TPublicFields, - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> - (IWithTwo two, TypeWithPublicMethods one) - { } - - static TypeWithPublicMethods MethodWithSpecificReturnType () => null; - - static TypeWithPublicMethods MethodWithMatchingReturn<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> () => null; - - [ExpectedWarning ("IL2091", ProducedBy = ProducedBy.Trimmer | ProducedBy.Analyzer)] // NativeAOT_StorageSpaceType - static TypeWithPublicMethods MethodWithOneMismatchReturn () => null; - - [ExpectedWarning ("IL2091", ProducedBy = ProducedBy.Trimmer | ProducedBy.Analyzer)] // NativeAOT_StorageSpaceType - [ExpectedWarning ("IL2091", ProducedBy = ProducedBy.Trimmer | ProducedBy.Analyzer)] // NativeAOT_StorageSpaceType - static IWithTwo MethodWithTwoMismatchesInReturn< - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TPublicFields, - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> - () => null; - - class ConstructorWithOneMatchAndOneMismatch<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TMethods> - { - [ExpectedWarning ("IL2091", ProducedBy = ProducedBy.Trimmer | ProducedBy.Analyzer)] // NativeAOT_StorageSpaceType - public ConstructorWithOneMatchAndOneMismatch (IWithTwo two) { } - } - - public static void Test () - { - MethodWithSpecificType (null, null); - MethodWithOneMismatch (null); - MethodWithTwoMismatches (null, null); - - MethodWithSpecificReturnType (); - MethodWithMatchingReturn (); - MethodWithOneMismatchReturn (); - MethodWithTwoMismatchesInReturn (); - - _ = new ConstructorWithOneMatchAndOneMismatch (null); - } - } - - class MethodParametersAndReturnAccessedViaReflection - { - class TypeWithPublicMethods<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> - { } - - interface IWithTwo< - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods, - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TPublicFields> - { } - - static void MethodWithSpecificType (TypeWithPublicMethods one, IWithTwo two) { } - - [ExpectedWarning ("IL2091")] - static void MethodWithOneMismatch (TypeWithPublicMethods one) { } - - [ExpectedWarning ("IL2091", nameof (IWithTwo))] - [ExpectedWarning ("IL2091", nameof (TypeWithPublicMethods))] - static void MethodWithTwoMismatches< - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TPublicFields, - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> - (IWithTwo two, TypeWithPublicMethods one) - { } - - static TypeWithPublicMethods MethodWithSpecificReturnType () => null; - - static TypeWithPublicMethods MethodWithMatchingReturn<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> () => null; - - [ExpectedWarning ("IL2091")] - static TypeWithPublicMethods MethodWithOneMismatchReturn () => null; - - [ExpectedWarning ("IL2091")] - [ExpectedWarning ("IL2091")] - static IWithTwo MethodWithTwoMismatchesInReturn< - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TPublicFields, - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> - () => null; - - class ConstructorWithOneMatchAndOneMismatch<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TMethods> - { - [ExpectedWarning ("IL2091")] - public ConstructorWithOneMatchAndOneMismatch (IWithTwo two) { } - } - - public static void Test () - { - // Access all of the methods via reflection - typeof (MethodParametersAndReturnAccessedViaReflection).RequiresNonPublicMethods (); - typeof (ConstructorWithOneMatchAndOneMismatch<>).RequiresPublicConstructors (); - } - } - - //.NativeAOT: Field types are not interesting until something creates an instance of them - // so there's no need to validate generic arguments. See comment at the top of the file for more details. - class FieldDefinition - { - class TypeWithPublicMethods<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> - { } - - interface IWithTwo< - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods, - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TPublicFields> - { } - - class SpecificType - { - static TypeWithPublicMethods _field; - - public static void Test () - { - _field = null; - } - } - - class OneMatchingAnnotation<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> - { - static TypeWithPublicMethods _field; - - public static void Test () - { - _field = null; - } - } - - class MultipleReferencesToTheSameType<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods, TUnknown> - { - [ExpectedWarning ("IL2091", ProducedBy = ProducedBy.Trimmer | ProducedBy.Analyzer)] // NativeAOT_StorageSpaceType - static TypeWithPublicMethods _field1; - static TypeWithPublicMethods _field2; - [ExpectedWarning ("IL2091", ProducedBy = ProducedBy.Trimmer | ProducedBy.Analyzer)] // NativeAOT_StorageSpaceType - static TypeWithPublicMethods _field3; - - public static void Test () - { - _field1 = null; - _field2 = null; - _field3 = null; - } - } - - class TwoMismatchesInOne< - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods, - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TPublicFields> - { - [ExpectedWarning ("IL2091", ProducedBy = ProducedBy.Trimmer | ProducedBy.Analyzer)] // NativeAOT_StorageSpaceType - [ExpectedWarning ("IL2091", ProducedBy = ProducedBy.Trimmer | ProducedBy.Analyzer)] // NativeAOT_StorageSpaceType - static IWithTwo _field; - - public static void Test () - { - _field = null; - } - } - - public static void Test () - { - SpecificType.Test (); - OneMatchingAnnotation.Test (); - MultipleReferencesToTheSameType.Test (); - TwoMismatchesInOne.Test (); - } - } - - class FieldDefinitionViaReflection - { - class TypeWithPublicMethods<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> - { } - - interface IWithTwo< - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods, - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TPublicFields> - { } - - class SpecificType - { - static TypeWithPublicMethods _field; - } - - class OneMatchingAnnotation<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> - { - static TypeWithPublicMethods _field; - } - - class MultipleReferencesToTheSameType<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods, TUnknown> - { - [ExpectedWarning ("IL2091")] - static TypeWithPublicMethods _field1; - static TypeWithPublicMethods _field2; - [ExpectedWarning ("IL2091")] - static TypeWithPublicMethods _field3; - } - - class TwoMismatchesInOne< - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods, - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TPublicFields> - { - [ExpectedWarning ("IL2091")] - [ExpectedWarning ("IL2091")] - static IWithTwo _field; - } - - public static void Test () - { - typeof (SpecificType).RequiresNonPublicFields (); - typeof (OneMatchingAnnotation<>).RequiresNonPublicFields (); - typeof (MultipleReferencesToTheSameType<,>).RequiresNonPublicFields (); - typeof (TwoMismatchesInOne<,>).RequiresNonPublicFields (); - } - } - - //.NativeAOT: Property types are not interesting until something creates an instance of them - // so there's no need to validate generic arguments. See comment at the top of the file for more details. - // In case of trimmer/aot it's even less important because properties don't exist in IL really - // and thus no code can manipulate them directly - only through reflection. - class PropertyDefinition - { - class TypeWithPublicMethods<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> - { } - - interface IWithTwo< - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods, - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TPublicFields> - { } - - class SpecificType - { - static TypeWithPublicMethods Property { get; set; } - - public static void Test () - { - Property = null; - } - } - - class OneMatchingAnnotation<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> - { - static TypeWithPublicMethods Property { get; set; } - - public static void Test () - { - Property = null; - } - } - - class MultipleReferencesToTheSameType<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods, TUnknown> - { - // The warning is generated on the backing field - [ExpectedWarning ("IL2091", CompilerGeneratedCode = true, ProducedBy = ProducedBy.Trimmer | ProducedBy.Analyzer)] // NativeAOT_StorageSpaceType - static TypeWithPublicMethods Property1 { - [ExpectedWarning ("IL2091", ProducedBy = ProducedBy.Trimmer | ProducedBy.Analyzer)] // NativeAOT_StorageSpaceType - get; - - [ExpectedWarning ("IL2091", ProducedBy = ProducedBy.Trimmer | ProducedBy.Analyzer)] // NativeAOT_StorageSpaceType - set; - } - - static TypeWithPublicMethods Property2 { - get; - set; - } - - // The warning is generated on the backing field - [ExpectedWarning ("IL2091", CompilerGeneratedCode = true, ProducedBy = ProducedBy.Trimmer | ProducedBy.Analyzer)] // NativeAOT_StorageSpaceType - static TypeWithPublicMethods Property3 { - [ExpectedWarning ("IL2091", ProducedBy = ProducedBy.Trimmer | ProducedBy.Analyzer)] // NativeAOT_StorageSpaceType - get; - - [ExpectedWarning ("IL2091", ProducedBy = ProducedBy.Trimmer | ProducedBy.Analyzer)] // NativeAOT_StorageSpaceType - set; - } - - public static void Test () - { - Property1 = Property1; - Property2 = Property2; - Property3 = Property3; - } - } - - class TwoMismatchesInOne< - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods, - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TPublicFields> - { - // The warnings are generated on the backing field - [ExpectedWarning ("IL2091", CompilerGeneratedCode = true, ProducedBy = ProducedBy.Trimmer | ProducedBy.Analyzer)] // NativeAOT_StorageSpaceType - [ExpectedWarning ("IL2091", CompilerGeneratedCode = true, ProducedBy = ProducedBy.Trimmer | ProducedBy.Analyzer)] // NativeAOT_StorageSpaceType - static IWithTwo Property { - // Getter is trimmed and doesn't produce any warning - get; - - [ExpectedWarning ("IL2091", ProducedBy = ProducedBy.Trimmer | ProducedBy.Analyzer)] // NativeAOT_StorageSpaceType - [ExpectedWarning ("IL2091", ProducedBy = ProducedBy.Trimmer | ProducedBy.Analyzer)] // NativeAOT_StorageSpaceType - set; - } - - public static void Test () - { - Property = null; - } - } - - public static void Test () - { - SpecificType.Test (); - OneMatchingAnnotation.Test (); - MultipleReferencesToTheSameType.Test (); - TwoMismatchesInOne.Test (); - } - } - - class MethodBody - { - class TypeWithPublicMethods<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> : Exception - { - public static void Method () { } - public void InstanceMethod () { } - - public static string Field; - public string InstanceField; - - public static string Property { get; set; } - } - - interface IWithTwo< - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods, - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TPublicFields> - { - public static void Method () { } - public void InstanceMethod (); - - public static string Field; - - public static string Property { get; set; } - } - - class TypeWithTwo< - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods, - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TPublicFields> : Exception - { } - - static void MethodWithPublicMethods<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> () { } - - void InstanceMethodWithPublicMethods<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> () { } - - static void MethodWithTwo< - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods, - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TPublicFields> () - { } - - static MethodBody GetInstance () => null; - - [ExpectedWarning ("IL2091", ProducedBy = ProducedBy.Trimmer | ProducedBy.Analyzer)] // return type // NativeAOT_StorageSpaceType - static TypeWithPublicMethods GetInstanceForTypeWithPublicMethods () => null; - - class TypeOf - { - static void AccessOpenTypeDefinition () - { - // Accessing the open type definition should not do anything on its own - just validating that it doesn't break anything - Type t = typeof (TypeWithPublicMethods<>); - t = typeof (IWithTwo<,>); - } - - static void SpecificType () - { - Type t = typeof (TypeWithPublicMethods); - t = typeof (IWithTwo); - } - - static void OneMatchingAnnotation<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> () - { - Type t = typeof (TypeWithPublicMethods); - } - - [ExpectedWarning ("IL2091")] - [ExpectedWarning ("IL2091")] - static void MultipleReferencesToTheSameType< - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods, - TUnknown> () - { - Type t = typeof (TypeWithPublicMethods); // Warn - t = typeof (TypeWithPublicMethods); // No warn - t = typeof (TypeWithPublicMethods); // Warn - } - - [ExpectedWarning ("IL2091")] - [ExpectedWarning ("IL2091")] - static void TwoMismatchesInOneStatement< - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TPublicFields, - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> - () - { - Type t = typeof (IWithTwo); - } - - public static void Test () - { - AccessOpenTypeDefinition (); - SpecificType (); - OneMatchingAnnotation (); - MultipleReferencesToTheSameType (); - TwoMismatchesInOneStatement (); - } - } - - class MethodCallOnGenericMethod - { - static void SpecificType () - { - MethodWithPublicMethods (); - MethodWithTwo (); - } - - static void OneMatchingAnnotation<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> () - { - MethodWithPublicMethods (); - } - - [ExpectedWarning ("IL2091")] - [ExpectedWarning ("IL2091")] - static void MultipleReferencesToTheSameMethod< - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods, - TUnknown> () - { - MethodWithPublicMethods (); // Warn - MethodWithPublicMethods (); // No warn - MethodWithPublicMethods (); // Warn - } - - [ExpectedWarning ("IL2091")] - [ExpectedWarning ("IL2091")] - static void TwoMismatchesInOneStatement< - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TPublicFields, - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> - () - { - MethodWithTwo (); - } - - [ExpectedWarning ("IL2091")] - static void InstanceMethodMismatch () - { - GetInstance ().InstanceMethodWithPublicMethods (); - } - - public static void Test () - { - SpecificType (); - OneMatchingAnnotation (); - MultipleReferencesToTheSameMethod (); - TwoMismatchesInOneStatement (); - InstanceMethodMismatch (); - } - } - - class MethodCallOnGenericType - { - static void SpecificType () - { - TypeWithPublicMethods.Method (); - IWithTwo.Method (); - } - - static void OneMatchingAnnotation<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> () - { - TypeWithPublicMethods.Method (); - } - - [ExpectedWarning ("IL2091")] - [ExpectedWarning ("IL2091")] - static void MultipleReferencesToTheSameMethod< - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods, - TUnknown> () - { - TypeWithPublicMethods.Method (); // Warn - TypeWithPublicMethods.Method (); // No warn - TypeWithPublicMethods.Method (); // Warn - } - - [ExpectedWarning ("IL2091")] - [ExpectedWarning ("IL2091")] - static void TwoMismatchesInOneStatement< - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TPublicFields, - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> - () - { - IWithTwo.Method (); - } - - [ExpectedWarning ("IL2091", ProducedBy = ProducedBy.Trimmer | ProducedBy.Analyzer)] // NativeAOT_StorageSpaceType - [ExpectedWarning ("IL2091", ProducedBy = ProducedBy.Trimmer | ProducedBy.Analyzer)] // local variable // NativeAOT_StorageSpaceType - static void InstanceMethodMismatch () - { - TypeWithPublicMethods instance = GetInstanceForTypeWithPublicMethods (); - instance.InstanceMethod (); - } - - public static void Test () - { - SpecificType (); - OneMatchingAnnotation (); - MultipleReferencesToTheSameMethod (); - TwoMismatchesInOneStatement (); - InstanceMethodMismatch (); - } - } - - class FieldAccessOnGenericType - { - static void SpecificType () - { - _ = TypeWithPublicMethods.Field; - IWithTwo.Field = ""; - } - - static void OneMatchingAnnotation<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> () - { - _ = TypeWithPublicMethods.Field; - } - - [ExpectedWarning ("IL2091")] - [ExpectedWarning ("IL2091")] - static void MultipleReferencesToTheSameField< - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods, - TUnknown> () - { - _ = TypeWithPublicMethods.Field; // Warn - TypeWithPublicMethods.Field = ""; // No warn - TypeWithPublicMethods.Field = ""; // Warn - } - - [ExpectedWarning ("IL2091")] - [ExpectedWarning ("IL2091")] - static void TwoMismatchesInOneStatement< - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TPublicFields, - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> - () - { - _ = IWithTwo.Field; - } - - // The local variable - [ExpectedWarning ("IL2091", ProducedBy = ProducedBy.Trimmer | ProducedBy.Analyzer)] // NativeAOT_StorageSpaceType - [ExpectedWarning ("IL2091", ProducedBy = ProducedBy.Trimmer | ProducedBy.Analyzer)] // access to the field // NativeAOT_StorageSpaceType - static void InstanceFieldMismatch () - { - TypeWithPublicMethods instance = GetInstanceForTypeWithPublicMethods (); - _ = instance.InstanceField; - } - - public static void Test () - { - SpecificType (); - OneMatchingAnnotation (); - MultipleReferencesToTheSameField (); - TwoMismatchesInOneStatement (); - InstanceFieldMismatch (); - } - } - - //.NativeAOT: Local variable types are not interesting until something creates an instance of them - // so there's no need to validate generic arguments. See comment at the top of the file for more details. - class LocalVariable - { - static void SpecificType () - { - TypeWithPublicMethods t = null; - IWithTwo i = null; - } - - static void OneMatchingAnnotation<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> () - { - TypeWithPublicMethods t = null; - } - - [ExpectedWarning ("IL2091", ProducedBy = ProducedBy.Trimmer | ProducedBy.Analyzer)] // NativeAOT_StorageSpaceType - [ExpectedWarning ("IL2091", ProducedBy = ProducedBy.Trimmer | ProducedBy.Analyzer)] // NativeAOT_StorageSpaceType - static void MultipleReferencesToTheSameType< - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods, - TUnknown> () - { - TypeWithPublicMethods t1 = null; // Warn - TypeWithPublicMethods t2 = null; // No warn - TypeWithPublicMethods t3 = null; // Warn - } - - [ExpectedWarning ("IL2091", ProducedBy = ProducedBy.Trimmer | ProducedBy.Analyzer)] // NativeAOT_StorageSpaceType - [ExpectedWarning ("IL2091", ProducedBy = ProducedBy.Trimmer | ProducedBy.Analyzer)] // NativeAOT_StorageSpaceType - static void TwoMismatchesInOneStatement< - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TPublicFields, - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> - () - { - IWithTwo i = null; - } - - public static void Test () - { - SpecificType (); - OneMatchingAnnotation (); - MultipleReferencesToTheSameType (); - TwoMismatchesInOneStatement (); - } - } - - class DelegateUsageOnGenericMethod - { - static void SpecificType () - { - var a = new Action (MethodWithPublicMethods); - } - - static void OneMatchingAnnotation<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> () - { - var a = new Action (MethodWithPublicMethods); - } - - [ExpectedWarning ("IL2091")] - [ExpectedWarning ("IL2091")] - static void MultipleReferencesToTheSameMethod< - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods, - TUnknown> () - { - var a1 = new Action (MethodWithPublicMethods); // Warn - var a2 = new Action (MethodWithPublicMethods); // No warn - var a3 = new Action (MethodWithPublicMethods); // Warn - } - - [ExpectedWarning ("IL2091")] - [ExpectedWarning ("IL2091")] - static void TwoMismatchesInOneStatement< - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TPublicFields, - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> - () - { - var a = new Action (MethodWithTwo); - } - - public static void Test () - { - SpecificType (); - OneMatchingAnnotation (); - MultipleReferencesToTheSameMethod (); - TwoMismatchesInOneStatement (); - } - } - - class DelegateUsageOnGenericType - { - static void SpecificType () - { - var a = new Action (TypeWithPublicMethods.Method); - } - - static void OneMatchingAnnotation<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> () - { - var a = new Action (TypeWithPublicMethods.Method); - } - - [ExpectedWarning ("IL2091")] - [ExpectedWarning ("IL2091")] - static void MultipleReferencesToTheSameMethod< - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods, - TUnknown> () - { - var a1 = new Action (TypeWithPublicMethods.Method); // Warn - var a2 = new Action (TypeWithPublicMethods.Method); // No warn - var a3 = new Action (TypeWithPublicMethods.Method); // Warn - } - - [ExpectedWarning ("IL2091")] - [ExpectedWarning ("IL2091")] - static void TwoMismatchesInOneStatement< - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TPublicFields, - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> - () - { - var a = new Action (IWithTwo.Method); - } - - public static void Test () - { - SpecificType (); - OneMatchingAnnotation (); - MultipleReferencesToTheSameMethod (); - TwoMismatchesInOneStatement (); - } - } - - class LdTokenOnGenericMethod - { - static void SpecificType () - { - Expression a = () => MethodWithPublicMethods (); - } - - static void OneMatchingAnnotation<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> () - { - Expression a = () => MethodWithPublicMethods (); - } - - [ExpectedWarning ("IL2091")] - [ExpectedWarning ("IL2091")] - static void MultipleReferencesToTheSameMethod< - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods, - TUnknown> () - { - Expression a = () => MethodWithPublicMethods (); // Warn - a = () => MethodWithPublicMethods (); // No warn - a = () => MethodWithPublicMethods (); // Warn - } - - [ExpectedWarning ("IL2091")] - [ExpectedWarning ("IL2091")] - static void TwoMismatchesInOneStatement< - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TPublicFields, - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> - () - { - Expression a = () => MethodWithTwo (); - } - - public static void Test () - { - SpecificType (); - OneMatchingAnnotation (); - MultipleReferencesToTheSameMethod (); - TwoMismatchesInOneStatement (); - } - } - - class LdTokenOfMethodOnGenericType - { - static void SpecificType () - { - Expression a = () => TypeWithPublicMethods.Method (); - } - - static void OneMatchingAnnotation<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> () - { - Expression a = () => TypeWithPublicMethods.Method (); - } - - // There are two warnings per "callsite" in this case because the generated IL does - // ldtoken method - // ldtoken owningtype - // In order to call the right Expression APIs. - [ExpectedWarning ("IL2091")] - [ExpectedWarning ("IL2091", ProducedBy = ProducedBy.Trimmer | ProducedBy.NativeAot)] - [ExpectedWarning ("IL2091")] - [ExpectedWarning ("IL2091", ProducedBy = ProducedBy.Trimmer | ProducedBy.NativeAot)] - static void MultipleReferencesToTheSameMethod< - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods, - TUnknown> () - { - Expression a = () => TypeWithPublicMethods.Method (); // Warn - a = () => TypeWithPublicMethods.Method (); // No warn - a = () => TypeWithPublicMethods.Method (); // Warn - } - - // There are two warnings per "callsite" in this case because the generated IL does - // ldtoken method - // ldtoken owningtype - // In order to call the right Expression APIs. - [ExpectedWarning ("IL2091")] - [ExpectedWarning ("IL2091", ProducedBy = ProducedBy.Trimmer | ProducedBy.NativeAot)] - [ExpectedWarning ("IL2091")] - [ExpectedWarning ("IL2091", ProducedBy = ProducedBy.Trimmer | ProducedBy.NativeAot)] - static void TwoMismatchesInOneStatement< - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TPublicFields, - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> - () - { - Expression a = () => IWithTwo.Method (); - } - - public static void Test () - { - SpecificType (); - OneMatchingAnnotation (); - MultipleReferencesToTheSameMethod (); - TwoMismatchesInOneStatement (); - } - } - - class LdTokenOfFieldOnGenericType - { - static void SpecificType () - { - Expression> a = () => TypeWithPublicMethods.Field; - } - - static void OneMatchingAnnotation<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> () - { - Expression> a = () => TypeWithPublicMethods.Field; - } - - // There are two warnings per "callsite" in this case because the generated IL does - // ldtoken field - // ldtoken owningtype - // In order to call the right Expression APIs. - [ExpectedWarning ("IL2091")] - [ExpectedWarning ("IL2091", ProducedBy = ProducedBy.Trimmer | ProducedBy.NativeAot)] - [ExpectedWarning ("IL2091")] - [ExpectedWarning ("IL2091", ProducedBy = ProducedBy.Trimmer | ProducedBy.NativeAot)] - static void MultipleReferencesToTheSameField< - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods, - TUnknown> () - { - Expression> a = () => TypeWithPublicMethods.Field; // Warn - a = () => TypeWithPublicMethods.Field; // No warn - a = () => TypeWithPublicMethods.Field; // Warn - } - - // There are two warnings per "callsite" in this case because the generated IL does - // ldtoken field - // ldtoken owningtype - // In order to call the right Expression APIs. - [ExpectedWarning ("IL2091")] - [ExpectedWarning ("IL2091", ProducedBy = ProducedBy.Trimmer | ProducedBy.NativeAot)] - [ExpectedWarning ("IL2091")] - [ExpectedWarning ("IL2091", ProducedBy = ProducedBy.Trimmer | ProducedBy.NativeAot)] - static void TwoMismatchesInOneStatement< - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TPublicFields, - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> - () - { - Expression> a = () => IWithTwo.Field; - } - - public static void Test () - { - SpecificType (); - OneMatchingAnnotation (); - MultipleReferencesToTheSameField (); - TwoMismatchesInOneStatement (); - } - } - - class LdTokenOfPropertyOnGenericType - { - static void SpecificType () - { - Expression> a = () => TypeWithPublicMethods.Property; - } - - static void OneMatchingAnnotation<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> () - { - Expression> a = () => TypeWithPublicMethods.Property; - } - - // There are two warnings per "callsite" in this case because the generated IL does - // ldtoken method (getter) - // ldtoken owningtype - // In order to call the right Expression APIs. - [ExpectedWarning ("IL2091")] - [ExpectedWarning ("IL2091", ProducedBy = ProducedBy.Trimmer | ProducedBy.NativeAot)] - [ExpectedWarning ("IL2091")] - [ExpectedWarning ("IL2091", ProducedBy = ProducedBy.Trimmer | ProducedBy.NativeAot)] - static void MultipleReferencesToTheSameProperty< - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods, - TUnknown> () - { - Expression> a = () => TypeWithPublicMethods.Property; // Warn - a = () => TypeWithPublicMethods.Property; // No warn - a = () => TypeWithPublicMethods.Property; // Warn - } - - // There are two warnings per "callsite" in this case because the generated IL does - // ldtoken method (getter) - // ldtoken owningtype - // In order to call the right Expression APIs. - [ExpectedWarning ("IL2091")] - [ExpectedWarning ("IL2091", ProducedBy = ProducedBy.Trimmer | ProducedBy.NativeAot)] - [ExpectedWarning ("IL2091")] - [ExpectedWarning ("IL2091", ProducedBy = ProducedBy.Trimmer | ProducedBy.NativeAot)] - static void TwoMismatchesInOneStatement< - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TPublicFields, - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> - () - { - Expression> a = () => IWithTwo.Property; - } - - public static void Test () - { - SpecificType (); - OneMatchingAnnotation (); - MultipleReferencesToTheSameProperty (); - TwoMismatchesInOneStatement (); - } - } - - class CreateInstance - { - static void SpecificType () - { - object a = new TypeWithPublicMethods (); - } - - static void OneMatchingAnnotation<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> () - { - object a = new TypeWithPublicMethods (); - } - - [ExpectedWarning ("IL2091")] - [ExpectedWarning ("IL2091")] - static void MultipleReferencesToTheSameMethod< - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods, - TUnknown> () - { - object a1 = new TypeWithPublicMethods (); // Warn - object a2 = new TypeWithPublicMethods (); // No warn - object a3 = new TypeWithPublicMethods (); // Warn - } - - [ExpectedWarning ("IL2091")] - [ExpectedWarning ("IL2091")] - static void TwoMismatchesInOneStatement< - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TPublicFields, - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> - () - { - object a = new TypeWithTwo (); - } - - public static void Test () - { - SpecificType (); - OneMatchingAnnotation (); - MultipleReferencesToTheSameMethod (); - TwoMismatchesInOneStatement (); - } - } - - //.NativeAOT: Checking an instance for its type is not interesting until something creates an instance of that type - // so there's no need to validate generic arguments. See comment at the top of the file for more details. - class IsInstance - { - static object _value = null; - - static void SpecificType () - { - bool a = _value is TypeWithPublicMethods; - } - - static void OneMatchingAnnotation<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> () - { - bool a = _value is TypeWithPublicMethods; - } - - [ExpectedWarning ("IL2091", ProducedBy = ProducedBy.Trimmer | ProducedBy.Analyzer)] // NativeAOT_StorageSpaceType - [ExpectedWarning ("IL2091", ProducedBy = ProducedBy.Trimmer | ProducedBy.Analyzer)] // NativeAOT_StorageSpaceType - static void MultipleReferencesToTheSameMethod< - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods, - TUnknown> () - { - bool a1 = _value is TypeWithPublicMethods; // Warn - bool a2 = _value is TypeWithPublicMethods; // No warn - bool a3 = _value is TypeWithPublicMethods; // Warn - } - - [ExpectedWarning ("IL2091", ProducedBy = ProducedBy.Trimmer | ProducedBy.Analyzer)] // NativeAOT_StorageSpaceType - [ExpectedWarning ("IL2091", ProducedBy = ProducedBy.Trimmer | ProducedBy.Analyzer)] // NativeAOT_StorageSpaceType - static void TwoMismatchesInOneStatement< - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TPublicFields, - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> - () - { - bool a = _value is TypeWithTwo; - } - - public static void Test () - { - SpecificType (); - OneMatchingAnnotation (); - MultipleReferencesToTheSameMethod (); - TwoMismatchesInOneStatement (); - } - } - - // This is basically the same operation as IsInstance - class AsType - { - static object _value = null; - - static void SpecificType () - { - object a = _value as TypeWithPublicMethods; - } - - static void OneMatchingAnnotation<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> () - { - object a = _value as TypeWithPublicMethods; - } - - [ExpectedWarning ("IL2091", ProducedBy = ProducedBy.Trimmer | ProducedBy.Analyzer)] // NativeAOT_StorageSpaceType - [ExpectedWarning ("IL2091", ProducedBy = ProducedBy.Trimmer | ProducedBy.Analyzer)] // NativeAOT_StorageSpaceType - static void MultipleReferencesToTheSameMethod< - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods, - TUnknown> () - { - object a1 = _value as TypeWithPublicMethods; // Warn - object a2 = _value as TypeWithPublicMethods; // No warn - object a3 = _value as TypeWithPublicMethods; // Warn - } - - [ExpectedWarning ("IL2091", ProducedBy = ProducedBy.Trimmer | ProducedBy.Analyzer)] // NativeAOT_StorageSpaceType - [ExpectedWarning ("IL2091", ProducedBy = ProducedBy.Trimmer | ProducedBy.Analyzer)] // NativeAOT_StorageSpaceType - static void TwoMismatchesInOneStatement< - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TPublicFields, - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> - () - { - object a = _value as TypeWithTwo; - } - - public static void Test () - { - SpecificType (); - OneMatchingAnnotation (); - MultipleReferencesToTheSameMethod (); - TwoMismatchesInOneStatement (); - } - } - - //.NativeAOT: Exception types are effectively very similar to local variable or method parameters. - // and are not interesting until something creates an instance of them - // so there's no need to validate generic arguments. See comment at the top of the file for more details. - class ExceptionCatch - { - static void SpecificType () - { - try { - DoNothing (); - } catch (TypeWithPublicMethods) { - } - } - - static void OneMatchingAnnotation<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> () - { - try { - DoNothing (); - } catch (TypeWithPublicMethods) { - } - } - - [ExpectedWarning ("IL2091", ProducedBy = ProducedBy.Trimmer | ProducedBy.Analyzer)] // NativeAOT_StorageSpaceType - [ExpectedWarning ("IL2091", ProducedBy = ProducedBy.Trimmer | ProducedBy.Analyzer)] // NativeAOT_StorageSpaceType - static void MultipleReferencesToTheSameType< - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods, - TUnknown> () - { - try { - DoNothing (); - } catch (TypeWithPublicMethods) { // Warn - } - - try { - DoNothing (); - } catch (TypeWithPublicMethods) { // No warn - } - - try { - DoNothing (); - } catch (TypeWithPublicMethods) { // Warn - } - } - - [ExpectedWarning ("IL2091", ProducedBy = ProducedBy.Trimmer | ProducedBy.Analyzer)] // NativeAOT_StorageSpaceType - [ExpectedWarning ("IL2091", ProducedBy = ProducedBy.Trimmer | ProducedBy.Analyzer)] // NativeAOT_StorageSpaceType - static void TwoMismatchesInOneStatement< - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TPublicFields, - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> - () - { - try { - DoNothing (); - } catch (TypeWithTwo) { // Warn x2 - } - } - - public static void Test () - { - SpecificType (); - OneMatchingAnnotation (); - MultipleReferencesToTheSameType (); - TwoMismatchesInOneStatement (); - } - } - - // This is basically the same as IsInstance and thus not dangerous - class ExceptionFilter - { - static void SpecificType () - { - try { - DoNothing (); - } catch (Exception ex) when (ex is TypeWithPublicMethods) { - } - } - - static void OneMatchingAnnotation<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> () - { - try { - DoNothing (); - } catch (Exception ex) when (ex is TypeWithPublicMethods) { - } - } - - [ExpectedWarning ("IL2091", ProducedBy = ProducedBy.Trimmer | ProducedBy.Analyzer)] // NativeAOT_StorageSpaceType - [ExpectedWarning ("IL2091", ProducedBy = ProducedBy.Trimmer | ProducedBy.Analyzer)] // NativeAOT_StorageSpaceType - static void MultipleReferencesToTheSameType< - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods, - TUnknown> () - { - try { - DoNothing (); - } catch (Exception ex) when (ex is TypeWithPublicMethods) { // Warn - } - - try { - DoNothing (); - } catch (Exception ex) when (ex is TypeWithPublicMethods) { // No warn - } - - try { - DoNothing (); - } catch (Exception ex) when (ex is TypeWithPublicMethods) { // Warn - } - } - - [ExpectedWarning ("IL2091", ProducedBy = ProducedBy.Trimmer | ProducedBy.Analyzer)] // NativeAOT_StorageSpaceType - [ExpectedWarning ("IL2091", ProducedBy = ProducedBy.Trimmer | ProducedBy.Analyzer)] // NativeAOT_StorageSpaceType - static void TwoMismatchesInOneStatement< - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TPublicFields, - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> - () - { - try { - DoNothing (); - } catch (Exception ex) when (ex is TypeWithTwo) { // Warn x2 - } - } - - public static void Test () - { - SpecificType (); - OneMatchingAnnotation (); - MultipleReferencesToTheSameType (); - TwoMismatchesInOneStatement (); - } - } - - public static void Test () - { - TypeOf.Test (); - MethodCallOnGenericMethod.Test (); - MethodCallOnGenericType.Test (); - FieldAccessOnGenericType.Test (); - LocalVariable.Test (); - DelegateUsageOnGenericMethod.Test (); - DelegateUsageOnGenericType.Test (); - LdTokenOnGenericMethod.Test (); - LdTokenOfMethodOnGenericType.Test (); - LdTokenOfFieldOnGenericType.Test (); - LdTokenOfPropertyOnGenericType.Test (); - CreateInstance.Test (); - IsInstance.Test (); - AsType.Test (); - ExceptionCatch.Test (); - ExceptionFilter.Test (); - } - } - - // There are no warnings due to data flow itself - // since the generic attributes must be fully instantiated always. - class GenericAttributes - { - class TypeWithPublicMethodsAttribute<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> - : Attribute - { } - - class TypeWithTwoAttribute< - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods, - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TPublicFields> - : Attribute - { } - - [TypeWithPublicMethods] - static void OneSpecificType () { } - - [TypeWithTwo] - static void TwoSpecificTypes () { } - - public static void Test () - { - OneSpecificType (); - TwoSpecificTypes (); - } - } - - class TestType { } - - static void DoNothing () { } - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/AssemblyChecker.cs b/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/AssemblyChecker.cs index f7e5ee0..51f2fa9 100644 --- a/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/AssemblyChecker.cs +++ b/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/AssemblyChecker.cs @@ -3,11 +3,14 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; +using System.Reflection.Metadata.Ecma335; using System.Text; using FluentAssertions; using ILCompiler; +using Internal.IL.Stubs; using Internal.TypeSystem; using Internal.TypeSystem.Ecma; using Mono.Cecil; @@ -21,6 +24,42 @@ namespace Mono.Linker.Tests.TestCasesRunner { public class AssemblyChecker { + internal readonly struct AssemblyQualifiedToken : IEquatable + { + public string? AssemblyName { get; } + public int Token { get; } + + public AssemblyQualifiedToken (string? assemblyName, int token) => (AssemblyName, Token) = (assemblyName, token); + + public AssemblyQualifiedToken (TypeSystemEntity entity) => + (AssemblyName, Token) = entity switch { + EcmaType type => (type.Module.Assembly.GetName ().Name, MetadataTokens.GetToken (type.Handle)), + EcmaMethod method => (method.Module.Assembly.GetName ().Name, MetadataTokens.GetToken (method.Handle)), + PropertyPseudoDesc property => (((EcmaType) property.OwningType).Module.Assembly.GetName ().Name, MetadataTokens.GetToken (property.Handle)), + EventPseudoDesc @event => (((EcmaType) @event.OwningType).Module.Assembly.GetName ().Name, MetadataTokens.GetToken (@event.Handle)), + ILStubMethod => (null, 0), // Ignore compiler generated methods + _ => throw new NotSupportedException ($"The infra doesn't support getting a token for {entity} yet.") + }; + + public AssemblyQualifiedToken (IMemberDefinition member) => + (AssemblyName, Token) = member switch { + TypeDefinition type => (type.Module.Assembly.Name.Name, type.MetadataToken.ToInt32 ()), + MethodDefinition method => (method.Module.Assembly.Name.Name, method.MetadataToken.ToInt32 ()), + PropertyDefinition property => (property.Module.Assembly.Name.Name, property.MetadataToken.ToInt32 ()), + EventDefinition @event => (@event.Module.Assembly.Name.Name, @event.MetadataToken.ToInt32 ()), + FieldDefinition field => (field.Module.Assembly.Name.Name, field.MetadataToken.ToInt32 ()), + _ => throw new NotSupportedException ($"The infra doesn't support getting a token for {member} yet.") + }; + + public override int GetHashCode () => AssemblyName == null ? 0 : AssemblyName.GetHashCode () ^ Token.GetHashCode (); + public override string ToString () => $"{AssemblyName}: {Token}"; + public bool Equals (AssemblyQualifiedToken other) => + string.CompareOrdinal (AssemblyName, other.AssemblyName) == 0 && Token == other.Token; + public override bool Equals ([NotNullWhen (true)] object? obj) => ((AssemblyQualifiedToken?) obj)?.Equals (this) == true; + + public bool IsNil => AssemblyName == null; + } + private readonly BaseAssemblyResolver originalsResolver; private readonly ReaderParameters originalReaderParameters; private readonly AssemblyDefinition originalAssembly; diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/AssemblyQualifiedToken.cs b/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/AssemblyQualifiedToken.cs deleted file mode 100644 index af39d8d..0000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/AssemblyQualifiedToken.cs +++ /dev/null @@ -1,51 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System; -using System.Diagnostics.CodeAnalysis; -using System.Reflection.Metadata.Ecma335; -using ILCompiler; -using Internal.IL.Stubs; -using Internal.TypeSystem.Ecma; -using Internal.TypeSystem; -using Mono.Cecil; - -namespace Mono.Linker.Tests.TestCasesRunner -{ - internal readonly struct AssemblyQualifiedToken : IEquatable - { - public string? AssemblyName { get; } - public int Token { get; } - - public AssemblyQualifiedToken (string? assemblyName, int token) => (AssemblyName, Token) = (assemblyName, token); - - public AssemblyQualifiedToken (TypeSystemEntity entity) => - (AssemblyName, Token) = entity switch { - EcmaType type => (type.Module.Assembly.GetName ().Name, MetadataTokens.GetToken (type.Handle)), - EcmaMethod method => (method.Module.Assembly.GetName ().Name, MetadataTokens.GetToken (method.Handle)), - EcmaField field => (field.Module.Assembly.GetName ().Name, MetadataTokens.GetToken (field.Handle)), - PropertyPseudoDesc property => (((EcmaType) property.OwningType).Module.Assembly.GetName ().Name, MetadataTokens.GetToken (property.Handle)), - EventPseudoDesc @event => (((EcmaType) @event.OwningType).Module.Assembly.GetName ().Name, MetadataTokens.GetToken (@event.Handle)), - ILStubMethod => (null, 0), // Ignore compiler generated methods - _ => throw new NotSupportedException ($"The infra doesn't support getting a token for {entity} yet.") - }; - - public AssemblyQualifiedToken (IMemberDefinition member) => - (AssemblyName, Token) = member switch { - TypeDefinition type => (type.Module.Assembly.Name.Name, type.MetadataToken.ToInt32 ()), - MethodDefinition method => (method.Module.Assembly.Name.Name, method.MetadataToken.ToInt32 ()), - PropertyDefinition property => (property.Module.Assembly.Name.Name, property.MetadataToken.ToInt32 ()), - EventDefinition @event => (@event.Module.Assembly.Name.Name, @event.MetadataToken.ToInt32 ()), - FieldDefinition field => (field.Module.Assembly.Name.Name, field.MetadataToken.ToInt32 ()), - _ => throw new NotSupportedException ($"The infra doesn't support getting a token for {member} yet.") - }; - - public override int GetHashCode () => AssemblyName == null ? 0 : AssemblyName.GetHashCode () ^ Token.GetHashCode (); - public override string ToString () => $"{AssemblyName}: {Token}"; - public bool Equals (AssemblyQualifiedToken other) => - string.CompareOrdinal (AssemblyName, other.AssemblyName) == 0 && Token == other.Token; - public override bool Equals ([NotNullWhen (true)] object? obj) => ((AssemblyQualifiedToken?) obj)?.Equals (this) == true; - - public bool IsNil => AssemblyName == null; - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/ResultChecker.cs b/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/ResultChecker.cs index b0c0bdd..090a3a1 100644 --- a/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/ResultChecker.cs +++ b/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/ResultChecker.cs @@ -398,17 +398,10 @@ namespace Mono.Linker.Tests.TestCasesRunner { var origin = mc.Origin; Debug.Assert (origin != null); - if (origin?.MemberDefinition == null) - return false; - if (expectedOriginProvider is not IMemberDefinition expectedOriginMember) - return false; - - var actualOriginToken = new AssemblyQualifiedToken (origin.Value.MemberDefinition); - var expectedOriginToken = new AssemblyQualifiedToken (expectedOriginMember); - if (actualOriginToken.Equals(expectedOriginToken)) + if (NameUtils.GetActualOriginDisplayName (origin?.MemberDefinition) == NameUtils.GetExpectedOriginDisplayName (expectedOriginProvider)) return true; - var actualMember = origin.Value.MemberDefinition; + var actualMember = origin!.Value.MemberDefinition; // Compensate for cases where for some reason the OM doesn't preserve the declaring types // on certain things after trimming. if (actualMember != null && GetOwningType (actualMember) == null && diff --git a/src/tests/nativeaot/SmokeTests/TrimmingBehaviors/DependencyInjectionPattern.cs b/src/tests/nativeaot/SmokeTests/TrimmingBehaviors/DependencyInjectionPattern.cs deleted file mode 100644 index de13a83..0000000 --- a/src/tests/nativeaot/SmokeTests/TrimmingBehaviors/DependencyInjectionPattern.cs +++ /dev/null @@ -1,146 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Reflection; - -public class DependencyInjectionPattern -{ - public static int Run() - { - Services services = new(); - services.RegisterService(typeof(INameProvider<>), typeof(NameProviderService<>)); - services.RegisterService(typeof(IDataObjectPrinter), typeof(DataObjectPrinterService)); - - var printer = services.GetService(); - var actual = printer.GetNameLength(new DataObject() { Name = "0123456789" }); - Assert.Equal(10, actual); - - return 100; - } -} - -public class DataObject -{ - public string Name { get; set; } -} - -// Simplistic implementation of DI which is comparable in behavior to our DI -class Services -{ - private Dictionary _services = new Dictionary(); - - public void RegisterService(Type interfaceType, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type implementationType) - { - _services.Add(interfaceType, implementationType); - } - - public T GetService() - { - return (T)GetService(typeof(T)); - } - - public object GetService(Type interfaceType) - { - Type typeDef = interfaceType.IsGenericType ? interfaceType.GetGenericTypeDefinition() : interfaceType; - Type implementationType = GetImplementationType(typeDef); - - if (implementationType.IsGenericTypeDefinition) - { - for (int i = 0; i < implementationType.GetGenericArguments().Length; i++) - { - Type genericArgument = implementationType.GetGenericArguments()[i]; - Type genericParameter = interfaceType.GetGenericArguments()[i]; - - // Validate that DAM annotations match - if (!DamAnnotationsMatch(genericArgument, genericParameter)) - throw new InvalidOperationException(); - - if (genericParameter.IsValueType) - throw new InvalidOperationException(); - } - - implementationType = InstantiateServiceType(implementationType, interfaceType.GetGenericArguments()); - } - - ConstructorInfo constructor = implementationType.GetConstructors()[0]; // Simplification - if (constructor.GetParameters().Length > 0) - { - List instances = new(); - foreach (var parameter in constructor.GetParameters()) - { - instances.Add(GetService(parameter.ParameterType)); - } - - return Activator.CreateInstance(implementationType, instances.ToArray())!; - } - else - { - return Activator.CreateInstance(implementationType)!; - } - - [UnconditionalSuppressMessage("", "IL2068", Justification = "We only add types with the right annotation to the dictionary")] - [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] - Type GetImplementationType(Type interfaceType) - { - if (!_services.TryGetValue(interfaceType, out Type? implementationType)) - throw new NotImplementedException(); - - return implementationType; - } - - [UnconditionalSuppressMessage("", "IL2055", Justification = "We validated that the type parameters match - THIS IS WRONG")] - [UnconditionalSuppressMessage("", "IL3050", Justification = "We validated there are no value types")] - [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] - Type InstantiateServiceType([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type typeDef, Type[] typeParameters) - { - return typeDef.MakeGenericType(typeParameters); - } - } - - private bool DamAnnotationsMatch(Type argument, Type parameter) - { - // .... - not interesting for this test, it will be true in the cases we use in this test - return true; - } -} - -interface INameProvider<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)] T> -{ - string? GetName(T instance); -} - -class NameProviderService<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)] T> - : INameProvider -{ - public string? GetName(T instance) - { - return (string?)typeof(T).GetProperty("Name")?.GetValue(instance); - } -} - -interface IDataObjectPrinter -{ - int GetNameLength(DataObject instance); -} - -class DataObjectPrinterService : IDataObjectPrinter -{ - // The data flow is not applied on the INameProvider here, or in the method parameter - // or in the call to the GetName below inside Print. - INameProvider _nameProvider; - - public DataObjectPrinterService(INameProvider nameProvider) - { - _nameProvider = nameProvider; - } - - public int GetNameLength(DataObject instance) - { - // This throws because DataObject.Name is not preserved - string? name = _nameProvider.GetName(instance); - return name == null ? 0 : name.Length; - } -} diff --git a/src/tests/nativeaot/SmokeTests/TrimmingBehaviors/Main.cs b/src/tests/nativeaot/SmokeTests/TrimmingBehaviors/Main.cs index 7a46f41..e2c96e8 100644 --- a/src/tests/nativeaot/SmokeTests/TrimmingBehaviors/Main.cs +++ b/src/tests/nativeaot/SmokeTests/TrimmingBehaviors/Main.cs @@ -8,7 +8,6 @@ bool success = RunTest(Dataflow.Run); success &= RunTest(DeadCodeElimination.Run); success &= RunTest(FeatureSwitches.Run); success &= RunTest(ILLinkDescriptor.Run); -success &= RunTest(DependencyInjectionPattern.Run); return success ? 100 : 1; diff --git a/src/tests/nativeaot/SmokeTests/TrimmingBehaviors/TrimmingBehaviors.csproj b/src/tests/nativeaot/SmokeTests/TrimmingBehaviors/TrimmingBehaviors.csproj index 9caa415..d324f0a 100644 --- a/src/tests/nativeaot/SmokeTests/TrimmingBehaviors/TrimmingBehaviors.csproj +++ b/src/tests/nativeaot/SmokeTests/TrimmingBehaviors/TrimmingBehaviors.csproj @@ -11,7 +11,6 @@ - -- 2.7.4