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());
}
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)
{
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)
{
}
}
- 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();
return false;
}
-
- public bool HasGenericParameterAnnotation() => _genericParameterAnnotations != null;
}
private readonly struct MethodAnnotations
namespace ILCompiler.Dataflow
{
- public static class GenericArgumentDataFlow
+ public readonly struct GenericArgumentDataFlow
{
- public static void ProcessGenericArgumentDataFlow(ref DependencyList dependencies, Logger logger, NodeFactory factory, FlowAnnotations annotations, in MessageOrigin origin, TypeDesc type)
- {
- var diagnosticContext = new DiagnosticContext(
- origin,
- !logger.ShouldSuppressAnalysisWarningsForRequires(origin.MemberDefinition, DiagnosticUtilities.RequiresUnreferencedCodeAttribute),
- logger);
- var reflectionMarker = new ReflectionMarker(logger, factory, annotations, typeHierarchyDataFlowOrigin: null, enabled: true);
-
- ProcessGenericArgumentDataFlow(diagnosticContext, reflectionMarker, type);
-
- if (reflectionMarker.Dependencies.Count > 0)
- {
- if (dependencies == null)
- dependencies = reflectionMarker.Dependencies;
- else
- dependencies.AddRange(reflectionMarker.Dependencies);
- }
- }
+ private readonly Logger _logger;
+ private readonly NodeFactory _factory;
+ private readonly FlowAnnotations _annotations;
+ private readonly MessageOrigin _origin;
- public static void ProcessGenericArgumentDataFlow(in DiagnosticContext diagnosticContext, ReflectionMarker reflectionMarker, TypeDesc type)
+ public GenericArgumentDataFlow(Logger logger, NodeFactory factory, FlowAnnotations annotations, in MessageOrigin origin)
{
- TypeDesc typeDefinition = type.GetTypeDefinition();
- if (typeDefinition != type)
- {
- ProcessGenericInstantiation(diagnosticContext, reflectionMarker, type.Instantiation, typeDefinition.Instantiation);
- }
+ _logger = logger;
+ _factory = factory;
+ _annotations = annotations;
+ _origin = origin;
}
- public static void ProcessGenericArgumentDataFlow(in DiagnosticContext diagnosticContext, ReflectionMarker reflectionMarker, MethodDesc method)
+ public DependencyList ProcessGenericArgumentDataFlow(GenericParameterDesc genericParameter, TypeDesc genericArgument)
{
- MethodDesc typicalMethod = method.GetTypicalMethodDefinition();
- if (typicalMethod != method)
- {
- ProcessGenericInstantiation(diagnosticContext, reflectionMarker, method.Instantiation, typicalMethod.Instantiation);
- }
+ var genericParameterValue = _annotations.GetGenericParameterValue(genericParameter);
+ Debug.Assert(genericParameterValue.DynamicallyAccessedMemberTypes != DynamicallyAccessedMemberTypes.None);
- ProcessGenericArgumentDataFlow(diagnosticContext, reflectionMarker, method.OwningType);
- }
+ MultiValue genericArgumentValue = _annotations.GetTypeValueFromGenericArgument(genericArgument);
- public static void ProcessGenericArgumentDataFlow(in DiagnosticContext diagnosticContext, ReflectionMarker reflectionMarker, FieldDesc field)
- {
- ProcessGenericArgumentDataFlow(diagnosticContext, reflectionMarker, field.OwningType);
+ var diagnosticContext = new DiagnosticContext(
+ _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;
}
}
}
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);
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)
{
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
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))
}
- /// <summary>
- /// 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.
- /// </summary>
- /// <remarks>
- /// 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.
- /// </remarks>
- protected abstract MultiValue HandleGetField(MethodIL methodBody, int offset, FieldDesc field);
+ protected abstract MultiValue GetFieldValue(FieldDesc field);
private void ScanLdfld(
MethodIL methodBody,
}
else
{
- value = HandleGetField(methodBody, offset, field);
+ value = GetFieldValue(field);
}
currentStack.Push(new StackSlot(value));
}
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.
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);
}
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)
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(
}
/// <summary>
- /// Called when type is accessed directly (basically only ldtoken)
- /// </summary>
- protected abstract void HandleTypeReflectionAccess(MethodIL methodBody, int offset, TypeDesc accessedType);
-
- /// <summary>
/// Called to handle reflection access to a method without any other specifics (ldtoken or ldftn for example)
/// </summary>
protected abstract void HandleMethodReflectionAccess(MethodIL methodBody, int offset, MethodDesc accessedMethod);
var dereferencedMethodParams = new List<MultiValue>();
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,
private MethodParameterValue GetMethodParameterValue(ParameterProxy parameter, DynamicallyAccessedMemberTypes dynamicallyAccessedMemberTypes)
=> _annotations.GetMethodParameterValue(parameter, dynamicallyAccessedMemberTypes);
- /// <summary>
- /// 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.
- /// </summary>
- 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)
{
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)
_origin
));
- ProcessGenericArgumentDataFlow(calledMethod);
-
var diagnosticContext = new DiagnosticContext(_origin, diagnosticsEnabled: false, _logger);
return HandleCall(
callingMethodBody,
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)
+++ /dev/null
-// 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;
- }
- }
- }
-}
private readonly Dictionary<(MessageOrigin, bool), TrimAnalysisAssignmentPattern> AssignmentPatterns;
private readonly Dictionary<MessageOrigin, TrimAnalysisMethodCallPattern> MethodCallPatterns;
private readonly Dictionary<(MessageOrigin, TypeSystemEntity), TrimAnalysisReflectionAccessPattern> ReflectionAccessPatterns;
- private readonly Dictionary<(MessageOrigin, TypeSystemEntity), TrimAnalysisGenericInstantiationAccessPattern> GenericInstantiations;
private readonly ValueSetLattice<SingleValue> Lattice;
private readonly Logger _logger;
AssignmentPatterns = new Dictionary<(MessageOrigin, bool), TrimAnalysisAssignmentPattern>();
MethodCallPatterns = new Dictionary<MessageOrigin, TrimAnalysisMethodCallPattern>();
ReflectionAccessPatterns = new Dictionary<(MessageOrigin, TypeSystemEntity), TrimAnalysisReflectionAccessPattern>();
- GenericInstantiations = new Dictionary<(MessageOrigin, TypeSystemEntity), TrimAnalysisGenericInstantiationAccessPattern>();
Lattice = lattice;
_logger = logger;
}
{
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)
foreach (var pattern in ReflectionAccessPatterns.Values)
pattern.MarkAndProduceDiagnostics(reflectionMarker, _logger);
-
- foreach (var pattern in GenericInstantiations.Values)
- pattern.MarkAndProduceDiagnostics(reflectionMarker, _logger);
}
}
}
// 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
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);
}
}
}
}
}
- // 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);
+++ /dev/null
-// 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;
-
-namespace ILCompiler.DependencyAnalysis
-{
- public class DataflowAnalyzedTypeDefinitionNode : DependencyNodeCore<NodeFactory>
- {
- 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<DependencyListEntry> GetStaticDependencies(NodeFactory factory)
- {
- var mdManager = (UsageBasedMetadataManager)factory.MetadataManager;
-
- DependencyList dependencies = null;
-
- if (_typeDefinition.HasBaseType)
- {
- GetDataFlowDependenciesForInstantiation(ref dependencies, mdManager.Logger, factory, mdManager.FlowAnnotations, _typeDefinition.BaseType, _typeDefinition);
- }
-
- if (_typeDefinition is MetadataType metadataType)
- {
- foreach (var interfaceType in metadataType.ExplicitlyImplementedInterfaces)
- {
- GetDataFlowDependenciesForInstantiation(ref dependencies, mdManager.Logger, factory, mdManager.FlowAnnotations, interfaceType, _typeDefinition);
- }
- }
-
- return dependencies;
- }
-
- private static void GetDataFlowDependenciesForInstantiation(
- ref DependencyList dependencies,
- Logger logger,
- NodeFactory factory,
- FlowAnnotations flowAnnotations,
- TypeDesc type,
- TypeDesc contextType)
- {
- TypeDesc instantiatedType = type.InstantiateSignature(contextType.Instantiation, Instantiation.Empty);
- GenericArgumentDataFlow.ProcessGenericArgumentDataFlow(ref dependencies, logger, factory, flowAnnotations, new Logging.MessageOrigin(contextType), instantiatedType);
- }
-
- 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<CombinedDependencyListEntry> GetConditionalStaticDependencies(NodeFactory context) => null;
- public override IEnumerable<CombinedDependencyListEntry> SearchDynamicDependencies(List<DependencyNodeCore<NodeFactory>> markedNodes, int firstNode, NodeFactory context) => null;
- }
-}
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)
{
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;
}
}
}
+ factory.MetadataManager.GetDependenciesForGenericDictionary(ref result, factory, _owningType);
+
return result;
}
return new DataflowAnalyzedMethodNode(il.MethodIL);
});
- _dataflowAnalyzedTypeDefinitions = new NodeCache<TypeDesc, DataflowAnalyzedTypeDefinitionNode>((TypeDesc type) =>
- {
- return new DataflowAnalyzedTypeDefinitionNode(type);
- });
-
_dynamicDependencyAttributesOnEntities = new NodeCache<TypeSystemEntity, DynamicDependencyAttributesOnEntityNode>((TypeSystemEntity entity) =>
{
return new DynamicDependencyAttributesOnEntityNode(entity);
return _dataflowAnalyzedMethods.GetOrAdd(new MethodILKey(methodIL));
}
- private NodeCache<TypeDesc, DataflowAnalyzedTypeDefinitionNode> _dataflowAnalyzedTypeDefinitions;
-
- public DataflowAnalyzedTypeDefinitionNode DataflowAnalyzedTypeDefinition(TypeDesc type)
- {
- return _dataflowAnalyzedTypeDefinitions.GetOrAdd(type);
- }
-
private NodeCache<TypeSystemEntity, DynamicDependencyAttributesOnEntityNode> _dynamicDependencyAttributesOnEntities;
public DynamicDependencyAttributesOnEntityNode DynamicDependencyAttributesOnEntity(TypeSystemEntity entity)
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;
/// <summary>
/// This method is an extension point that can provide additional metadata-based dependencies to generated EETypes.
/// </summary>
- 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);
{
}
+ public virtual void GetDependenciesForGenericDictionary(ref DependencyList dependencies, NodeFactory factory, TypeDesc type)
+ {
+ }
+
public virtual void NoteOverridingMethod(MethodDesc baseMethod, MethodDesc overridingMethod)
{
}
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
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)
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)
{
}
}
+ 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;
<Compile Include="Compiler\Dataflow\RequireDynamicallyAccessedMembersAction.cs" />
<Compile Include="Compiler\Dataflow\ScannerExtensions.cs" />
<Compile Include="Compiler\Dataflow\TrimAnalysisAssignmentPattern.cs" />
- <Compile Include="Compiler\Dataflow\TrimAnalysisGenericInstantiationAccessPattern.cs" />
<Compile Include="Compiler\Dataflow\TrimAnalysisMethodCallPattern.cs" />
<Compile Include="Compiler\Dataflow\TrimAnalysisPatternStore.cs" />
<Compile Include="Compiler\Dataflow\TrimAnalysisReflectionAccessPattern.cs" />
<Compile Include="Compiler\DependencyAnalysis\CustomAttributeMetadataNode.cs" />
<Compile Include="Compiler\DependencyAnalysis\EmbeddedTrimmingDescriptorNode.cs" />
<Compile Include="Compiler\DependencyAnalysis\DataflowAnalyzedMethodNode.cs" />
- <Compile Include="Compiler\DependencyAnalysis\DataflowAnalyzedTypeDefinitionNode.cs" />
<Compile Include="Compiler\DependencyAnalysis\DefaultConstructorMapNode.cs" />
<Compile Include="Compiler\DependencyAnalysis\DelegateMarshallingDataNode.cs" />
<Compile Include="Compiler\DependencyAnalysis\DynamicDependencyAttributesOnEntityNode.cs" />
+++ /dev/null
-// 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<object> ();
- TestStructConstraintSatisfiesParameterlessConstructor<TestStruct> ();
- TestUnmanagedConstraintSatisfiesParameterlessConstructor<byte> ();
-
- TestGenericParameterFlowsToField ();
- TestGenericParameterFlowsToReturnValue ();
-
- TestNoWarningsInRUCMethod<TestType> ();
- TestNoWarningsInRUCType<TestType, TestType> ();
- }
-
- static void TestSingleGenericParameterOnType ()
- {
- TypeRequiresNothing<TestType>.Test ();
- TypeRequiresPublicFields<TestType>.Test ();
- TypeRequiresPublicMethods<TestType>.Test ();
- TypeRequiresPublicFieldsPassThrough<TestType>.Test ();
- TypeRequiresNothingPassThrough<TestType>.Test ();
- }
-
- static void TestGenericParameterFlowsToReturnValue ()
- {
- _ = TypeRequiresPublicFields<TestType>.ReturnRequiresPublicFields ();
- _ = TypeRequiresPublicFields<TestType>.ReturnRequiresPublicMethods ();
- _ = TypeRequiresPublicFields<TestType>.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<T>), 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<T>), 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<T>), 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<T>
- {
- [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<TSource>",
- "T",
- "Mono.Linker.Tests.Cases.DataFlow.GenericParameterDataFlow.TypeRequiresPublicMethods<T>")]
- public static void Test ()
- {
- TypeRequiresPublicFields<TSource>.Test ();
- TypeRequiresPublicMethods<TSource>.Test ();
- TypeRequiresNothing<TSource>.Test ();
- }
- }
-
- class TypeRequiresNothingPassThrough<T>
- {
- [ExpectedWarning ("IL2091", nameof (TypeRequiresPublicFields<T>))]
- [ExpectedWarning ("IL2091", nameof (TypeRequiresPublicMethods<T>))]
- public static void Test ()
- {
- TypeRequiresPublicFields<T>.Test ();
- TypeRequiresPublicMethods<T>.Test ();
- TypeRequiresNothing<T>.Test ();
- }
- }
-
- static void TestBaseTypeGenericRequirements ()
- {
- new DerivedTypeWithInstantiatedGenericOnBase ();
- new DerivedTypeWithInstantiationOverSelfOnBase ();
- new DerivedTypeWithOpenGenericOnBase<TestType> ();
- TestDerivedTypeWithOpenGenericOnBaseWithRUCOnBase ();
- TestDerivedTypeWithOpenGenericOnBaseWithRUCOnDerived ();
- new DerivedTypeWithOpenGenericOnBaseWithRequirements<TestType> ();
- }
-
- /// <summary>
- /// Adding a comment to verify that analyzer doesn't null ref when trying to analyze
- /// generic parameter in cref comments on a class
- /// <see cref="GenericBaseTypeWithRequirements{T}"/>
- /// </summary>
- class GenericBaseTypeWithRequirements<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] T>
- {
- public GenericBaseTypeWithRequirements ()
- {
- typeof (T).RequiresPublicFields ();
- }
- }
-
- class DerivedTypeWithInstantiatedGenericOnBase : GenericBaseTypeWithRequirements<TestType>
- {
- }
-
- class DerivedTypeWithInstantiationOverSelfOnBase : GenericBaseTypeWithRequirements<DerivedTypeWithInstantiationOverSelfOnBase>
- {
- }
-
- [ExpectedWarning ("IL2091", nameof (GenericBaseTypeWithRequirements<T>))]
- class DerivedTypeWithOpenGenericOnBase<T> : GenericBaseTypeWithRequirements<T>
- {
- // Analyzer does not see the base class constructor
- [ExpectedWarning ("IL2091", nameof (GenericBaseTypeWithRequirements<T>), ProducedBy = ProducedBy.Trimmer | ProducedBy.NativeAot)]
- public DerivedTypeWithOpenGenericOnBase () { }
- }
-
- static void TestDerivedTypeWithOpenGenericOnBaseWithRUCOnBase ()
- {
- new DerivedTypeWithOpenGenericOnBaseWithRUCOnBase<TestType> ();
- }
-
- // https://github.com/dotnet/runtime/issues/81158
- [ExpectedWarning ("IL2109", nameof (BaseTypeWithOpenGenericDAMTAndRUC<T>), ProducedBy = ProducedBy.Trimmer | ProducedBy.Analyzer)]
- [ExpectedWarning ("IL2091", nameof (BaseTypeWithOpenGenericDAMTAndRUC<T>))]
- class DerivedTypeWithOpenGenericOnBaseWithRUCOnBase<T> : BaseTypeWithOpenGenericDAMTAndRUC<T>
- {
- [ExpectedWarning ("IL2091", nameof (DerivedTypeWithOpenGenericOnBaseWithRUCOnBase<T>), ProducedBy = ProducedBy.Trimmer | ProducedBy.NativeAot)]
- [ExpectedWarning ("IL2026", nameof (BaseTypeWithOpenGenericDAMTAndRUC<T>), ProducedBy = ProducedBy.Trimmer | ProducedBy.NativeAot)]
- public DerivedTypeWithOpenGenericOnBaseWithRUCOnBase () { }
- }
-
- [RequiresUnreferencedCode ("RUC")]
- class BaseTypeWithOpenGenericDAMTAndRUC<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)] T> { }
-
-
- [ExpectedWarning ("IL2026", nameof (DerivedTypeWithOpenGenericOnBaseWithRUCOnDerived<TestType>))]
- static void TestDerivedTypeWithOpenGenericOnBaseWithRUCOnDerived ()
- {
- new DerivedTypeWithOpenGenericOnBaseWithRUCOnDerived<TestType> ();
- }
- [ExpectedWarning ("IL2091", nameof (BaseTypeWithOpenGenericDAMT<T>))]
- [RequiresUnreferencedCode ("RUC")]
- class DerivedTypeWithOpenGenericOnBaseWithRUCOnDerived<T> : BaseTypeWithOpenGenericDAMT<T>
- {
- }
-
- class BaseTypeWithOpenGenericDAMT<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)] T> { }
-
-
- class DerivedTypeWithOpenGenericOnBaseWithRequirements<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] T>
- : GenericBaseTypeWithRequirements<T>
- {
- }
-
- static void TestMultipleGenericParametersOnType ()
- {
- MultipleTypesWithDifferentRequirements<TestType, TestType, TestType, TestType>.TestMultiple ();
- MultipleTypesWithDifferentRequirements<TestType, TestType, TestType, TestType>.TestFields ();
- MultipleTypesWithDifferentRequirements<TestType, TestType, TestType, TestType>.TestMethods ();
- MultipleTypesWithDifferentRequirements<TestType, TestType, TestType, TestType>.TestBoth ();
- MultipleTypesWithDifferentRequirements<TestType, TestType, TestType, TestType>.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<TestType>.InnerTypeWithNoAddedGenerics.TestAccess ();
- }
-
- class RootTypeWithRequirements<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TRoot>
- {
- public class InnerTypeWithNoAddedGenerics
- {
- [ExpectedWarning ("IL2087", nameof (TRoot),
- "Mono.Linker.Tests.Cases.DataFlow.GenericParameterDataFlow.RootTypeWithRequirements<TRoot>",
- "type",
- "DataFlowTypeExtensions.RequiresPublicMethods(Type)")]
- public static void TestAccess ()
- {
- typeof (TRoot).RequiresPublicFields ();
- typeof (TRoot).RequiresPublicMethods ();
- }
- }
- }
-
- static void TestInterfaceTypeGenericRequirements ()
- {
- IGenericInterfaceTypeWithRequirements<TestType> instance = new InterfaceImplementationTypeWithInstantiatedGenericOnBase ();
- new InterfaceImplementationTypeWithInstantiationOverSelfOnBase ();
- new InterfaceImplementationTypeWithOpenGenericOnBase<TestType> ();
- new InterfaceImplementationTypeWithOpenGenericOnBaseWithRequirements<TestType> ();
-
- RecursiveGenericWithInterfacesRequirement.Test ();
- }
-
- interface IGenericInterfaceTypeWithRequirements<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] T>
- {
- }
-
- class InterfaceImplementationTypeWithInstantiatedGenericOnBase : IGenericInterfaceTypeWithRequirements<TestType>
- {
- }
-
- interface IGenericInterfaceTypeWithRequiresAll<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)] T>
- {
- }
-
- class InterfaceImplementationTypeWithInstantiationOverSelfOnBase : IGenericInterfaceTypeWithRequiresAll<InterfaceImplementationTypeWithInstantiationOverSelfOnBase>
- {
- }
-
- [ExpectedWarning ("IL2091", nameof (IGenericInterfaceTypeWithRequirements<T>))]
- class InterfaceImplementationTypeWithOpenGenericOnBase<T> : IGenericInterfaceTypeWithRequirements<T>
- {
- }
- class InterfaceImplementationTypeWithOpenGenericOnBaseWithRequirements<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] T>
- : IGenericInterfaceTypeWithRequirements<T>
- {
- }
-
- class RecursiveGenericWithInterfacesRequirement
- {
- interface IFace<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.Interfaces)] T>
- {
- }
-
- class TestType : IFace<TestType>
- {
- }
-
- public static void Test ()
- {
- var a = typeof (IFace<string>);
- var t = new TestType ();
- }
- }
-
- static void TestTypeGenericRequirementsOnMembers ()
- {
- // Basically just root everything we need to test
- var instance = new TypeGenericRequirementsOnMembers<TestType> ();
-
- _ = 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<TOuter> PublicFieldsField;
-
- [ExpectedWarning ("IL2091", nameof (TypeRequiresPublicMethods<TOuter>), ProducedBy = ProducedBy.Trimmer | ProducedBy.Analyzer)] // NativeAOT_StorageSpaceType
- public TypeRequiresPublicMethods<TOuter> PublicMethodsField;
-
- public TypeRequiresPublicFields<TOuter> PublicFieldsProperty {
- get;
- set;
- }
-
- [ExpectedWarning ("IL2091", nameof (TypeGenericRequirementsOnMembers<TOuter>), ProducedBy = ProducedBy.Analyzer)]
- public TypeRequiresPublicMethods<TOuter> PublicMethodsProperty {
- [ExpectedWarning ("IL2091", nameof (TypeRequiresPublicMethods<TOuter>), ProducedBy = ProducedBy.Trimmer)] // NativeAOT_StorageSpaceType
- get => null;
- [ExpectedWarning ("IL2091", nameof (TypeRequiresPublicMethods<TOuter>), ProducedBy = ProducedBy.Trimmer)] // NativeAOT_StorageSpaceType
- set { }
- }
-
- public void PublicFieldsMethodParameter (TypeRequiresPublicFields<TOuter> param) { }
- [ExpectedWarning ("IL2091", nameof (TypeRequiresPublicMethods<TOuter>), ProducedBy = ProducedBy.Trimmer | ProducedBy.Analyzer)] // NativeAOT_StorageSpaceType
- public void PublicMethodsMethodParameter (TypeRequiresPublicMethods<TOuter> param) { }
-
- public TypeRequiresPublicFields<TOuter> PublicFieldsMethodReturnValue () { return null; }
-
- [ExpectedWarning ("IL2091", nameof (TypeRequiresPublicMethods<TOuter>), ProducedBy = ProducedBy.Trimmer)] // NativeAOT_StorageSpaceType
- [ExpectedWarning ("IL2091", nameof (TypeRequiresPublicMethods<TOuter>), ProducedBy = ProducedBy.Trimmer | ProducedBy.Analyzer)] // NativeAOT_StorageSpaceType
- public TypeRequiresPublicMethods<TOuter> PublicMethodsMethodReturnValue () { return null; }
-
- public void PublicFieldsMethodLocalVariable ()
- {
- TypeRequiresPublicFields<TOuter> t = null;
- }
-
- [ExpectedWarning ("IL2091", nameof (TypeRequiresPublicMethods<TOuter>), ProducedBy = ProducedBy.Trimmer | ProducedBy.Analyzer)] // NativeAOT_StorageSpaceType
- public void PublicMethodsMethodLocalVariable ()
- {
- TypeRequiresPublicMethods<TOuter> t = null;
- }
- }
-
- static void TestPartialInstantiationTypes ()
- {
- _ = new PartialyInstantiatedFields<TestType> ();
- _ = new FullyInstantiatedOverPartiallyInstantiatedFields ();
- _ = new PartialyInstantiatedMethods<TestType> ();
- _ = new FullyInstantiatedOverPartiallyInstantiatedMethods ();
- }
-
- class BaseForPartialInstantiation<
- [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TFields,
- [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TMethods>
- {
- }
-
- class PartialyInstantiatedFields<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TOuter>
- : BaseForPartialInstantiation<TOuter, TestType>
- {
- }
-
- class FullyInstantiatedOverPartiallyInstantiatedFields
- : PartialyInstantiatedFields<TestType>
- {
- }
-
- [ExpectedWarning ("IL2091", nameof (BaseForPartialInstantiation<TestType, TOuter>), "'TMethods'")]
- class PartialyInstantiatedMethods<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TOuter>
- : BaseForPartialInstantiation<TestType, TOuter>
- {
- // Analyzer does not see the base class constructor
- [ExpectedWarning ("IL2091", nameof (BaseForPartialInstantiation<TestType, TOuter>), "'TMethods'", ProducedBy = ProducedBy.Trimmer | ProducedBy.NativeAot)]
- public PartialyInstantiatedMethods () { }
- }
-
- class FullyInstantiatedOverPartiallyInstantiatedMethods
- : PartialyInstantiatedMethods<TestType>
- {
- }
-
- static void TestSingleGenericParameterOnMethod ()
- {
- MethodRequiresPublicFields<TestType> ();
- MethodRequiresPublicMethods<TestType> ();
- MethodRequiresNothing<TestType> ();
- MethodRequiresPublicFieldsPassThrough<TestType> ();
- MethodRequiresNothingPassThrough<TestType> ();
- }
-
- /// <summary>
- /// Adding a comment to verify that analyzer doesn't null ref when trying to analyze
- /// generic parameter comments on a method
- /// <see cref="MethodRequiresPublicFields{T}"/>
- /// </summary>
- [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<T> ()
- {
- typeof (T).RequiresPublicFields ();
- typeof (T).RequiresPublicMethods ();
- typeof (T).RequiresNone ();
- }
-
- [ExpectedWarning ("IL2091", nameof (MethodRequiresPublicMethods), "'T'")]
- static void MethodRequiresPublicFieldsPassThrough<
- [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] T> ()
- {
- MethodRequiresPublicFields<T> ();
- MethodRequiresPublicMethods<T> ();
- MethodRequiresNothing<T> ();
- }
-
- [ExpectedWarning ("IL2091", nameof (MethodRequiresPublicFields), "'T'")]
- [ExpectedWarning ("IL2091", nameof (MethodRequiresPublicMethods), "'T'")]
- static void MethodRequiresNothingPassThrough<T> ()
- {
- MethodRequiresPublicFields<T> ();
- MethodRequiresPublicMethods<T> ();
- MethodRequiresNothing<T> ();
- }
-
- static void TestMultipleGenericParametersOnMethod ()
- {
- MethodMultipleWithDifferentRequirements_TestMultiple<TestType, TestType, TestType, TestType> ();
- MethodMultipleWithDifferentRequirements_TestFields<TestType, TestType, TestType, TestType> ();
- MethodMultipleWithDifferentRequirements_TestMethods<TestType, TestType, TestType, TestType> ();
- MethodMultipleWithDifferentRequirements_TestBoth<TestType, TestType, TestType, TestType> ();
- MethodMultipleWithDifferentRequirements_TestNothing<TestType, TestType, TestType, TestType> ();
- }
-
- 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<TestType>.StaticRequiresPublicFields<TestType> ();
- TypeWithInstantiatedGenericMethodViaGenericParameter<TestType>.StaticRequiresPublicFieldsNonGeneric ();
-
- TypeWithInstantiatedGenericMethodViaGenericParameter<TestType>.StaticPartialInstantiation ();
- TypeWithInstantiatedGenericMethodViaGenericParameter<TestType>.StaticPartialInstantiationUnrecognized ();
-
- var instance = new TypeWithInstantiatedGenericMethodViaGenericParameter<TestType> ();
-
- instance.InstanceRequiresPublicFields<TestType> ();
- instance.InstanceRequiresPublicFieldsNonGeneric ();
-
- instance.VirtualRequiresPublicFields<TestType> ();
- instance.VirtualRequiresPublicMethods<TestType> ();
-
- instance.CallInterface ();
-
- IInterfaceWithGenericMethod interfaceInstance = (IInterfaceWithGenericMethod) instance;
- interfaceInstance.InterfaceRequiresPublicFields<TestType> ();
- interfaceInstance.InterfaceRequiresPublicMethods<TestType> ();
- }
-
- 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<TOuter>.StaticRequiresPublicFields<TInner>()",
- "'T'",
- "Mono.Linker.Tests.Cases.DataFlow.GenericParameterDataFlow.BaseTypeWithGenericMethod.StaticRequiresPublicMethods<T>()")]
- public static void StaticRequiresPublicFields<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TInner> ()
- {
- StaticRequiresPublicFields<TInner> ();
- StaticRequiresPublicMethods<TInner> ();
- }
-
- [ExpectedWarning ("IL2091",
- "'TOuter'",
- "Mono.Linker.Tests.Cases.DataFlow.GenericParameterDataFlow.TypeWithInstantiatedGenericMethodViaGenericParameter<TOuter>",
- "'T'",
- "Mono.Linker.Tests.Cases.DataFlow.GenericParameterDataFlow.BaseTypeWithGenericMethod.StaticRequiresPublicMethods<T>()")]
- public static void StaticRequiresPublicFieldsNonGeneric ()
- {
- StaticRequiresPublicFields<TOuter> ();
- StaticRequiresPublicMethods<TOuter> ();
- }
-
- public static void StaticPartialInstantiation ()
- {
- StaticRequiresMultipleGenericParams<TOuter, TestType> ();
- }
-
- [ExpectedWarning ("IL2091",
- nameof (TOuter),
- "Mono.Linker.Tests.Cases.DataFlow.GenericParameterDataFlow.TypeWithInstantiatedGenericMethodViaGenericParameter<TOuter>",
- "TMethods",
- "Mono.Linker.Tests.Cases.DataFlow.GenericParameterDataFlow.BaseTypeWithGenericMethod.StaticRequiresMultipleGenericParams<TFields, TMethods>()",
- 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<TestType, TOuter> ();
- }
-
- [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<TInner> ();
- InstanceRequiresPublicMethods<TInner> ();
- }
-
- [ExpectedWarning ("IL2091",
- "'TOuter'",
- "Mono.Linker.Tests.Cases.DataFlow.GenericParameterDataFlow.TypeWithInstantiatedGenericMethodViaGenericParameter",
- "'T'",
- "Mono.Linker.Tests.Cases.DataFlow.GenericParameterDataFlow.BaseTypeWithGenericMethod.InstanceRequiresPublicMethods")]
- public void InstanceRequiresPublicFieldsNonGeneric ()
- {
- InstanceRequiresPublicFields<TOuter> ();
- InstanceRequiresPublicMethods<TOuter> ();
- }
-
- 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<TOuter> ();
- interfaceInstance.InterfaceRequiresPublicMethods<TOuter> ();
- }
- }
-
- static void TestNewConstraintSatisfiesParameterlessConstructor<T> () where T : new()
- {
- RequiresParameterlessConstructor<T> ();
- }
-
- static void TestStructConstraintSatisfiesParameterlessConstructor<T> () where T : struct
- {
- RequiresParameterlessConstructor<T> ();
- }
- static void TestUnmanagedConstraintSatisfiesParameterlessConstructor<T> () where T : unmanaged
- {
- RequiresParameterlessConstructor<T> ();
- }
-
- 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<T> ()
- {
- TypeRequiresPublicFields<T>.RUCTest ();
- RUCMethodRequiresPublicMethods<T> ();
- }
-
- // 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<T>
- [ExpectedWarning ("IL2091", "RUCTypeRequiresPublicFields")] // StaticMethodRequiresPublicMethods<U>
- [ExpectedWarning ("IL2091", "RUCTypeRequiresPublicFields")] // RUCTypeRequiresPublicFields<T> ctor
- [ExpectedWarning ("IL2091", "RUCTypeRequiresPublicFields", ProducedBy = ProducedBy.Trimmer)] // RUCTypeRequiresPublicFields<T> local, // NativeAOT_StorageSpaceType
- [ExpectedWarning ("IL2091", "RUCTypeRequiresPublicFields", ProducedBy = ProducedBy.Trimmer)] // InstanceMethod, // NativeAOT_StorageSpaceType
- [ExpectedWarning ("IL2091", "RUCTypeRequiresPublicFields", ProducedBy = ProducedBy.Trimmer | ProducedBy.NativeAot)] // InstanceMethodRequiresPublicMethods<T>
- [ExpectedWarning ("IL2091", "RUCTypeRequiresPublicFields", ProducedBy = ProducedBy.Trimmer)] // VirtualMethod, // NativeAOT_StorageSpaceType
- [ExpectedWarning ("IL2091", "RUCTypeRequiresPublicFields", ProducedBy = ProducedBy.Trimmer | ProducedBy.NativeAot)] // VirtualMethodRequiresPublicMethods<T>
- static void TestNoWarningsInRUCType<T, U> ()
- {
- RUCTypeRequiresPublicFields<T>.StaticMethod ();
- RUCTypeRequiresPublicFields<T>.StaticMethodRequiresPublicMethods<T> ();
- RUCTypeRequiresPublicFields<U>.StaticMethodRequiresPublicMethods<T> ();
- RUCTypeRequiresPublicFields<int>.StaticMethodRequiresPublicMethods<string> ();
- var rucType = new RUCTypeRequiresPublicFields<T> ();
- rucType.InstanceMethod ();
- rucType.InstanceMethodRequiresPublicMethods<T> ();
- rucType.VirtualMethod ();
- rucType.VirtualMethodRequiresPublicMethods<T> ();
- }
-
- [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<TestType>.TestFields ();
- }
-
- public class TestType
- {
- }
- public struct TestStruct
- {
- }
-
- }
-}
+++ /dev/null
-// 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;
-
-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 ();
- FieldDefinition.Test ();
- PropertyDefinition.Test ();
- MethodBody.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<TestType> { }
-
- // No warning - annotations match
- class DerivedWithMatchingAnnotation<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods)] TAllMethods>
- : BaseWithPublicMethods<TAllMethods>
- { }
-
- [ExpectedWarning ("IL2091")]
- class DerivedWithNoAnnotations<TUnknown>
- : BaseWithPublicMethods<TUnknown>
- {
- [ExpectedWarning ("IL2091")] // Compiler generates an implicit call to BaseWithPublicMethods<TUnknown>..ctor
- public DerivedWithNoAnnotations () { }
- }
-
- [ExpectedWarning ("IL2091")]
- class DerivedWithMismatchAnnotation<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TPublicFields>
- : BaseWithPublicMethods<TPublicFields>
- { }
-
- [ExpectedWarning ("IL2091", nameof (DynamicallyAccessedMemberTypes.PublicMethods))]
- class DerivedWithOneMismatch<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TPublicFields>
- : BaseWithTwo<TPublicFields, TPublicFields>
- { }
-
- class DerivedWithTwoMatching<
- [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TPublicFields,
- [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods>
- : BaseWithTwo<TPublicMethods, TPublicFields>
- { }
-
- [ExpectedWarning ("IL2091")]
- class DerivedWithOnlyStaticMethodReference<TUnknown> : BaseWithPublicMethods<TUnknown>
- {
- // The method body in this case looks like:
- // BaseWithPublicMethods<TUnknown>.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<TUnknown> ()
- {
- object a;
- a = new DerivedWithMatchingAnnotation<TUnknown> (); // IL2091 due to the instantiation
- a = new DerivedWithNoAnnotations<TUnknown> ();
- }
-
- 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<TestType> ();
- a = new DerivedWithMatchingAnnotation<string> ();
-
- // Also try with unannotated type parameter
- TestWithUnannotatedTypeArgument<TestType> ();
-
- DerivedWithOnlyStaticMethodReference<TestType>.GetDerivedMethods ();
- }
- }
-
- class TypeImplementingInterface
- {
- interface IWithPublicMethods<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> { }
-
- interface IWithPublicFields<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TPublicFields> { }
-
- // No warning - annotations applied
- class ImplementsWithSpecificType : IWithPublicMethods<TestType>, IWithPublicFields<TestType> { }
-
- // No warning - matching annotations
- class ImplementsWithMatchingAnnotation<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)] TAll>
- : IWithPublicMethods<TAll>, IWithPublicFields<TAll>
- { }
-
- [ExpectedWarning ("IL2091", nameof (DynamicallyAccessedMemberTypes.PublicFields))]
- class ImplementsWithOneMismatch<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods>
- : IWithPublicMethods<TPublicMethods>, IWithPublicFields<TPublicMethods>
- { }
-
- [ExpectedWarning ("IL2091", nameof (DynamicallyAccessedMemberTypes.PublicMethods))]
- [ExpectedWarning ("IL2091", nameof (DynamicallyAccessedMemberTypes.PublicFields))]
- class ImplementsWithTwoMismatches<
- [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods,
- [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TPublicFields>
- : IWithPublicMethods<TPublicFields>, IWithPublicFields<TPublicMethods>
- { }
-
- public static void Test ()
- {
- // Instantiate the types
- new ImplementsWithSpecificType ();
- new ImplementsWithMatchingAnnotation<TestType> ();
- new ImplementsWithOneMismatch<TestType> ();
- new ImplementsWithTwoMismatches<TestType, TestType> ();
-
- // 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<TestType> one, IWithTwo<TestType, TestType> two) { }
-
- [ExpectedWarning ("IL2091", ProducedBy = ProducedBy.Trimmer | ProducedBy.Analyzer)] // NativeAOT_StorageSpaceType
- static void MethodWithOneMismatch<TUnknown> (TypeWithPublicMethods<TUnknown> one) { }
-
- [ExpectedWarning ("IL2091", nameof (IWithTwo<TestType, TestType>), ProducedBy = ProducedBy.Trimmer | ProducedBy.Analyzer)] // NativeAOT_StorageSpaceType
- [ExpectedWarning ("IL2091", nameof (TypeWithPublicMethods<TestType>), ProducedBy = ProducedBy.Trimmer | ProducedBy.Analyzer)] // NativeAOT_StorageSpaceType
- static void MethodWithTwoMismatches<
- [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TPublicFields,
- [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods>
- (IWithTwo<TPublicMethods, TPublicMethods> two, TypeWithPublicMethods<TPublicFields> one)
- { }
-
- static TypeWithPublicMethods<TestType> MethodWithSpecificReturnType () => null;
-
- static TypeWithPublicMethods<TPublicMethods> MethodWithMatchingReturn<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> () => null;
-
- [ExpectedWarning ("IL2091", ProducedBy = ProducedBy.Trimmer | ProducedBy.Analyzer)] // NativeAOT_StorageSpaceType
- static TypeWithPublicMethods<TUnknown> MethodWithOneMismatchReturn<TUnknown> () => null;
-
- [ExpectedWarning ("IL2091", ProducedBy = ProducedBy.Trimmer | ProducedBy.Analyzer)] // NativeAOT_StorageSpaceType
- [ExpectedWarning ("IL2091", ProducedBy = ProducedBy.Trimmer | ProducedBy.Analyzer)] // NativeAOT_StorageSpaceType
- static IWithTwo<TPublicFields, TPublicMethods> MethodWithTwoMismatchesInReturn<
- [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TPublicFields,
- [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods>
- () => null;
-
- public static void Test ()
- {
- MethodWithSpecificType (null, null);
- MethodWithOneMismatch<TestType> (null);
- MethodWithTwoMismatches<TestType, TestType> (null, null);
-
- MethodWithSpecificReturnType ();
- MethodWithMatchingReturn<TestType> ();
- MethodWithOneMismatchReturn<TestType> ();
- MethodWithTwoMismatchesInReturn<TestType, TestType> ();
- }
- }
-
- //.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<TestType> _field;
-
- public static void Test ()
- {
- _field = null;
- }
- }
-
- class OneMatchingAnnotation<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods>
- {
- static TypeWithPublicMethods<TPublicMethods> _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<TUnknown> _field1;
- static TypeWithPublicMethods<TPublicMethods> _field2;
- [ExpectedWarning ("IL2091", ProducedBy = ProducedBy.Trimmer | ProducedBy.Analyzer)] // NativeAOT_StorageSpaceType
- static TypeWithPublicMethods<TUnknown> _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<TPublicFields, TPublicMethods> _field;
-
- public static void Test ()
- {
- _field = null;
- }
- }
-
- public static void Test ()
- {
- SpecificType.Test ();
- OneMatchingAnnotation<TestType>.Test ();
- MultipleReferencesToTheSameType<TestType, TestType>.Test ();
- TwoMismatchesInOne<TestType, TestType>.Test ();
- }
- }
-
- //.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<TestType> Property { get; set; }
-
- public static void Test ()
- {
- Property = null;
- }
- }
-
- class OneMatchingAnnotation<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods>
- {
- static TypeWithPublicMethods<TPublicMethods> 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<TUnknown> Property1 {
- [ExpectedWarning ("IL2091", ProducedBy = ProducedBy.Trimmer | ProducedBy.Analyzer)] // NativeAOT_StorageSpaceType
- get;
-
- [ExpectedWarning ("IL2091", ProducedBy = ProducedBy.Trimmer | ProducedBy.Analyzer)] // NativeAOT_StorageSpaceType
- set;
- }
-
- static TypeWithPublicMethods<TPublicMethods> Property2 {
- get;
- set;
- }
-
- // The warning is generated on the backing field
- [ExpectedWarning ("IL2091", CompilerGeneratedCode = true, ProducedBy = ProducedBy.Trimmer | ProducedBy.Analyzer)] // NativeAOT_StorageSpaceType
- static TypeWithPublicMethods<TUnknown> 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<TPublicFields, TPublicMethods> 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<TestType>.Test ();
- MultipleReferencesToTheSameType<TestType, TestType>.Test ();
- TwoMismatchesInOne<TestType, TestType>.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<T> GetInstanceForTypeWithPublicMethods<T> () => 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<TestType>);
- t = typeof (IWithTwo<TestType, TestType>);
- }
-
- static void OneMatchingAnnotation<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> ()
- {
- Type t = typeof (TypeWithPublicMethods<TPublicMethods>);
- }
-
- [ExpectedWarning ("IL2091")]
- [ExpectedWarning ("IL2091")]
- static void MultipleReferencesToTheSameType<
- [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods,
- TUnknown> ()
- {
- Type t = typeof (TypeWithPublicMethods<TUnknown>); // Warn
- t = typeof (TypeWithPublicMethods<TPublicMethods>); // No warn
- t = typeof (TypeWithPublicMethods<TUnknown>); // Warn
- }
-
- [ExpectedWarning ("IL2091")]
- [ExpectedWarning ("IL2091")]
- static void TwoMismatchesInOneStatement<
- [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TPublicFields,
- [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods>
- ()
- {
- Type t = typeof (IWithTwo<TPublicFields, TPublicMethods>);
- }
-
- public static void Test ()
- {
- AccessOpenTypeDefinition ();
- SpecificType ();
- OneMatchingAnnotation<TestType> ();
- MultipleReferencesToTheSameType<TestType, TestType> ();
- TwoMismatchesInOneStatement<TestType, TestType> ();
- }
- }
-
- class MethodCallOnGenericMethod
- {
- static void SpecificType ()
- {
- MethodWithPublicMethods<TestType> ();
- MethodWithTwo<TestType, TestType> ();
- }
-
- static void OneMatchingAnnotation<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> ()
- {
- MethodWithPublicMethods<TPublicMethods> ();
- }
-
- [ExpectedWarning ("IL2091")]
- [ExpectedWarning ("IL2091")]
- static void MultipleReferencesToTheSameMethod<
- [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods,
- TUnknown> ()
- {
- MethodWithPublicMethods<TUnknown> (); // Warn
- MethodWithPublicMethods<TPublicMethods> (); // No warn
- MethodWithPublicMethods<TUnknown> (); // Warn
- }
-
- [ExpectedWarning ("IL2091")]
- [ExpectedWarning ("IL2091")]
- static void TwoMismatchesInOneStatement<
- [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TPublicFields,
- [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods>
- ()
- {
- MethodWithTwo<TPublicFields, TPublicMethods> ();
- }
-
- [ExpectedWarning ("IL2091")]
- static void InstanceMethodMismatch<TUnknown> ()
- {
- GetInstance ().InstanceMethodWithPublicMethods<TUnknown> ();
- }
-
- public static void Test ()
- {
- SpecificType ();
- OneMatchingAnnotation<TestType> ();
- MultipleReferencesToTheSameMethod<TestType, TestType> ();
- TwoMismatchesInOneStatement<TestType, TestType> ();
- InstanceMethodMismatch<TestType> ();
- }
- }
-
- class MethodCallOnGenericType
- {
- static void SpecificType ()
- {
- TypeWithPublicMethods<TestType>.Method ();
- IWithTwo<TestType, TestType>.Method ();
- }
-
- static void OneMatchingAnnotation<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> ()
- {
- TypeWithPublicMethods<TPublicMethods>.Method ();
- }
-
- [ExpectedWarning ("IL2091")]
- [ExpectedWarning ("IL2091")]
- static void MultipleReferencesToTheSameMethod<
- [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods,
- TUnknown> ()
- {
- TypeWithPublicMethods<TUnknown>.Method (); // Warn
- TypeWithPublicMethods<TPublicMethods>.Method (); // No warn
- TypeWithPublicMethods<TUnknown>.Method (); // Warn
- }
-
- [ExpectedWarning ("IL2091")]
- [ExpectedWarning ("IL2091")]
- static void TwoMismatchesInOneStatement<
- [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TPublicFields,
- [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods>
- ()
- {
- IWithTwo<TPublicFields, TPublicMethods>.Method ();
- }
-
- [ExpectedWarning ("IL2091", ProducedBy = ProducedBy.Trimmer | ProducedBy.Analyzer)] // NativeAOT_StorageSpaceType
- [ExpectedWarning ("IL2091", ProducedBy = ProducedBy.Trimmer | ProducedBy.Analyzer)] // local variable // NativeAOT_StorageSpaceType
- static void InstanceMethodMismatch<TUnknown> ()
- {
- TypeWithPublicMethods<TUnknown> instance = GetInstanceForTypeWithPublicMethods<TUnknown> ();
- instance.InstanceMethod ();
- }
-
- public static void Test ()
- {
- SpecificType ();
- OneMatchingAnnotation<TestType> ();
- MultipleReferencesToTheSameMethod<TestType, TestType> ();
- TwoMismatchesInOneStatement<TestType, TestType> ();
- InstanceMethodMismatch<TestType> ();
- }
- }
-
- class FieldAccessOnGenericType
- {
- static void SpecificType ()
- {
- _ = TypeWithPublicMethods<TestType>.Field;
- IWithTwo<TestType, TestType>.Field = "";
- }
-
- static void OneMatchingAnnotation<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> ()
- {
- _ = TypeWithPublicMethods<TPublicMethods>.Field;
- }
-
- [ExpectedWarning ("IL2091")]
- [ExpectedWarning ("IL2091")]
- static void MultipleReferencesToTheSameField<
- [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods,
- TUnknown> ()
- {
- _ = TypeWithPublicMethods<TUnknown>.Field; // Warn
- TypeWithPublicMethods<TPublicMethods>.Field = ""; // No warn
- TypeWithPublicMethods<TUnknown>.Field = ""; // Warn
- }
-
- [ExpectedWarning ("IL2091")]
- [ExpectedWarning ("IL2091")]
- static void TwoMismatchesInOneStatement<
- [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TPublicFields,
- [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods>
- ()
- {
- _ = IWithTwo<TPublicFields, TPublicMethods>.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<TUnknown> ()
- {
- TypeWithPublicMethods<TUnknown> instance = GetInstanceForTypeWithPublicMethods<TUnknown> ();
- _ = instance.InstanceField;
- }
-
- public static void Test ()
- {
- SpecificType ();
- OneMatchingAnnotation<TestType> ();
- MultipleReferencesToTheSameField<TestType, TestType> ();
- TwoMismatchesInOneStatement<TestType, TestType> ();
- InstanceFieldMismatch<TestType> ();
- }
- }
-
- //.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<TestType> t = null;
- IWithTwo<TestType, TestType> i = null;
- }
-
- static void OneMatchingAnnotation<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> ()
- {
- TypeWithPublicMethods<TPublicMethods> 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<TUnknown> t1 = null; // Warn
- TypeWithPublicMethods<TPublicMethods> t2 = null; // No warn
- TypeWithPublicMethods<TUnknown> 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<TPublicFields, TPublicMethods> i = null;
- }
-
- public static void Test ()
- {
- SpecificType ();
- OneMatchingAnnotation<TestType> ();
- MultipleReferencesToTheSameType<TestType, TestType> ();
- TwoMismatchesInOneStatement<TestType, TestType> ();
- }
- }
-
- class DelegateUsageOnGenericMethod
- {
- static void SpecificType ()
- {
- var a = new Action (MethodWithPublicMethods<TestType>);
- }
-
- static void OneMatchingAnnotation<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> ()
- {
- var a = new Action (MethodWithPublicMethods<TPublicMethods>);
- }
-
- [ExpectedWarning ("IL2091")]
- [ExpectedWarning ("IL2091")]
- static void MultipleReferencesToTheSameMethod<
- [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods,
- TUnknown> ()
- {
- var a1 = new Action (MethodWithPublicMethods<TUnknown>); // Warn
- var a2 = new Action (MethodWithPublicMethods<TPublicMethods>); // No warn
- var a3 = new Action (MethodWithPublicMethods<TUnknown>); // Warn
- }
-
- [ExpectedWarning ("IL2091")]
- [ExpectedWarning ("IL2091")]
- static void TwoMismatchesInOneStatement<
- [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TPublicFields,
- [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods>
- ()
- {
- var a = new Action (MethodWithTwo<TPublicFields, TPublicMethods>);
- }
-
- public static void Test ()
- {
- SpecificType ();
- OneMatchingAnnotation<TestType> ();
- MultipleReferencesToTheSameMethod<TestType, TestType> ();
- TwoMismatchesInOneStatement<TestType, TestType> ();
- }
- }
-
- class DelegateUsageOnGenericType
- {
- static void SpecificType ()
- {
- var a = new Action (TypeWithPublicMethods<TestType>.Method);
- }
-
- static void OneMatchingAnnotation<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> ()
- {
- var a = new Action (TypeWithPublicMethods<TPublicMethods>.Method);
- }
-
- [ExpectedWarning ("IL2091")]
- [ExpectedWarning ("IL2091")]
- static void MultipleReferencesToTheSameMethod<
- [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods,
- TUnknown> ()
- {
- var a1 = new Action (TypeWithPublicMethods<TUnknown>.Method); // Warn
- var a2 = new Action (TypeWithPublicMethods<TPublicMethods>.Method); // No warn
- var a3 = new Action (TypeWithPublicMethods<TUnknown>.Method); // Warn
- }
-
- [ExpectedWarning ("IL2091")]
- [ExpectedWarning ("IL2091")]
- static void TwoMismatchesInOneStatement<
- [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TPublicFields,
- [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods>
- ()
- {
- var a = new Action (IWithTwo<TPublicFields, TPublicMethods>.Method);
- }
-
- public static void Test ()
- {
- SpecificType ();
- OneMatchingAnnotation<TestType> ();
- MultipleReferencesToTheSameMethod<TestType, TestType> ();
- TwoMismatchesInOneStatement<TestType, TestType> ();
- }
- }
-
- class LdTokenOnGenericMethod
- {
- static void SpecificType ()
- {
- Expression<Action> a = () => MethodWithPublicMethods<TestType> ();
- }
-
- static void OneMatchingAnnotation<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> ()
- {
- Expression<Action> a = () => MethodWithPublicMethods<TPublicMethods> ();
- }
-
- [ExpectedWarning ("IL2091")]
- [ExpectedWarning ("IL2091")]
- static void MultipleReferencesToTheSameMethod<
- [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods,
- TUnknown> ()
- {
- Expression<Action> a = () => MethodWithPublicMethods<TUnknown> (); // Warn
- a = () => MethodWithPublicMethods<TPublicMethods> (); // No warn
- a = () => MethodWithPublicMethods<TUnknown> (); // Warn
- }
-
- [ExpectedWarning ("IL2091")]
- [ExpectedWarning ("IL2091")]
- static void TwoMismatchesInOneStatement<
- [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TPublicFields,
- [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods>
- ()
- {
- Expression<Action> a = () => MethodWithTwo<TPublicFields, TPublicMethods> ();
- }
-
- public static void Test ()
- {
- SpecificType ();
- OneMatchingAnnotation<TestType> ();
- MultipleReferencesToTheSameMethod<TestType, TestType> ();
- TwoMismatchesInOneStatement<TestType, TestType> ();
- }
- }
-
- class LdTokenOfMethodOnGenericType
- {
- static void SpecificType ()
- {
- Expression<Action> a = () => TypeWithPublicMethods<TestType>.Method ();
- }
-
- static void OneMatchingAnnotation<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> ()
- {
- Expression<Action> a = () => TypeWithPublicMethods<TPublicMethods>.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<Action> a = () => TypeWithPublicMethods<TUnknown>.Method (); // Warn
- a = () => TypeWithPublicMethods<TPublicMethods>.Method (); // No warn
- a = () => TypeWithPublicMethods<TUnknown>.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<Action> a = () => IWithTwo<TPublicFields, TPublicMethods>.Method ();
- }
-
- public static void Test ()
- {
- SpecificType ();
- OneMatchingAnnotation<TestType> ();
- MultipleReferencesToTheSameMethod<TestType, TestType> ();
- TwoMismatchesInOneStatement<TestType, TestType> ();
- }
- }
-
- class LdTokenOfFieldOnGenericType
- {
- static void SpecificType ()
- {
- Expression<Func<string>> a = () => TypeWithPublicMethods<TestType>.Field;
- }
-
- static void OneMatchingAnnotation<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> ()
- {
- Expression<Func<string>> a = () => TypeWithPublicMethods<TPublicMethods>.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<Func<string>> a = () => TypeWithPublicMethods<TUnknown>.Field; // Warn
- a = () => TypeWithPublicMethods<TPublicMethods>.Field; // No warn
- a = () => TypeWithPublicMethods<TUnknown>.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<Func<string>> a = () => IWithTwo<TPublicFields, TPublicMethods>.Field;
- }
-
- public static void Test ()
- {
- SpecificType ();
- OneMatchingAnnotation<TestType> ();
- MultipleReferencesToTheSameField<TestType, TestType> ();
- TwoMismatchesInOneStatement<TestType, TestType> ();
- }
- }
-
- class LdTokenOfPropertyOnGenericType
- {
- static void SpecificType ()
- {
- Expression<Func<string>> a = () => TypeWithPublicMethods<TestType>.Property;
- }
-
- static void OneMatchingAnnotation<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> ()
- {
- Expression<Func<string>> a = () => TypeWithPublicMethods<TPublicMethods>.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<Func<string>> a = () => TypeWithPublicMethods<TUnknown>.Property; // Warn
- a = () => TypeWithPublicMethods<TPublicMethods>.Property; // No warn
- a = () => TypeWithPublicMethods<TUnknown>.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<Func<string>> a = () => IWithTwo<TPublicFields, TPublicMethods>.Property;
- }
-
- public static void Test ()
- {
- SpecificType ();
- OneMatchingAnnotation<TestType> ();
- MultipleReferencesToTheSameProperty<TestType, TestType> ();
- TwoMismatchesInOneStatement<TestType, TestType> ();
- }
- }
-
- class CreateInstance
- {
- static void SpecificType ()
- {
- object a = new TypeWithPublicMethods<TestType> ();
- }
-
- static void OneMatchingAnnotation<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> ()
- {
- object a = new TypeWithPublicMethods<TPublicMethods> ();
- }
-
- [ExpectedWarning ("IL2091")]
- [ExpectedWarning ("IL2091")]
- static void MultipleReferencesToTheSameMethod<
- [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods,
- TUnknown> ()
- {
- object a1 = new TypeWithPublicMethods<TUnknown> (); // Warn
- object a2 = new TypeWithPublicMethods<TPublicMethods> (); // No warn
- object a3 = new TypeWithPublicMethods<TUnknown> (); // Warn
- }
-
- [ExpectedWarning ("IL2091")]
- [ExpectedWarning ("IL2091")]
- static void TwoMismatchesInOneStatement<
- [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TPublicFields,
- [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods>
- ()
- {
- object a = new TypeWithTwo<TPublicFields, TPublicMethods> ();
- }
-
- public static void Test ()
- {
- SpecificType ();
- OneMatchingAnnotation<TestType> ();
- MultipleReferencesToTheSameMethod<TestType, TestType> ();
- TwoMismatchesInOneStatement<TestType, TestType> ();
- }
- }
-
- //.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<TestType>;
- }
-
- static void OneMatchingAnnotation<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> ()
- {
- bool a = _value is TypeWithPublicMethods<TPublicMethods>;
- }
-
- [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<TUnknown>; // Warn
- bool a2 = _value is TypeWithPublicMethods<TPublicMethods>; // No warn
- bool a3 = _value is TypeWithPublicMethods<TUnknown>; // 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<TPublicFields, TPublicMethods>;
- }
-
- public static void Test ()
- {
- SpecificType ();
- OneMatchingAnnotation<TestType> ();
- MultipleReferencesToTheSameMethod<TestType, TestType> ();
- TwoMismatchesInOneStatement<TestType, TestType> ();
- }
- }
-
- // This is basically the same operation as IsInstance
- class AsType
- {
- static object _value = null;
-
- static void SpecificType ()
- {
- object a = _value as TypeWithPublicMethods<TestType>;
- }
-
- static void OneMatchingAnnotation<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> ()
- {
- object a = _value as TypeWithPublicMethods<TPublicMethods>;
- }
-
- [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<TUnknown>; // Warn
- object a2 = _value as TypeWithPublicMethods<TPublicMethods>; // No warn
- object a3 = _value as TypeWithPublicMethods<TUnknown>; // 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<TPublicFields, TPublicMethods>;
- }
-
- public static void Test ()
- {
- SpecificType ();
- OneMatchingAnnotation<TestType> ();
- MultipleReferencesToTheSameMethod<TestType, TestType> ();
- TwoMismatchesInOneStatement<TestType, TestType> ();
- }
- }
-
- //.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<TestType>) {
- }
- }
-
- static void OneMatchingAnnotation<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> ()
- {
- try {
- DoNothing ();
- } catch (TypeWithPublicMethods<TPublicMethods>) {
- }
- }
-
- [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<TUnknown>) { // Warn
- }
-
- try {
- DoNothing ();
- } catch (TypeWithPublicMethods<TPublicMethods>) { // No warn
- }
-
- try {
- DoNothing ();
- } catch (TypeWithPublicMethods<TUnknown>) { // 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<TPublicFields, TPublicMethods>) { // Warn x2
- }
- }
-
- public static void Test ()
- {
- SpecificType ();
- OneMatchingAnnotation<TestType> ();
- MultipleReferencesToTheSameType<TestType, TestType> ();
- TwoMismatchesInOneStatement<TestType, TestType> ();
- }
- }
-
- // 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<TestType>) {
- }
- }
-
- static void OneMatchingAnnotation<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> ()
- {
- try {
- DoNothing ();
- } catch (Exception ex) when (ex is TypeWithPublicMethods<TPublicMethods>) {
- }
- }
-
- [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<TUnknown>) { // Warn
- }
-
- try {
- DoNothing ();
- } catch (Exception ex) when (ex is TypeWithPublicMethods<TPublicMethods>) { // No warn
- }
-
- try {
- DoNothing ();
- } catch (Exception ex) when (ex is TypeWithPublicMethods<TUnknown>) { // 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<TPublicFields, TPublicMethods>) { // Warn x2
- }
- }
-
- public static void Test ()
- {
- SpecificType ();
- OneMatchingAnnotation<TestType> ();
- MultipleReferencesToTheSameType<TestType, TestType> ();
- TwoMismatchesInOneStatement<TestType, TestType> ();
- }
- }
-
- 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 ();
- }
- }
-
- class TestType { }
-
- static void DoNothing () { }
- }
-}
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;
{
public class AssemblyChecker
{
+ internal readonly struct AssemblyQualifiedToken : IEquatable<AssemblyQualifiedToken>
+ {
+ 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;
+++ /dev/null
-// 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<AssemblyQualifiedToken>
- {
- 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;
- }
-}
{
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 &&