From 56421a1b1c1713d9d02567f481595d6b7b5ac000 Mon Sep 17 00:00:00 2001 From: Lakshan Fernando Date: Mon, 31 Jan 2022 16:27:34 -0800 Subject: 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 --- .../DataFlow/GenericParameterDataFlow.cs | 808 +++++---------------- .../DataFlow/MakeGenericDataFlow.cs | 501 +++++++++++++ 2 files changed, 684 insertions(+), 625 deletions(-) create mode 100644 test/Mono.Linker.Tests.Cases/DataFlow/MakeGenericDataFlow.cs (limited to 'test/Mono.Linker.Tests.Cases/DataFlow') 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 (); TestStructConstraintSatisfiesParameterlessConstructor (); TestUnmanagedConstraintSatisfiesParameterlessConstructor (); @@ -45,11 +42,6 @@ namespace Mono.Linker.Tests.Cases.DataFlow TypeRequiresNothingPassThrough.Test (); } - static void TestGenericParameterFlowsToField () - { - TypeRequiresPublicFields.TestFields (); - } - static void TestGenericParameterFlowsToReturnValue () { _ = TypeRequiresPublicFields.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), 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 (); + TestDerivedTypeWithOpenGenericOnBaseWithRUCOnBase (); + TestDerivedTypeWithOpenGenericOnBaseWithRUCOnDerived (); + new DerivedTypeWithOpenGenericOnBaseWithRequirements (); + } + + class GenericBaseTypeWithRequirements<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] T> + { + public GenericBaseTypeWithRequirements () + { + typeof (T).RequiresPublicFields (); + } + } + + class DerivedTypeWithInstantiatedGenericOnBase : GenericBaseTypeWithRequirements + { + } + + class DerivedTypeWithInstantiationOverSelfOnBase : GenericBaseTypeWithRequirements + { + } + + [ExpectedWarning ("IL2091", nameof (GenericBaseTypeWithRequirements))] + class DerivedTypeWithOpenGenericOnBase : GenericBaseTypeWithRequirements + { + // Analyzer does not see the base class constructor + [ExpectedWarning ("IL2091", nameof (GenericBaseTypeWithRequirements), ProducedBy = ProducedBy.Trimmer)] + public DerivedTypeWithOpenGenericOnBase () { } + } + + static void TestDerivedTypeWithOpenGenericOnBaseWithRUCOnBase () + { + new DerivedTypeWithOpenGenericOnBaseWithRUCOnBase (); + } + + [ExpectedWarning ("IL2109", nameof (BaseTypeWithOpenGenericDAMTAndRUC))] + [ExpectedWarning ("IL2091", nameof (BaseTypeWithOpenGenericDAMTAndRUC))] + class DerivedTypeWithOpenGenericOnBaseWithRUCOnBase : BaseTypeWithOpenGenericDAMTAndRUC + { + [ExpectedWarning ("IL2091", nameof (DerivedTypeWithOpenGenericOnBaseWithRUCOnBase), ProducedBy = ProducedBy.Trimmer)] + [ExpectedWarning ("IL2026", nameof (BaseTypeWithOpenGenericDAMTAndRUC), ProducedBy = ProducedBy.Trimmer)] + public DerivedTypeWithOpenGenericOnBaseWithRUCOnBase () { } + } + + [RequiresUnreferencedCode ("RUC")] + class BaseTypeWithOpenGenericDAMTAndRUC<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)] T> { } + + + [ExpectedWarning ("IL2026", nameof (DerivedTypeWithOpenGenericOnBaseWithRUCOnDerived))] + static void TestDerivedTypeWithOpenGenericOnBaseWithRUCOnDerived () + { + new DerivedTypeWithOpenGenericOnBaseWithRUCOnDerived (); + } + [ExpectedWarning ("IL2091", nameof (BaseTypeWithOpenGenericDAMT))] + [RequiresUnreferencedCode ("RUC")] + class DerivedTypeWithOpenGenericOnBaseWithRUCOnDerived : BaseTypeWithOpenGenericDAMT + { + } + + class BaseTypeWithOpenGenericDAMT<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)] T> { } + + + class DerivedTypeWithOpenGenericOnBaseWithRequirements<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] T> + : GenericBaseTypeWithRequirements + { + } + static void TestMultipleGenericParametersOnType () { MultipleTypesWithDifferentRequirements.TestMultiple (); @@ -216,46 +277,27 @@ namespace Mono.Linker.Tests.Cases.DataFlow } } - static void TestBaseTypeGenericRequirements () + static void TestDeepNestedTypesWithGenerics () { - new DerivedTypeWithInstantiatedGenericOnBase (); - new DerivedTypeWithInstantiationOverSelfOnBase (); - new DerivedTypeWithOpenGenericOnBase (); - new DerivedTypeWithOpenGenericOnBaseWithRequirements (); + RootTypeWithRequirements.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", + "type", + "DataFlowTypeExtensions.RequiresPublicMethods(Type)")] + public static void TestAccess () + { + typeof (TRoot).RequiresPublicFields (); + typeof (TRoot).RequiresPublicMethods (); + } } } - class DerivedTypeWithInstantiatedGenericOnBase : GenericBaseTypeWithRequirements - { - } - - class GenericBaseTypeWithRequiresAll<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)] T> - { - } - - class DerivedTypeWithInstantiationOverSelfOnBase : GenericBaseTypeWithRequirements - { - } - - [ExpectedWarning ("IL2091", nameof (GenericBaseTypeWithRequirements))] - class DerivedTypeWithOpenGenericOnBase : GenericBaseTypeWithRequirements - { - [ExpectedWarning ("IL2091", nameof (GenericBaseTypeWithRequirements))] - public DerivedTypeWithOpenGenericOnBase () { } - } - - class DerivedTypeWithOpenGenericOnBaseWithRequirements<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] T> - : GenericBaseTypeWithRequirements - { - } - static void TestInterfaceTypeGenericRequirements () { IGenericInterfaceTypeWithRequirements instance = new InterfaceImplementationTypeWithInstantiatedGenericOnBase (); @@ -284,35 +326,11 @@ namespace Mono.Linker.Tests.Cases.DataFlow class InterfaceImplementationTypeWithOpenGenericOnBase : IGenericInterfaceTypeWithRequirements { } - class InterfaceImplementationTypeWithOpenGenericOnBaseWithRequirements<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] T> : IGenericInterfaceTypeWithRequirements { } - static void TestDeepNestedTypesWithGenerics () - { - RootTypeWithRequirements.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.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), ProducedBy = ProducedBy.Analyzer)] public TypeRequiresPublicMethods PublicMethodsProperty { - [ExpectedWarning ("IL2091", nameof (TypeRequiresPublicMethods))] + [ExpectedWarning ("IL2091", nameof (TypeRequiresPublicMethods), ProducedBy = ProducedBy.Trimmer)] get => null; - [ExpectedWarning ("IL2091", nameof (TypeRequiresPublicMethods))] + [ExpectedWarning ("IL2091", nameof (TypeRequiresPublicMethods), ProducedBy = ProducedBy.Trimmer)] set { } } @@ -360,8 +379,9 @@ namespace Mono.Linker.Tests.Cases.DataFlow public void PublicMethodsMethodParameter (TypeRequiresPublicMethods param) { } public TypeRequiresPublicFields PublicFieldsMethodReturnValue () { return null; } - [ExpectedWarning ("IL2091", nameof (TypeRequiresPublicMethods))] // Return value - [ExpectedWarning ("IL2091", nameof (TypeRequiresPublicMethods))] // Compiler generated local variable + + [ExpectedWarning ("IL2091", nameof (TypeRequiresPublicMethods), ProducedBy = ProducedBy.Trimmer)] + [ExpectedWarning ("IL2091", nameof (TypeRequiresPublicMethods))] public TypeRequiresPublicMethods PublicMethodsMethodReturnValue () { return null; } public void PublicFieldsMethodLocalVariable () @@ -404,7 +424,8 @@ namespace Mono.Linker.Tests.Cases.DataFlow class PartialyInstantiatedMethods<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TOuter> : BaseForPartialInstantiation { - [ExpectedWarning ("IL2091", nameof (BaseForPartialInstantiation), "'TMethods'")] + // Analyzer does not see the base class constructor + [ExpectedWarning ("IL2091", nameof (BaseForPartialInstantiation), "'TMethods'", ProducedBy = ProducedBy.Trimmer)] public PartialyInstantiatedMethods () { } } @@ -467,6 +488,79 @@ namespace Mono.Linker.Tests.Cases.DataFlow MethodRequiresNothing (); } + static void TestMultipleGenericParametersOnMethod () + { + MethodMultipleWithDifferentRequirements_TestMultiple (); + MethodMultipleWithDifferentRequirements_TestFields (); + MethodMultipleWithDifferentRequirements_TestMethods (); + MethodMultipleWithDifferentRequirements_TestBoth (); + MethodMultipleWithDifferentRequirements_TestNothing (); + } + + static void MethodMultipleWithDifferentRequirements_TestMultiple< + [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TFields, + [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TMethods, + [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.PublicMethods)] TBoth, + TNothing> () + { + typeof (TFields).RequiresPublicFields (); ; + typeof (TMethods).RequiresPublicMethods (); + typeof (TBoth).RequiresPublicFields (); ; + typeof (TBoth).RequiresPublicMethods (); + typeof (TFields).RequiresNone (); + typeof (TMethods).RequiresNone (); + typeof (TBoth).RequiresNone (); + typeof (TNothing).RequiresNone (); + } + + [ExpectedWarning ("IL2087", nameof (DataFlowTypeExtensions.RequiresPublicMethods))] + static void MethodMultipleWithDifferentRequirements_TestFields< + [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TFields, + [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TMethods, + [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.PublicMethods)] TBoth, + TNothing> () + { + typeof (TFields).RequiresPublicFields (); ; + typeof (TFields).RequiresPublicMethods (); + typeof (TFields).RequiresNone (); + } + + [ExpectedWarning ("IL2087", nameof (DataFlowTypeExtensions.RequiresPublicFields))] + static void MethodMultipleWithDifferentRequirements_TestMethods< + [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TFields, + [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TMethods, + [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.PublicMethods)] TBoth, + TNothing> () + { + typeof (TMethods).RequiresPublicFields (); + typeof (TMethods).RequiresPublicMethods (); + typeof (TMethods).RequiresNone (); + } + + static void MethodMultipleWithDifferentRequirements_TestBoth< + [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TFields, + [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TMethods, + [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.PublicMethods)] TBoth, + TNothing> () + { + typeof (TBoth).RequiresPublicFields (); + typeof (TBoth).RequiresPublicMethods (); + typeof (TBoth).RequiresNone (); + } + + [ExpectedWarning ("IL2087", nameof (DataFlowTypeExtensions.RequiresPublicFields))] + [ExpectedWarning ("IL2087", nameof (DataFlowTypeExtensions.RequiresPublicMethods))] + static void MethodMultipleWithDifferentRequirements_TestNothing< + [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TFields, + [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TMethods, + [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.PublicMethods)] TBoth, + TNothing> () + { + typeof (TNothing).RequiresPublicFields (); + typeof (TNothing).RequiresPublicMethods (); + typeof (TNothing).RequiresNone (); + } + static void TestMethodGenericParametersViaInheritance () { TypeWithInstantiatedGenericMethodViaGenericParameter.StaticRequiresPublicFields (); @@ -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 { @@ -551,11 +646,18 @@ namespace Mono.Linker.Tests.Cases.DataFlow StaticRequiresMultipleGenericParams (); } + [ExpectedWarning ("IL2091", + nameof (TOuter), + "Mono.Linker.Tests.Cases.DataFlow.GenericParameterDataFlow.TypeWithInstantiatedGenericMethodViaGenericParameter", + "TMethods", + "Mono.Linker.Tests.Cases.DataFlow.GenericParameterDataFlow.BaseTypeWithGenericMethod.StaticRequiresMultipleGenericParams()", + ProducedBy = ProducedBy.Analyzer)] [ExpectedWarning ("IL2091", "'TOuter'", "Mono.Linker.Tests.Cases.DataFlow.GenericParameterDataFlow.TypeWithInstantiatedGenericMethodViaGenericParameter", "'TMethods'", - "Mono.Linker.Tests.Cases.DataFlow.GenericParameterDataFlow.BaseTypeWithGenericMethod.StaticRequiresMultipleGenericParams()")] + "Mono.Linker.Tests.Cases.DataFlow.GenericParameterDataFlow.BaseTypeWithGenericMethod.StaticRequiresMultipleGenericParams()", + ProducedBy = ProducedBy.Trimmer)] public static void StaticPartialInstantiationUnrecognized () { StaticRequiresMultipleGenericParams (); @@ -616,554 +718,6 @@ namespace Mono.Linker.Tests.Cases.DataFlow } } - - static void TestMultipleGenericParametersOnMethod () - { - MethodMultipleWithDifferentRequirements_TestMultiple (); - MethodMultipleWithDifferentRequirements_TestFields (); - MethodMultipleWithDifferentRequirements_TestMethods (); - MethodMultipleWithDifferentRequirements_TestBoth (); - MethodMultipleWithDifferentRequirements_TestNothing (); - } - - static void MethodMultipleWithDifferentRequirements_TestMultiple< - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TFields, - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TMethods, - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.PublicMethods)] TBoth, - TNothing> () - { - typeof (TFields).RequiresPublicFields (); ; - typeof (TMethods).RequiresPublicMethods (); - typeof (TBoth).RequiresPublicFields (); ; - typeof (TBoth).RequiresPublicMethods (); - typeof (TFields).RequiresNone (); - typeof (TMethods).RequiresNone (); - typeof (TBoth).RequiresNone (); - typeof (TNothing).RequiresNone (); - } - - [ExpectedWarning ("IL2087", nameof (DataFlowTypeExtensions.RequiresPublicMethods))] - static void MethodMultipleWithDifferentRequirements_TestFields< - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TFields, - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TMethods, - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.PublicMethods)] TBoth, - TNothing> () - { - typeof (TFields).RequiresPublicFields (); ; - typeof (TFields).RequiresPublicMethods (); - typeof (TFields).RequiresNone (); - } - - [ExpectedWarning ("IL2087", nameof (DataFlowTypeExtensions.RequiresPublicFields))] - static void MethodMultipleWithDifferentRequirements_TestMethods< - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TFields, - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TMethods, - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.PublicMethods)] TBoth, - TNothing> () - { - typeof (TMethods).RequiresPublicFields (); - typeof (TMethods).RequiresPublicMethods (); - typeof (TMethods).RequiresNone (); - } - - static void MethodMultipleWithDifferentRequirements_TestBoth< - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TFields, - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TMethods, - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.PublicMethods)] TBoth, - TNothing> () - { - typeof (TBoth).RequiresPublicFields (); - typeof (TBoth).RequiresPublicMethods (); - typeof (TBoth).RequiresNone (); - } - - [ExpectedWarning ("IL2087", nameof (DataFlowTypeExtensions.RequiresPublicFields))] - [ExpectedWarning ("IL2087", nameof (DataFlowTypeExtensions.RequiresPublicMethods))] - static void MethodMultipleWithDifferentRequirements_TestNothing< - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TFields, - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TMethods, - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.PublicMethods)] TBoth, - TNothing> () - { - typeof (TNothing).RequiresPublicFields (); - typeof (TNothing).RequiresPublicMethods (); - typeof (TNothing).RequiresNone (); - } - - - class MakeGenericType - { - public static void Test () - { - TestNullType (); - TestUnknownInput (null); - TestWithUnknownTypeArray (null); - TestWithArrayUnknownIndexSet (0); - TestWithArrayUnknownLengthSet (1); - TestNoArguments (); - - TestWithRequirements (); - TestWithRequirementsFromParam (null); - TestWithRequirementsFromParamWithMismatch (null); - TestWithRequirementsFromGenericParam (); - TestWithRequirementsFromGenericParamWithMismatch (); - - 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 - { - } - - 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 where T : new() - { - } - - static void TestWithStructConstraint () - { - typeof (GenericWithStructConstraint<>).MakeGenericType (typeof (TestType)); - } - - class GenericWithStructConstraint where T : struct - { - } - - static void TestWithUnmanagedConstraint () - { - typeof (GenericWithUnmanagedConstraint<>).MakeGenericType (typeof (TestType)); - } - - class GenericWithUnmanagedConstraint 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 (); - 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 () - { - } - - - 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 () 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 () 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 () where T : unmanaged - { - var t = new T (); - } - } - static void TestNewConstraintSatisfiesParameterlessConstructor () where T : new() { RequiresParameterlessConstructor (); @@ -1173,7 +727,6 @@ namespace Mono.Linker.Tests.Cases.DataFlow { RequiresParameterlessConstructor (); } - static void TestUnmanagedConstraintSatisfiesParameterlessConstructor () where T : unmanaged { RequiresParameterlessConstructor (); @@ -1183,12 +736,17 @@ namespace Mono.Linker.Tests.Cases.DataFlow { } - public class TestType + static void TestGenericParameterFlowsToField () { + TypeRequiresPublicFields.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 (); + TestWithRequirementsFromGenericParamWithMismatch (); + + 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 + { + } + + 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 where T : new() + { + } + + static void TestWithStructConstraint () + { + typeof (GenericWithStructConstraint<>).MakeGenericType (typeof (TestType)); + } + + class GenericWithStructConstraint where T : struct + { + } + + static void TestWithUnmanagedConstraint () + { + typeof (GenericWithUnmanagedConstraint<>).MakeGenericType (typeof (TestType)); + } + + class GenericWithUnmanagedConstraint 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 (); + 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 () + { + } + + + 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 () 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 () 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 () where T : unmanaged + { + var t = new T (); + } + } + + public class TestType + { + } + + public struct TestStruct + { + } + } +} -- cgit v1.2.3