diff options
author | Lakshan Fernando <lakshanf@hotmail.com> | 2022-02-01 03:27:34 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-02-01 03:27:34 +0300 |
commit | 56421a1b1c1713d9d02567f481595d6b7b5ac000 (patch) | |
tree | c308034fe957e46dd37adb60844c25a653d60e36 /test/Mono.Linker.Tests.Cases | |
parent | f6fde401e2841726ac04fcc37a34ce402ac800c6 (diff) |
generic type annotation (#2478)
* generic type annotation - take 1
* fb
* FB2
* Using Syntax API and refactored GenericParameterDataFlow test into 2
* incorprate FB
* fix remaining issues
* CI build break fix
* FB
* FB
* FB
* enhanced comments
Diffstat (limited to 'test/Mono.Linker.Tests.Cases')
-rw-r--r-- | test/Mono.Linker.Tests.Cases/DataFlow/GenericParameterDataFlow.cs | 808 | ||||
-rw-r--r-- | test/Mono.Linker.Tests.Cases/DataFlow/MakeGenericDataFlow.cs | 501 |
2 files changed, 684 insertions, 625 deletions
diff --git a/test/Mono.Linker.Tests.Cases/DataFlow/GenericParameterDataFlow.cs b/test/Mono.Linker.Tests.Cases/DataFlow/GenericParameterDataFlow.cs index f94b62a0c..0c6a77867 100644 --- a/test/Mono.Linker.Tests.Cases/DataFlow/GenericParameterDataFlow.cs +++ b/test/Mono.Linker.Tests.Cases/DataFlow/GenericParameterDataFlow.cs @@ -25,9 +25,6 @@ namespace Mono.Linker.Tests.Cases.DataFlow TestMultipleGenericParametersOnMethod (); TestMethodGenericParametersViaInheritance (); - MakeGenericType.Test (); - MakeGenericMethod.Test (); - TestNewConstraintSatisfiesParameterlessConstructor<object> (); TestStructConstraintSatisfiesParameterlessConstructor<TestStruct> (); TestUnmanagedConstraintSatisfiesParameterlessConstructor<byte> (); @@ -45,11 +42,6 @@ namespace Mono.Linker.Tests.Cases.DataFlow TypeRequiresNothingPassThrough<TestType>.Test (); } - static void TestGenericParameterFlowsToField () - { - TypeRequiresPublicFields<TestType>.TestFields (); - } - static void TestGenericParameterFlowsToReturnValue () { _ = TypeRequiresPublicFields<TestType>.ReturnRequiresPublicFields (); @@ -65,6 +57,7 @@ namespace Mono.Linker.Tests.Cases.DataFlow static Type FieldRequiresNothing; + class TypeRequiresPublicFields< [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] T> { @@ -84,21 +77,18 @@ namespace Mono.Linker.Tests.Cases.DataFlow 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); @@ -156,6 +146,77 @@ namespace Mono.Linker.Tests.Cases.DataFlow } } + static void TestBaseTypeGenericRequirements () + { + new DerivedTypeWithInstantiatedGenericOnBase (); + new DerivedTypeWithInstantiationOverSelfOnBase (); + new DerivedTypeWithOpenGenericOnBase<TestType> (); + TestDerivedTypeWithOpenGenericOnBaseWithRUCOnBase (); + TestDerivedTypeWithOpenGenericOnBaseWithRUCOnDerived (); + new DerivedTypeWithOpenGenericOnBaseWithRequirements<TestType> (); + } + + 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)] + public DerivedTypeWithOpenGenericOnBase () { } + } + + static void TestDerivedTypeWithOpenGenericOnBaseWithRUCOnBase () + { + new DerivedTypeWithOpenGenericOnBaseWithRUCOnBase<TestType> (); + } + + [ExpectedWarning ("IL2109", nameof (BaseTypeWithOpenGenericDAMTAndRUC<T>))] + [ExpectedWarning ("IL2091", nameof (BaseTypeWithOpenGenericDAMTAndRUC<T>))] + class DerivedTypeWithOpenGenericOnBaseWithRUCOnBase<T> : BaseTypeWithOpenGenericDAMTAndRUC<T> + { + [ExpectedWarning ("IL2091", nameof (DerivedTypeWithOpenGenericOnBaseWithRUCOnBase<T>), ProducedBy = ProducedBy.Trimmer)] + [ExpectedWarning ("IL2026", nameof (BaseTypeWithOpenGenericDAMTAndRUC<T>), ProducedBy = ProducedBy.Trimmer)] + 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 (); @@ -216,46 +277,27 @@ namespace Mono.Linker.Tests.Cases.DataFlow } } - static void TestBaseTypeGenericRequirements () + static void TestDeepNestedTypesWithGenerics () { - new DerivedTypeWithInstantiatedGenericOnBase (); - new DerivedTypeWithInstantiationOverSelfOnBase (); - new DerivedTypeWithOpenGenericOnBase<TestType> (); - new DerivedTypeWithOpenGenericOnBaseWithRequirements<TestType> (); + RootTypeWithRequirements<TestType>.InnerTypeWithNoAddedGenerics.TestAccess (); } - class GenericBaseTypeWithRequirements<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] T> + class RootTypeWithRequirements<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TRoot> { - public GenericBaseTypeWithRequirements () + public class InnerTypeWithNoAddedGenerics { - typeof (T).RequiresPublicFields (); + [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 (); + } } } - class DerivedTypeWithInstantiatedGenericOnBase : GenericBaseTypeWithRequirements<TestType> - { - } - - class GenericBaseTypeWithRequiresAll<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)] T> - { - } - - class DerivedTypeWithInstantiationOverSelfOnBase : GenericBaseTypeWithRequirements<DerivedTypeWithInstantiationOverSelfOnBase> - { - } - - [ExpectedWarning ("IL2091", nameof (GenericBaseTypeWithRequirements<T>))] - class DerivedTypeWithOpenGenericOnBase<T> : GenericBaseTypeWithRequirements<T> - { - [ExpectedWarning ("IL2091", nameof (GenericBaseTypeWithRequirements<T>))] - public DerivedTypeWithOpenGenericOnBase () { } - } - - class DerivedTypeWithOpenGenericOnBaseWithRequirements<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] T> - : GenericBaseTypeWithRequirements<T> - { - } - static void TestInterfaceTypeGenericRequirements () { IGenericInterfaceTypeWithRequirements<TestType> instance = new InterfaceImplementationTypeWithInstantiatedGenericOnBase (); @@ -284,35 +326,11 @@ namespace Mono.Linker.Tests.Cases.DataFlow class InterfaceImplementationTypeWithOpenGenericOnBase<T> : IGenericInterfaceTypeWithRequirements<T> { } - class InterfaceImplementationTypeWithOpenGenericOnBaseWithRequirements<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] T> : IGenericInterfaceTypeWithRequirements<T> { } - static void TestDeepNestedTypesWithGenerics () - { - RootTypeWithRequirements<TestType>.InnerTypeWithNoAddedGenerics.TestAccess (); - } - - class RootTypeWithRequirements<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TRoot> - { - public class InnerTypeWithNoAddedGenerics - { - // The message is not ideal since we report the TRoot to come from RootTypeWithRequirements/InnerTypeWIthNoAddedGenerics - // while it originates on RootTypeWithRequirements, but it's correct from IL's point of view. - [ExpectedWarning ("IL2087", nameof (TRoot), - "Mono.Linker.Tests.Cases.DataFlow.GenericParameterDataFlow.RootTypeWithRequirements<TRoot>.InnerTypeWithNoAddedGenerics", - "type", - "DataFlowTypeExtensions.RequiresPublicMethods(Type)")] - public static void TestAccess () - { - typeof (TRoot).RequiresPublicFields (); - typeof (TRoot).RequiresPublicMethods (); - } - } - } - static void TestTypeGenericRequirementsOnMembers () { // Basically just root everything we need to test @@ -348,10 +366,11 @@ namespace Mono.Linker.Tests.Cases.DataFlow set; } + [ExpectedWarning ("IL2091", nameof (TypeGenericRequirementsOnMembers<TOuter>), ProducedBy = ProducedBy.Analyzer)] public TypeRequiresPublicMethods<TOuter> PublicMethodsProperty { - [ExpectedWarning ("IL2091", nameof (TypeRequiresPublicMethods<TOuter>))] + [ExpectedWarning ("IL2091", nameof (TypeRequiresPublicMethods<TOuter>), ProducedBy = ProducedBy.Trimmer)] get => null; - [ExpectedWarning ("IL2091", nameof (TypeRequiresPublicMethods<TOuter>))] + [ExpectedWarning ("IL2091", nameof (TypeRequiresPublicMethods<TOuter>), ProducedBy = ProducedBy.Trimmer)] set { } } @@ -360,8 +379,9 @@ namespace Mono.Linker.Tests.Cases.DataFlow public void PublicMethodsMethodParameter (TypeRequiresPublicMethods<TOuter> param) { } public TypeRequiresPublicFields<TOuter> PublicFieldsMethodReturnValue () { return null; } - [ExpectedWarning ("IL2091", nameof (TypeRequiresPublicMethods<TOuter>))] // Return value - [ExpectedWarning ("IL2091", nameof (TypeRequiresPublicMethods<TOuter>))] // Compiler generated local variable + + [ExpectedWarning ("IL2091", nameof (TypeRequiresPublicMethods<TOuter>), ProducedBy = ProducedBy.Trimmer)] + [ExpectedWarning ("IL2091", nameof (TypeRequiresPublicMethods<TOuter>))] public TypeRequiresPublicMethods<TOuter> PublicMethodsMethodReturnValue () { return null; } public void PublicFieldsMethodLocalVariable () @@ -404,7 +424,8 @@ namespace Mono.Linker.Tests.Cases.DataFlow class PartialyInstantiatedMethods<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TOuter> : BaseForPartialInstantiation<TestType, TOuter> { - [ExpectedWarning ("IL2091", nameof (BaseForPartialInstantiation<TestType, TOuter>), "'TMethods'")] + // Analyzer does not see the base class constructor + [ExpectedWarning ("IL2091", nameof (BaseForPartialInstantiation<TestType, TOuter>), "'TMethods'", ProducedBy = ProducedBy.Trimmer)] public PartialyInstantiatedMethods () { } } @@ -467,6 +488,79 @@ namespace Mono.Linker.Tests.Cases.DataFlow 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> (); @@ -501,9 +595,9 @@ namespace Mono.Linker.Tests.Cases.DataFlow public static void StaticRequiresPublicMethods<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] T> () => typeof (T).RequiresPublicMethods (); - public void InstanceRequiresPublicMethods<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)]T> () + public void InstanceRequiresPublicMethods<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] T> () => typeof (T).RequiresPublicMethods (); - public virtual void VirtualRequiresPublicMethods<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)]T> () + public virtual void VirtualRequiresPublicMethods<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] T> () => typeof (T).RequiresPublicMethods (); public static void StaticRequiresMultipleGenericParams< @@ -521,6 +615,7 @@ namespace Mono.Linker.Tests.Cases.DataFlow void InterfaceRequiresPublicMethods<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] T> (); } + class TypeWithInstantiatedGenericMethodViaGenericParameter<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TOuter> : BaseTypeWithGenericMethod, IInterfaceWithGenericMethod { @@ -552,10 +647,17 @@ namespace Mono.Linker.Tests.Cases.DataFlow } [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<TOuter>", "'TMethods'", - "Mono.Linker.Tests.Cases.DataFlow.GenericParameterDataFlow.BaseTypeWithGenericMethod.StaticRequiresMultipleGenericParams<TFields,TMethods>()")] + "Mono.Linker.Tests.Cases.DataFlow.GenericParameterDataFlow.BaseTypeWithGenericMethod.StaticRequiresMultipleGenericParams<TFields,TMethods>()", + ProducedBy = ProducedBy.Trimmer)] public static void StaticPartialInstantiationUnrecognized () { StaticRequiresMultipleGenericParams<TestType, TOuter> (); @@ -616,554 +718,6 @@ namespace Mono.Linker.Tests.Cases.DataFlow } } - - 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 (); - } - - - class MakeGenericType - { - public static void Test () - { - TestNullType (); - TestUnknownInput (null); - TestWithUnknownTypeArray (null); - TestWithArrayUnknownIndexSet (0); - TestWithArrayUnknownLengthSet (1); - TestNoArguments (); - - TestWithRequirements (); - TestWithRequirementsFromParam (null); - TestWithRequirementsFromParamWithMismatch (null); - TestWithRequirementsFromGenericParam<TestType> (); - TestWithRequirementsFromGenericParamWithMismatch<TestType> (); - - TestWithNoRequirements (); - TestWithNoRequirementsFromParam (null); - - TestWithMultipleArgumentsWithRequirements (); - - TestWithNewConstraint (); - TestWithStructConstraint (); - TestWithUnmanagedConstraint (); - TestWithNullable (); - } - - // This is OK since we know it's null, so MakeGenericType is effectively a no-op (will throw) - // so no validation necessary. - static void TestNullType () - { - Type nullType = null; - nullType.MakeGenericType (typeof (TestType)); - } - - [ExpectedWarning ("IL2055", nameof (Type.MakeGenericType))] - static void TestUnknownInput (Type inputType) - { - inputType.MakeGenericType (typeof (TestType)); - } - - [ExpectedWarning ("IL2055", nameof (Type.MakeGenericType))] - static void TestWithUnknownTypeArray (Type[] types) - { - typeof (GenericWithPublicFieldsArgument<>).MakeGenericType (types); - } - - [ExpectedWarning ("IL2055", nameof (Type.MakeGenericType))] - static void TestWithArrayUnknownIndexSet (int indexToSet) - { - Type[] types = new Type[1]; - types[indexToSet] = typeof (TestType); - typeof (GenericWithPublicFieldsArgument<>).MakeGenericType (types); - } - - [ExpectedWarning ("IL2055", nameof (Type.MakeGenericType))] - static void TestWithArrayUnknownLengthSet (int arrayLen) - { - Type[] types = new Type[arrayLen]; - types[0] = typeof (TestType); - typeof (GenericWithPublicFieldsArgument<>).MakeGenericType (types); - } - - static void TestNoArguments () - { - typeof (TypeMakeGenericNoArguments).MakeGenericType (); - } - - class TypeMakeGenericNoArguments - { - } - - static void TestWithRequirements () - { - // Currently this is not analyzable since we don't track array elements. - // Would be really nice to support this kind of code in the future though. - typeof (GenericWithPublicFieldsArgument<>).MakeGenericType (typeof (TestType)); - } - - static void TestWithRequirementsFromParam ( - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] Type type) - { - typeof (GenericWithPublicFieldsArgument<>).MakeGenericType (type); - } - - // https://github.com/dotnet/linker/issues/2428 - // [ExpectedWarning ("IL2071", "'T'")] - [ExpectedWarning ("IL2070", "'this'")] - static void TestWithRequirementsFromParamWithMismatch ( - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] Type type) - { - typeof (GenericWithPublicFieldsArgument<>).MakeGenericType (type); - } - - static void TestWithRequirementsFromGenericParam< - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] T> () - { - typeof (GenericWithPublicFieldsArgument<>).MakeGenericType (typeof (T)); - } - - // https://github.com/dotnet/linker/issues/2428 - // [ExpectedWarning ("IL2091", "'T'")] - [ExpectedWarning ("IL2090", "'this'")] // Note that this actually produces a warning which should not be possible to produce right now - static void TestWithRequirementsFromGenericParamWithMismatch< - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TInput> () - { - typeof (GenericWithPublicFieldsArgument<>).MakeGenericType (typeof (TInput)); - } - - class GenericWithPublicFieldsArgument<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] T> - { - } - - static void TestWithNoRequirements () - { - typeof (GenericWithNoRequirements<>).MakeGenericType (typeof (TestType)); - } - - static void TestWithNoRequirementsFromParam (Type type) - { - typeof (GenericWithNoRequirements<>).MakeGenericType (type); - } - - class GenericWithNoRequirements<T> - { - } - - static void TestWithMultipleArgumentsWithRequirements () - { - typeof (GenericWithMultipleArgumentsWithRequirements<,>).MakeGenericType (typeof (TestType), typeof (TestType)); - } - - class GenericWithMultipleArgumentsWithRequirements< - TOne, - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TTwo> - { - } - - static void TestWithNewConstraint () - { - typeof (GenericWithNewConstraint<>).MakeGenericType (typeof (TestType)); - } - - class GenericWithNewConstraint<T> where T : new() - { - } - - static void TestWithStructConstraint () - { - typeof (GenericWithStructConstraint<>).MakeGenericType (typeof (TestType)); - } - - class GenericWithStructConstraint<T> where T : struct - { - } - - static void TestWithUnmanagedConstraint () - { - typeof (GenericWithUnmanagedConstraint<>).MakeGenericType (typeof (TestType)); - } - - class GenericWithUnmanagedConstraint<T> where T : unmanaged - { - } - - static void TestWithNullable () - { - typeof (Nullable<>).MakeGenericType (typeof (TestType)); - } - } - - class MakeGenericMethod - { - public static void Test () - { - TestNullMethod (); - TestUnknownMethod (null); - TestUnknownMethodButNoTypeArguments (null); - TestWithUnknownTypeArray (null); - TestWithArrayUnknownIndexSet (0); - TestWithArrayUnknownIndexSetByRef (0); - TestWithArrayUnknownLengthSet (1); - TestWithArrayPassedToAnotherMethod (); - TestWithNoArguments (); - TestWithArgumentsButNonGenericMethod (); - - TestWithRequirements (); - TestWithRequirementsFromParam (null); - TestWithRequirementsFromGenericParam<TestType> (); - TestWithRequirementsViaRuntimeMethod (); - TestWithRequirementsButNoTypeArguments (); - - TestWithMultipleKnownGenericParameters (); - TestWithOneUnknownGenericParameter (null); - TestWithPartiallyInitializedGenericTypeArray (); - TestWithConditionalGenericTypeSet (true); - - TestWithNoRequirements (); - TestWithNoRequirementsFromParam (null); - TestWithNoRequirementsViaRuntimeMethod (); - TestWithNoRequirementsUnknownType (null); - TestWithNoRequirementsWrongNumberOfTypeParameters (); - TestWithNoRequirementsUnknownArrayElement (); - - TestWithMultipleArgumentsWithRequirements (); - - TestWithNewConstraint (); - TestWithStructConstraint (); - TestWithUnmanagedConstraint (); - } - - static void TestNullMethod () - { - MethodInfo mi = null; - mi.MakeGenericMethod (typeof (TestType)); - } - - [ExpectedWarning ("IL2060", nameof (MethodInfo.MakeGenericMethod))] - static void TestUnknownMethod (MethodInfo mi) - { - mi.MakeGenericMethod (typeof (TestType)); - } - - [ExpectedWarning ("IL2060", nameof (MethodInfo.MakeGenericMethod))] - static void TestUnknownMethodButNoTypeArguments (MethodInfo mi) - { - // Thechnically linker could figure this out, but it's not worth the complexity - such call will always fail at runtime. - mi.MakeGenericMethod (Type.EmptyTypes); - } - - [ExpectedWarning ("IL2060", nameof (MethodInfo.MakeGenericMethod))] - static void TestWithUnknownTypeArray (Type[] types) - { - typeof (MakeGenericMethod).GetMethod (nameof (GenericWithRequirements), BindingFlags.Static) - .MakeGenericMethod (types); - } - - [ExpectedWarning ("IL2060", nameof (MethodInfo.MakeGenericMethod))] - static void TestWithArrayUnknownIndexSet (int indexToSet) - { - Type[] types = new Type[1]; - types[indexToSet] = typeof (TestType); - typeof (MakeGenericMethod).GetMethod (nameof (GenericWithRequirements), BindingFlags.Static) - .MakeGenericMethod (types); - } - - [ExpectedWarning ("IL2060", nameof (MethodInfo.MakeGenericMethod))] - static void TestWithArrayUnknownIndexSetByRef (int indexToSet) - { - Type[] types = new Type[1]; - types[0] = typeof (TestType); - ref Type t = ref types[indexToSet]; - t = typeof (TestType); - typeof (MakeGenericMethod).GetMethod (nameof (GenericWithRequirements), BindingFlags.Static) - .MakeGenericMethod (types); - } - - [ExpectedWarning ("IL2060", nameof (MethodInfo.MakeGenericMethod))] - static void TestWithArrayUnknownLengthSet (int arrayLen) - { - Type[] types = new Type[arrayLen]; - types[0] = typeof (TestType); - typeof (MakeGenericMethod).GetMethod (nameof (GenericWithRequirements), BindingFlags.Static) - .MakeGenericMethod (types); - } - - static void MethodThatTakesArrayParameter (Type[] types) - { - } - - [ExpectedWarning ("IL2060", nameof (MethodInfo.MakeGenericMethod))] - static void TestWithArrayPassedToAnotherMethod () - { - Type[] types = new Type[1]; - types[0] = typeof (TestType); - MethodThatTakesArrayParameter (types); - typeof (MakeGenericMethod).GetMethod (nameof (GenericWithRequirements), BindingFlags.Static) - .MakeGenericMethod (types); - } - - static void TestWithNoArguments () - { - typeof (MakeGenericMethod).GetMethod (nameof (NonGenericMethod), BindingFlags.Static | BindingFlags.NonPublic) - .MakeGenericMethod (); - } - - // This should not warn since we can't be always sure about the exact overload as we don't support - // method parameter signature matching, and thus the GetMethod may return multiple potential methods. - // It can happen that some are generic and some are not. The analysis should not fail on this. - static void TestWithArgumentsButNonGenericMethod () - { - typeof (MakeGenericMethod).GetMethod (nameof (NonGenericMethod), BindingFlags.Static | BindingFlags.NonPublic) - .MakeGenericMethod (typeof (TestType)); - } - - static void NonGenericMethod () - { - } - - static void TestWithRequirements () - { - typeof (MakeGenericMethod).GetMethod (nameof (GenericWithRequirements), BindingFlags.Static) - .MakeGenericMethod (typeof (TestType)); - } - - static void TestWithRequirementsFromParam ( - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] Type type) - { - typeof (MakeGenericMethod).GetMethod (nameof (GenericWithRequirements), BindingFlags.Static) - .MakeGenericMethod (type); - } - - static void TestWithRequirementsFromGenericParam< - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] T> () - { - typeof (MakeGenericMethod).GetMethod (nameof (GenericWithRequirements), BindingFlags.Static) - .MakeGenericMethod (typeof (T)); - } - - - static void TestWithRequirementsViaRuntimeMethod () - { - typeof (MakeGenericMethod).GetRuntimeMethod (nameof (GenericWithRequirements), Type.EmptyTypes) - .MakeGenericMethod (typeof (TestType)); - } - - [ExpectedWarning ("IL2060", nameof (MethodInfo.MakeGenericMethod))] - static void TestWithRequirementsButNoTypeArguments () - { - typeof (MakeGenericMethod).GetMethod (nameof (GenericWithRequirements), BindingFlags.Static) - .MakeGenericMethod (Type.EmptyTypes); - } - - public static void GenericWithRequirements<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] T> () - { - } - - static void TestWithMultipleKnownGenericParameters () - { - typeof (MakeGenericMethod).GetMethod (nameof (GenericMultipleParameters), BindingFlags.Static) - .MakeGenericMethod (typeof (TestType), typeof (TestType), typeof (TestType)); - } - - [ExpectedWarning ("IL2060", nameof (MethodInfo.MakeGenericMethod))] - static void TestWithOneUnknownGenericParameter (Type[] types) - { - typeof (MakeGenericMethod).GetMethod (nameof (GenericMultipleParameters), BindingFlags.Static) - .MakeGenericMethod (typeof (TestType), typeof (TestStruct), types[0]); - } - - [ExpectedWarning ("IL2060", nameof (MethodInfo.MakeGenericMethod))] - static void TestWithPartiallyInitializedGenericTypeArray () - { - Type[] types = new Type[3]; - types[0] = typeof (TestType); - types[1] = typeof (TestStruct); - typeof (MakeGenericMethod).GetMethod (nameof (GenericMultipleParameters), BindingFlags.Static) - .MakeGenericMethod (types); - } - - static void TestWithConditionalGenericTypeSet (bool thirdParameterIsStruct) - { - Type[] types = new Type[3]; - types[0] = typeof (TestType); - types[1] = typeof (TestStruct); - if (thirdParameterIsStruct) { - types[2] = typeof (TestStruct); - } else { - types[2] = typeof (TestType); - } - typeof (MakeGenericMethod).GetMethod (nameof (GenericMultipleParameters), BindingFlags.Static) - .MakeGenericMethod (types); - } - - public static void GenericMultipleParameters< - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] T, - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] U, - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] V> () - { - } - - static void TestWithNoRequirements () - { - typeof (MakeGenericMethod).GetMethod (nameof (GenericWithNoRequirements), BindingFlags.Static) - .MakeGenericMethod (typeof (TestType)); - } - - static void TestWithNoRequirementsFromParam (Type type) - { - typeof (MakeGenericMethod).GetMethod (nameof (GenericWithNoRequirements), BindingFlags.Static) - .MakeGenericMethod (type); - } - - static void TestWithNoRequirementsViaRuntimeMethod () - { - typeof (MakeGenericMethod).GetRuntimeMethod (nameof (GenericWithNoRequirements), Type.EmptyTypes) - .MakeGenericMethod (typeof (TestType)); - } - - // There are no requirements, so no warnings - static void TestWithNoRequirementsUnknownType (Type type) - { - typeof (MakeGenericMethod).GetMethod (nameof (GenericWithNoRequirements)) - .MakeGenericMethod (type); - } - - // There are no requirements, so no warnings - static void TestWithNoRequirementsWrongNumberOfTypeParameters () - { - typeof (MakeGenericMethod).GetMethod (nameof (GenericWithNoRequirements)) - .MakeGenericMethod (typeof (TestType), typeof (TestType)); - } - - // There are no requirements, so no warnings - static void TestWithNoRequirementsUnknownArrayElement () - { - Type[] types = new Type[1]; - typeof (MakeGenericMethod).GetMethod (nameof (GenericWithNoRequirements)) - .MakeGenericMethod (types); - } - - public static void GenericWithNoRequirements<T> () - { - } - - - static void TestWithMultipleArgumentsWithRequirements () - { - typeof (MakeGenericMethod).GetMethod (nameof (GenericWithMultipleArgumentsWithRequirements), BindingFlags.Static | BindingFlags.NonPublic) - .MakeGenericMethod (typeof (TestType), typeof (TestType)); - } - - static void GenericWithMultipleArgumentsWithRequirements< - TOne, - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TTwo> () - { - } - - static void TestWithNewConstraint () - { - typeof (MakeGenericMethod).GetMethod (nameof (GenericWithNewConstraint), BindingFlags.Static | BindingFlags.NonPublic) - .MakeGenericMethod (typeof (TestType)); - } - - static void GenericWithNewConstraint<T> () where T : new() - { - var t = new T (); - } - - static void TestWithStructConstraint () - { - typeof (MakeGenericMethod).GetMethod (nameof (GenericWithStructConstraint), BindingFlags.Static | BindingFlags.NonPublic) - .MakeGenericMethod (typeof (TestType)); - } - - static void GenericWithStructConstraint<T> () where T : struct - { - var t = new T (); - } - - static void TestWithUnmanagedConstraint () - { - typeof (MakeGenericMethod).GetMethod (nameof (GenericWithUnmanagedConstraint), BindingFlags.Static | BindingFlags.NonPublic) - .MakeGenericMethod (typeof (TestType)); - } - - static void GenericWithUnmanagedConstraint<T> () where T : unmanaged - { - var t = new T (); - } - } - static void TestNewConstraintSatisfiesParameterlessConstructor<T> () where T : new() { RequiresParameterlessConstructor<T> (); @@ -1173,7 +727,6 @@ namespace Mono.Linker.Tests.Cases.DataFlow { RequiresParameterlessConstructor<T> (); } - static void TestUnmanagedConstraintSatisfiesParameterlessConstructor<T> () where T : unmanaged { RequiresParameterlessConstructor<T> (); @@ -1183,12 +736,17 @@ namespace Mono.Linker.Tests.Cases.DataFlow { } - public class TestType + static void TestGenericParameterFlowsToField () { + TypeRequiresPublicFields<TestType>.TestFields (); } + public class TestType + { + } public struct TestStruct { } + } } diff --git a/test/Mono.Linker.Tests.Cases/DataFlow/MakeGenericDataFlow.cs b/test/Mono.Linker.Tests.Cases/DataFlow/MakeGenericDataFlow.cs new file mode 100644 index 000000000..3d3f2551b --- /dev/null +++ b/test/Mono.Linker.Tests.Cases/DataFlow/MakeGenericDataFlow.cs @@ -0,0 +1,501 @@ +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 +{ + [SkipKeptItemsValidation] + [ExpectedNoWarnings] + public class MakeGenericDataFlow + { + public static void Main () + { + MakeGenericType.Test (); + MakeGenericMethod.Test (); + } + + class MakeGenericType + { + public static void Test () + { + TestNullType (); + TestUnknownInput (null); + TestWithUnknownTypeArray (null); + TestWithArrayUnknownIndexSet (0); + TestWithArrayUnknownLengthSet (1); + TestNoArguments (); + + TestWithRequirements (); + TestWithRequirementsFromParam (null); + TestWithRequirementsFromParamWithMismatch (null); + TestWithRequirementsFromGenericParam<TestType> (); + TestWithRequirementsFromGenericParamWithMismatch<TestType> (); + + TestWithNoRequirements (); + TestWithNoRequirementsFromParam (null); + + TestWithMultipleArgumentsWithRequirements (); + + TestWithNewConstraint (); + TestWithStructConstraint (); + TestWithUnmanagedConstraint (); + TestWithNullable (); + } + + // This is OK since we know it's null, so MakeGenericType is effectively a no-op (will throw) + // so no validation necessary. + static void TestNullType () + { + Type nullType = null; + nullType.MakeGenericType (typeof (TestType)); + } + + [ExpectedWarning ("IL2055", nameof (Type.MakeGenericType))] + static void TestUnknownInput (Type inputType) + { + inputType.MakeGenericType (typeof (TestType)); + } + + [ExpectedWarning ("IL2055", nameof (Type.MakeGenericType))] + static void TestWithUnknownTypeArray (Type[] types) + { + typeof (GenericWithPublicFieldsArgument<>).MakeGenericType (types); + } + + [ExpectedWarning ("IL2055", nameof (Type.MakeGenericType))] + static void TestWithArrayUnknownIndexSet (int indexToSet) + { + Type[] types = new Type[1]; + types[indexToSet] = typeof (TestType); + typeof (GenericWithPublicFieldsArgument<>).MakeGenericType (types); + } + + [ExpectedWarning ("IL2055", nameof (Type.MakeGenericType))] + static void TestWithArrayUnknownLengthSet (int arrayLen) + { + Type[] types = new Type[arrayLen]; + types[0] = typeof (TestType); + typeof (GenericWithPublicFieldsArgument<>).MakeGenericType (types); + } + + static void TestNoArguments () + { + typeof (TypeMakeGenericNoArguments).MakeGenericType (); + } + + class TypeMakeGenericNoArguments + { + } + + static void TestWithRequirements () + { + // Currently this is not analyzable since we don't track array elements. + // Would be really nice to support this kind of code in the future though. + typeof (GenericWithPublicFieldsArgument<>).MakeGenericType (typeof (TestType)); + } + + static void TestWithRequirementsFromParam ( + [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] Type type) + { + typeof (GenericWithPublicFieldsArgument<>).MakeGenericType (type); + } + + // https://github.com/dotnet/linker/issues/2428 + // [ExpectedWarning ("IL2071", "'T'")] + [ExpectedWarning ("IL2070", "'this'")] + static void TestWithRequirementsFromParamWithMismatch ( + [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] Type type) + { + typeof (GenericWithPublicFieldsArgument<>).MakeGenericType (type); + } + + static void TestWithRequirementsFromGenericParam< + [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] T> () + { + typeof (GenericWithPublicFieldsArgument<>).MakeGenericType (typeof (T)); + } + + // https://github.com/dotnet/linker/issues/2428 + // [ExpectedWarning ("IL2091", "'T'")] + [ExpectedWarning ("IL2090", "'this'")] // Note that this actually produces a warning which should not be possible to produce right now + static void TestWithRequirementsFromGenericParamWithMismatch< + [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TInput> () + { + typeof (GenericWithPublicFieldsArgument<>).MakeGenericType (typeof (TInput)); + } + + class GenericWithPublicFieldsArgument<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] T> + { + } + + static void TestWithNoRequirements () + { + typeof (GenericWithNoRequirements<>).MakeGenericType (typeof (TestType)); + } + + static void TestWithNoRequirementsFromParam (Type type) + { + typeof (GenericWithNoRequirements<>).MakeGenericType (type); + } + + class GenericWithNoRequirements<T> + { + } + + static void TestWithMultipleArgumentsWithRequirements () + { + typeof (GenericWithMultipleArgumentsWithRequirements<,>).MakeGenericType (typeof (TestType), typeof (TestType)); + } + + class GenericWithMultipleArgumentsWithRequirements< + TOne, + [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TTwo> + { + } + + static void TestWithNewConstraint () + { + typeof (GenericWithNewConstraint<>).MakeGenericType (typeof (TestType)); + } + + class GenericWithNewConstraint<T> where T : new() + { + } + + static void TestWithStructConstraint () + { + typeof (GenericWithStructConstraint<>).MakeGenericType (typeof (TestType)); + } + + class GenericWithStructConstraint<T> where T : struct + { + } + + static void TestWithUnmanagedConstraint () + { + typeof (GenericWithUnmanagedConstraint<>).MakeGenericType (typeof (TestType)); + } + + class GenericWithUnmanagedConstraint<T> where T : unmanaged + { + } + + static void TestWithNullable () + { + typeof (Nullable<>).MakeGenericType (typeof (TestType)); + } + } + + class MakeGenericMethod + { + public static void Test () + { + TestNullMethod (); + TestUnknownMethod (null); + TestUnknownMethodButNoTypeArguments (null); + TestWithUnknownTypeArray (null); + TestWithArrayUnknownIndexSet (0); + TestWithArrayUnknownIndexSetByRef (0); + TestWithArrayUnknownLengthSet (1); + TestWithArrayPassedToAnotherMethod (); + TestWithNoArguments (); + TestWithArgumentsButNonGenericMethod (); + + TestWithRequirements (); + TestWithRequirementsFromParam (null); + TestWithRequirementsFromGenericParam<TestType> (); + TestWithRequirementsViaRuntimeMethod (); + TestWithRequirementsButNoTypeArguments (); + + TestWithMultipleKnownGenericParameters (); + TestWithOneUnknownGenericParameter (null); + TestWithPartiallyInitializedGenericTypeArray (); + TestWithConditionalGenericTypeSet (true); + + TestWithNoRequirements (); + TestWithNoRequirementsFromParam (null); + TestWithNoRequirementsViaRuntimeMethod (); + TestWithNoRequirementsUnknownType (null); + TestWithNoRequirementsWrongNumberOfTypeParameters (); + TestWithNoRequirementsUnknownArrayElement (); + + TestWithMultipleArgumentsWithRequirements (); + + TestWithNewConstraint (); + TestWithStructConstraint (); + TestWithUnmanagedConstraint (); + } + + static void TestNullMethod () + { + MethodInfo mi = null; + mi.MakeGenericMethod (typeof (TestType)); + } + + [ExpectedWarning ("IL2060", nameof (MethodInfo.MakeGenericMethod))] + static void TestUnknownMethod (MethodInfo mi) + { + mi.MakeGenericMethod (typeof (TestType)); + } + + [ExpectedWarning ("IL2060", nameof (MethodInfo.MakeGenericMethod))] + static void TestUnknownMethodButNoTypeArguments (MethodInfo mi) + { + // Thechnically linker could figure this out, but it's not worth the complexity - such call will always fail at runtime. + mi.MakeGenericMethod (Type.EmptyTypes); + } + + [ExpectedWarning ("IL2060", nameof (MethodInfo.MakeGenericMethod))] + static void TestWithUnknownTypeArray (Type[] types) + { + typeof (MakeGenericMethod).GetMethod (nameof (GenericWithRequirements), BindingFlags.Static) + .MakeGenericMethod (types); + } + + [ExpectedWarning ("IL2060", nameof (MethodInfo.MakeGenericMethod))] + static void TestWithArrayUnknownIndexSet (int indexToSet) + { + Type[] types = new Type[1]; + types[indexToSet] = typeof (TestType); + typeof (MakeGenericMethod).GetMethod (nameof (GenericWithRequirements), BindingFlags.Static) + .MakeGenericMethod (types); + } + + [ExpectedWarning ("IL2060", nameof (MethodInfo.MakeGenericMethod))] + static void TestWithArrayUnknownIndexSetByRef (int indexToSet) + { + Type[] types = new Type[1]; + types[0] = typeof (TestType); + ref Type t = ref types[indexToSet]; + t = typeof (TestType); + typeof (MakeGenericMethod).GetMethod (nameof (GenericWithRequirements), BindingFlags.Static) + .MakeGenericMethod (types); + } + + [ExpectedWarning ("IL2060", nameof (MethodInfo.MakeGenericMethod))] + static void TestWithArrayUnknownLengthSet (int arrayLen) + { + Type[] types = new Type[arrayLen]; + types[0] = typeof (TestType); + typeof (MakeGenericMethod).GetMethod (nameof (GenericWithRequirements), BindingFlags.Static) + .MakeGenericMethod (types); + } + + static void MethodThatTakesArrayParameter (Type[] types) + { + } + + [ExpectedWarning ("IL2060", nameof (MethodInfo.MakeGenericMethod))] + static void TestWithArrayPassedToAnotherMethod () + { + Type[] types = new Type[1]; + types[0] = typeof (TestType); + MethodThatTakesArrayParameter (types); + typeof (MakeGenericMethod).GetMethod (nameof (GenericWithRequirements), BindingFlags.Static) + .MakeGenericMethod (types); + } + + static void TestWithNoArguments () + { + typeof (MakeGenericMethod).GetMethod (nameof (NonGenericMethod), BindingFlags.Static | BindingFlags.NonPublic) + .MakeGenericMethod (); + } + + // This should not warn since we can't be always sure about the exact overload as we don't support + // method parameter signature matching, and thus the GetMethod may return multiple potential methods. + // It can happen that some are generic and some are not. The analysis should not fail on this. + static void TestWithArgumentsButNonGenericMethod () + { + typeof (MakeGenericMethod).GetMethod (nameof (NonGenericMethod), BindingFlags.Static | BindingFlags.NonPublic) + .MakeGenericMethod (typeof (TestType)); + } + + static void NonGenericMethod () + { + } + + static void TestWithRequirements () + { + typeof (MakeGenericMethod).GetMethod (nameof (GenericWithRequirements), BindingFlags.Static) + .MakeGenericMethod (typeof (TestType)); + } + + static void TestWithRequirementsFromParam ( + [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] Type type) + { + typeof (MakeGenericMethod).GetMethod (nameof (GenericWithRequirements), BindingFlags.Static) + .MakeGenericMethod (type); + } + + static void TestWithRequirementsFromGenericParam< + [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] T> () + { + typeof (MakeGenericMethod).GetMethod (nameof (GenericWithRequirements), BindingFlags.Static) + .MakeGenericMethod (typeof (T)); + } + + + static void TestWithRequirementsViaRuntimeMethod () + { + typeof (MakeGenericMethod).GetRuntimeMethod (nameof (GenericWithRequirements), Type.EmptyTypes) + .MakeGenericMethod (typeof (TestType)); + } + + [ExpectedWarning ("IL2060", nameof (MethodInfo.MakeGenericMethod))] + static void TestWithRequirementsButNoTypeArguments () + { + typeof (MakeGenericMethod).GetMethod (nameof (GenericWithRequirements), BindingFlags.Static) + .MakeGenericMethod (Type.EmptyTypes); + } + + public static void GenericWithRequirements<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] T> () + { + } + + static void TestWithMultipleKnownGenericParameters () + { + typeof (MakeGenericMethod).GetMethod (nameof (GenericMultipleParameters), BindingFlags.Static) + .MakeGenericMethod (typeof (TestType), typeof (TestType), typeof (TestType)); + } + + [ExpectedWarning ("IL2060", nameof (MethodInfo.MakeGenericMethod))] + static void TestWithOneUnknownGenericParameter (Type[] types) + { + typeof (MakeGenericMethod).GetMethod (nameof (GenericMultipleParameters), BindingFlags.Static) + .MakeGenericMethod (typeof (TestType), typeof (TestStruct), types[0]); + } + + [ExpectedWarning ("IL2060", nameof (MethodInfo.MakeGenericMethod))] + static void TestWithPartiallyInitializedGenericTypeArray () + { + Type[] types = new Type[3]; + types[0] = typeof (TestType); + types[1] = typeof (TestStruct); + typeof (MakeGenericMethod).GetMethod (nameof (GenericMultipleParameters), BindingFlags.Static) + .MakeGenericMethod (types); + } + + static void TestWithConditionalGenericTypeSet (bool thirdParameterIsStruct) + { + Type[] types = new Type[3]; + types[0] = typeof (TestType); + types[1] = typeof (TestStruct); + if (thirdParameterIsStruct) { + types[2] = typeof (TestStruct); + } else { + types[2] = typeof (TestType); + } + typeof (MakeGenericMethod).GetMethod (nameof (GenericMultipleParameters), BindingFlags.Static) + .MakeGenericMethod (types); + } + + public static void GenericMultipleParameters< + [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] T, + [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] U, + [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] V> () + { + } + + static void TestWithNoRequirements () + { + typeof (MakeGenericMethod).GetMethod (nameof (GenericWithNoRequirements), BindingFlags.Static) + .MakeGenericMethod (typeof (TestType)); + } + + static void TestWithNoRequirementsFromParam (Type type) + { + typeof (MakeGenericMethod).GetMethod (nameof (GenericWithNoRequirements), BindingFlags.Static) + .MakeGenericMethod (type); + } + + static void TestWithNoRequirementsViaRuntimeMethod () + { + typeof (MakeGenericMethod).GetRuntimeMethod (nameof (GenericWithNoRequirements), Type.EmptyTypes) + .MakeGenericMethod (typeof (TestType)); + } + + // There are no requirements, so no warnings + static void TestWithNoRequirementsUnknownType (Type type) + { + typeof (MakeGenericMethod).GetMethod (nameof (GenericWithNoRequirements)) + .MakeGenericMethod (type); + } + + // There are no requirements, so no warnings + static void TestWithNoRequirementsWrongNumberOfTypeParameters () + { + typeof (MakeGenericMethod).GetMethod (nameof (GenericWithNoRequirements)) + .MakeGenericMethod (typeof (TestType), typeof (TestType)); + } + + // There are no requirements, so no warnings + static void TestWithNoRequirementsUnknownArrayElement () + { + Type[] types = new Type[1]; + typeof (MakeGenericMethod).GetMethod (nameof (GenericWithNoRequirements)) + .MakeGenericMethod (types); + } + + public static void GenericWithNoRequirements<T> () + { + } + + + static void TestWithMultipleArgumentsWithRequirements () + { + typeof (MakeGenericMethod).GetMethod (nameof (GenericWithMultipleArgumentsWithRequirements), BindingFlags.Static | BindingFlags.NonPublic) + .MakeGenericMethod (typeof (TestType), typeof (TestType)); + } + + static void GenericWithMultipleArgumentsWithRequirements< + TOne, + [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TTwo> () + { + } + + static void TestWithNewConstraint () + { + typeof (MakeGenericMethod).GetMethod (nameof (GenericWithNewConstraint), BindingFlags.Static | BindingFlags.NonPublic) + .MakeGenericMethod (typeof (TestType)); + } + + static void GenericWithNewConstraint<T> () where T : new() + { + var t = new T (); + } + + static void TestWithStructConstraint () + { + typeof (MakeGenericMethod).GetMethod (nameof (GenericWithStructConstraint), BindingFlags.Static | BindingFlags.NonPublic) + .MakeGenericMethod (typeof (TestType)); + } + + static void GenericWithStructConstraint<T> () where T : struct + { + var t = new T (); + } + + static void TestWithUnmanagedConstraint () + { + typeof (MakeGenericMethod).GetMethod (nameof (GenericWithUnmanagedConstraint), BindingFlags.Static | BindingFlags.NonPublic) + .MakeGenericMethod (typeof (TestType)); + } + + static void GenericWithUnmanagedConstraint<T> () where T : unmanaged + { + var t = new T (); + } + } + + public class TestType + { + } + + public struct TestStruct + { + } + } +} |