diff options
author | Vitek Karas <10670590+vitek-karas@users.noreply.github.com> | 2022-04-06 23:04:42 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-04-06 23:04:42 +0300 |
commit | e8b0ba08dcee4350cc76c8cd160140b0684020af (patch) | |
tree | 615d3bcf551029ab74d3bde34943acfa78d6eea5 /test | |
parent | d12919c43c8af7034e24069b3075f181d3473f80 (diff) |
Share GetConstructor intrinsic a lot of small fixes (#2725)
The main change is sharing of the GetConstructor intrinsic and related tests.
To make those tests work this also implements Type.EmptyTypes and String.Empty and Array.Empty intrinsics.
These are all treated as special cases:
* Type.EmptyTypes and String.Empty are actually field accesses, so we don't have infra to share these yet, no need to add one for now
* Array.Empty is a generic method where we need to know the generic instantiation. The current sharing doesn't propagate this information
so this forced the implementation to NOT be shared but instead done as a fallback which the shared one doesn't handle.
The rest of the changes are all about fixing how the shared intrinsic handling propagates return value from intrinsics.
Lot of small subtle bugs around null or emtpy inputs and forgetting to add return value and so on. The main changes are in GetMethod and GetNestedType intrinsics which had lot of issues.
Added tests for all of the corner cases.
NestedTypesUsedViaReflection test has been reworked as previously it didn't work correctly. Lot of the [Kept] attributes were fulfilled by some of the negative tests and thus the positive tests didn't have coverage (for example calling GetNestedType(unknownName) will mark all nested types on the type, so a subsequent call to GetNestedType("knownname") will not have an observable effect).
Diffstat (limited to 'test')
8 files changed, 379 insertions, 124 deletions
diff --git a/test/ILLink.RoslynAnalyzer.Tests/ReflectionTests.cs b/test/ILLink.RoslynAnalyzer.Tests/ReflectionTests.cs index 84e4e583c..605a37e47 100644 --- a/test/ILLink.RoslynAnalyzer.Tests/ReflectionTests.cs +++ b/test/ILLink.RoslynAnalyzer.Tests/ReflectionTests.cs @@ -31,8 +31,7 @@ namespace ILLink.RoslynAnalyzer.Tests [Fact] public Task ConstructorUsedViaReflection () { - // https://github.com/dotnet/linker/issues/2578 - return RunTest (allowMissingWarnings: true); + return RunTest (); } [Fact] diff --git a/test/Mono.Linker.Tests.Cases/DataFlow/GetNestedTypeOnAllAnnotatedType.cs b/test/Mono.Linker.Tests.Cases/DataFlow/GetNestedTypeOnAllAnnotatedType.cs index 7cee28667..d8f14b71e 100644 --- a/test/Mono.Linker.Tests.Cases/DataFlow/GetNestedTypeOnAllAnnotatedType.cs +++ b/test/Mono.Linker.Tests.Cases/DataFlow/GetNestedTypeOnAllAnnotatedType.cs @@ -25,9 +25,13 @@ namespace Mono.Linker.Tests.Cases.DataFlow TestWithUnknownBindingFlags (BindingFlags.Public, typeof (TestType)); TestUnsupportedBindingFlags (typeof (TestType)); TestWithNull (); + TestWithEmptyInput (); TestIfElse (1, typeof (TestType), typeof (TestType)); TestSwitchAllValid (1, typeof (TestType)); TestOnKnownTypeOnly (); + TestOnKnownTypeWithNullName (); + TestOnKnownTypeWithUnknownName ("noname"); + TestWithKnownTypeAndNameWhichDoesntExist (); } static void TestOnAllAnnotatedParameter ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)] Type parentType) @@ -68,6 +72,13 @@ namespace Mono.Linker.Tests.Cases.DataFlow nestedType.RequiresAll (); } + static void TestWithEmptyInput () + { + Type t = null; + Type noValue = Type.GetTypeFromHandle (t.TypeHandle); // Throws at runtime -> tracked as empty value set + noValue.GetNestedType (nameof (TestType.NestedType)).RequiresAll (); // No warning - empty input + } + [ExpectedWarning ("IL2072", nameof (DataFlowTypeExtensions.RequiresAll))] static void TestIfElse (int number, [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)] Type parentWithAll, [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicNestedTypes)] Type parentWithoutAll) { @@ -98,6 +109,24 @@ namespace Mono.Linker.Tests.Cases.DataFlow typeof (TestType).GetNestedType (nameof (TestType.NestedType)).RequiresAll (); } + static void TestOnKnownTypeWithNullName () + { + typeof (TestType).GetNestedType (null).RequiresAll (); + } + + [ExpectedWarning ("IL2072", nameof (DataFlowTypeExtensions.RequiresAll))] + static void TestOnKnownTypeWithUnknownName (string name) + { + // WARN - we will preserve the nested type, but not as a whole, just the type itself, so it can't fullfil the All annotation + typeof (TestType).GetNestedType (name).RequiresAll (); + } + + static void TestWithKnownTypeAndNameWhichDoesntExist () + { + // Should not warn since we can statically determine that GetNestedType will return null so there's no problem with trimming + typeof (TestType).GetNestedType ("NonExisting").RequiresAll (); + } + class TestType { public class NestedType diff --git a/test/Mono.Linker.Tests.Cases/DataFlow/MakeGenericDataFlow.cs b/test/Mono.Linker.Tests.Cases/DataFlow/MakeGenericDataFlow.cs index eebea73e0..73c6d875d 100644 --- a/test/Mono.Linker.Tests.Cases/DataFlow/MakeGenericDataFlow.cs +++ b/test/Mono.Linker.Tests.Cases/DataFlow/MakeGenericDataFlow.cs @@ -217,9 +217,20 @@ namespace Mono.Linker.Tests.Cases.DataFlow public static void Test () { TestNullMethod (); - TestNoValueMethod (); + TestNullMethodName (); + TestNullMethodName_GetRuntimeMethod (); + TestMethodOnNullType (); + TestMethodOnNullType_GetRuntimeMethod (); + TestWithEmptyInputToGetMethod (null); + TestWithEmptyInputToGetMethod_GetRuntimeMethod (null); + TestWithEmptyInputNoSuchMethod (null); + TestWithEmptyInputNoSuchMethod_GetRuntimeMethod (null); TestUnknownMethod (null); TestUnknownMethodButNoTypeArguments (null); + TestWithMultipleTypes (); + TestWithMultipleTypes_GetRuntimeMethod (); + TestWithMultipleNames (); + TestWithMultipleNames_GetRuntimeMethod (); TestNullTypeArgument (); TestNoValueTypeArgument (); TestWithUnknownTypeArray (null); @@ -261,14 +272,62 @@ namespace Mono.Linker.Tests.Cases.DataFlow mi.MakeGenericMethod (typeof (TestType)); } - [ExpectedWarning ("IL2060", nameof (MethodInfo.MakeGenericMethod) + "(Type[])")] - static void TestNoValueMethod () + static void TestNullMethodName () { // GetMethod(null) throws at runtime. MethodInfo noValue = typeof (MakeGenericMethod).GetMethod (null); noValue.MakeGenericMethod (typeof (TestType)); } + static void TestNullMethodName_GetRuntimeMethod () + { + // GetRuntimeMethod(null, ...) throws at runtime. + MethodInfo noValue = typeof (MakeGenericMethod).GetRuntimeMethod (null, new Type[] { }); + noValue.MakeGenericMethod (typeof (TestType)); + } + + static void TestMethodOnNullType () + { + Type t = null; + MethodInfo noValue = t.GetMethod (null); + noValue.MakeGenericMethod (typeof (TestType)); + } + + static void TestMethodOnNullType_GetRuntimeMethod () + { + Type t = null; + MethodInfo noValue = t.GetRuntimeMethod (null, new Type[] { }); + noValue.MakeGenericMethod (typeof (TestType)); + } + + static void TestWithEmptyInputToGetMethod (Type unknownType) + { + Type t = null; + Type noValue = Type.GetTypeFromHandle (t.TypeHandle); // Returns empty value set (throws at runtime) + // No warning - since there's no method on input + noValue.GetMethod ("NoMethod").MakeGenericMethod (unknownType); + } + + static void TestWithEmptyInputToGetMethod_GetRuntimeMethod (Type unknownType) + { + Type t = null; + Type noValue = Type.GetTypeFromHandle (t.TypeHandle); // Returns empty value set (throws at runtime) + // No warning - since there's no method on input + noValue.GetRuntimeMethod ("NoMethod", new Type[] { }).MakeGenericMethod (unknownType); + } + + static void TestWithEmptyInputNoSuchMethod (Type unknownType) + { + // No warning - the method doesn't exist, so this should throw at runtime anyway + typeof (TestType).GetMethod ("NoSuchMethod").MakeGenericMethod (unknownType); + } + + static void TestWithEmptyInputNoSuchMethod_GetRuntimeMethod (Type unknownType) + { + // No warning - the method doesn't exist, so this should throw at runtime anyway + typeof (TestType).GetRuntimeMethod ("NoSuchMethod", new Type[] { }).MakeGenericMethod (unknownType); + } + [ExpectedWarning ("IL2060", nameof (MethodInfo.MakeGenericMethod))] static void TestUnknownMethod (MethodInfo mi) { @@ -282,6 +341,94 @@ namespace Mono.Linker.Tests.Cases.DataFlow mi.MakeGenericMethod (Type.EmptyTypes); } + [ExpectedWarning ("IL2060", nameof (MethodInfo.MakeGenericMethod))] + static void TestWithMultipleTypes ( + int p = 0, + [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] Type annotatedType = null) + { + Type t = null; + switch (p) { + case 0: + t = typeof (MakeGenericMethod); + break; + case 1: + t = null; + break; + case 2: + t = annotatedType; + break; + } + + // This should warn just once due to case 2 - annotated type, but unknown method + t.GetMethod (nameof (GenericWithNoRequirements), BindingFlags.Static).MakeGenericMethod (new Type[] { typeof (TestType) }); + } + + [ExpectedWarning ("IL2060", nameof (MethodInfo.MakeGenericMethod))] + static void TestWithMultipleTypes_GetRuntimeMethod ( + int p = 0, + [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] Type annotatedType = null) + { + Type t = null; + switch (p) { + case 0: + t = typeof (MakeGenericMethod); + break; + case 1: + t = null; + break; + case 2: + t = annotatedType; + break; + } + + // This should warn just once due to case 2 - annotated type, but unknown method + t.GetRuntimeMethod (nameof (GenericWithNoRequirements), new Type[] { }).MakeGenericMethod (new Type[] { typeof (TestType) }); + } + + [ExpectedWarning ("IL2060", nameof (MethodInfo.MakeGenericMethod))] + static void TestWithMultipleNames ( + int p = 0, + string unknownName = null) + { + string name = null; + switch (p) { + case 0: + name = nameof (GenericWithNoRequirements); + break; + case 1: + name = null; + break; + case 2: + name = unknownName; + break; + } + + // This should warn just once due to case 2 - unknown name + typeof (MakeGenericMethod).GetMethod (name, BindingFlags.Static).MakeGenericMethod (new Type[] { typeof (TestType) }); + } + + [ExpectedWarning ("IL2060", nameof (MethodInfo.MakeGenericMethod))] + static void TestWithMultipleNames_GetRuntimeMethod ( + int p = 0, + string unknownName = null) + { + string name = null; + switch (p) { + case 0: + name = nameof (GenericWithNoRequirements); + break; + case 1: + name = null; + break; + case 2: + name = unknownName; + break; + } + + // This should warn just once due to case 2 - unknown name + typeof (MakeGenericMethod).GetRuntimeMethod (name, new Type[] { }).MakeGenericMethod (new Type[] { typeof (TestType) }); + } + static void TestNullTypeArgument () { Type t = null; diff --git a/test/Mono.Linker.Tests.Cases/DataFlow/NullableAnnotations.cs b/test/Mono.Linker.Tests.Cases/DataFlow/NullableAnnotations.cs index 1ab063e3a..527179fc6 100644 --- a/test/Mono.Linker.Tests.Cases/DataFlow/NullableAnnotations.cs +++ b/test/Mono.Linker.Tests.Cases/DataFlow/NullableAnnotations.cs @@ -56,6 +56,7 @@ namespace Mono.Linker.Tests.Cases.DataFlow TestGetUnderlyingTypeOnStructs (); TestAnnotationsOnNullableKeepsMembersOnUnderlyingType (); TestGetUnderlyingTypeOfCreatedNullableOnStructs (); + TestGetUnderlyingTypeOnEmptyInput (); ImproperMakeGenericTypeDoesntWarn (); MakeGenericTypeWithUnknownValue (new object[2] { 1, 2 }); } @@ -192,6 +193,15 @@ namespace Mono.Linker.Tests.Cases.DataFlow NullableOfUnannotatedGenericParameterRequiresPublicProperties<TestType> (); } + [Kept] + static void TestGetUnderlyingTypeOnEmptyInput () + { + Type t = null; + Type noValue = Type.GetTypeFromHandle (t.TypeHandle); // This throws at runtime, data flow will track the result as empty value set + // No warning - since there's no value on input + Nullable.GetUnderlyingType (noValue).RequiresPublicProperties (); + } + [Kept] [return: DynamicallyAccessedMembers (DAMT.PublicProperties)] diff --git a/test/Mono.Linker.Tests.Cases/Reflection/ConstructorUsedViaReflection.cs b/test/Mono.Linker.Tests.Cases/Reflection/ConstructorUsedViaReflection.cs index a4b01a9ac..27609cd22 100644 --- a/test/Mono.Linker.Tests.Cases/Reflection/ConstructorUsedViaReflection.cs +++ b/test/Mono.Linker.Tests.Cases/Reflection/ConstructorUsedViaReflection.cs @@ -52,12 +52,28 @@ namespace Mono.Linker.Tests.Cases.Reflection } [Kept] + class CtorWithRUC + { + [Kept] + [KeptAttributeAttribute (typeof (RequiresUnreferencedCodeAttribute))] + [RequiresUnreferencedCode (nameof (CtorWithRUC) + "()")] + public CtorWithRUC () { } + + [Kept] + [KeptAttributeAttribute (typeof (RequiresUnreferencedCodeAttribute))] + [RequiresUnreferencedCode (nameof (CtorWithRUC) + "(int)")] + public CtorWithRUC (int i) { } + } + + [Kept] public static void Test () { TestConstructorWithTypes_EmptyTypes (); TestConstructorWithTypes_NonEmptyTypes (); TestConstructorWithTypes_EmptyTypes_DataFlow (typeof (TestType)); TestConstructorWithTypes_NonEmptyTypes_DataFlow (typeof (TestType)); + TestConstructorWithTypes_EmptyTypes_RUCOnCtor (); + TestConstructorWithTypes_NonEmptyTypes_RUCOnCtor (); } [Kept] @@ -94,6 +110,21 @@ namespace Mono.Linker.Tests.Cases.Reflection var constructor = type.GetConstructor (new Type[] { typeof (int) }); constructor.Invoke (null, new object[] { null }); } + + [Kept] + [ExpectedWarning ("IL2026", nameof (CtorWithRUC) + "()")] + static void TestConstructorWithTypes_EmptyTypes_RUCOnCtor () + { + typeof (CtorWithRUC).GetConstructor (new Type[] { }); + } + + [Kept] + [ExpectedWarning ("IL2026", nameof (CtorWithRUC) + "()")] + [ExpectedWarning ("IL2026", nameof (CtorWithRUC) + "(int)")] + static void TestConstructorWithTypes_NonEmptyTypes_RUCOnCtor () + { + typeof (CtorWithRUC).GetConstructor (new Type[] { typeof (int) }); + } } [Kept] diff --git a/test/Mono.Linker.Tests.Cases/Reflection/MethodUsedViaReflection.cs b/test/Mono.Linker.Tests.Cases/Reflection/MethodUsedViaReflection.cs index 393a2ea5e..079c7eae7 100644 --- a/test/Mono.Linker.Tests.Cases/Reflection/MethodUsedViaReflection.cs +++ b/test/Mono.Linker.Tests.Cases/Reflection/MethodUsedViaReflection.cs @@ -286,7 +286,6 @@ namespace Mono.Linker.Tests.Cases.Reflection { private static void Known () { } - [Kept] // Currently this is kept as we don't have a special case for null constant (not worth it) public void AlsoKnown () { } } @@ -833,33 +832,9 @@ namespace Mono.Linker.Tests.Cases.Reflection } } - [Kept] - public static int OnlyCalledViaReflection () - { - return 42; - } - - private static int PrivateMethod () + public static int Unused () { return 42; } - - [Kept] - public int OnlyCalledViaReflection (int foo) - { - return 43; - } - - // This one will not be kept as we're only ever ask for public methods of this name - int OnlyCalledViaReflection (int foo, int bar) - { - return 44; - } - - [Kept] - public static int OnlyCalledViaReflection (int foo, int bar, int baz) - { - return 45; - } } } diff --git a/test/Mono.Linker.Tests.Cases/Reflection/NestedTypeUsedViaReflection.cs b/test/Mono.Linker.Tests.Cases/Reflection/NestedTypeUsedViaReflection.cs index 5162dea51..7789cd8bc 100644 --- a/test/Mono.Linker.Tests.Cases/Reflection/NestedTypeUsedViaReflection.cs +++ b/test/Mono.Linker.Tests.Cases/Reflection/NestedTypeUsedViaReflection.cs @@ -13,95 +13,160 @@ namespace Mono.Linker.Tests.Cases.Reflection { public static void Main () { - TestByName (); - TestPrivateByName (); - TestNullName (); - TestEmptyName (); - TestNoValueName (); - TestByBindingFlags (); - TestByUnknownBindingFlags (BindingFlags.Public); - TestByUnknownBindingFlagsAndName (BindingFlags.Public, "DoesntMatter"); - TestNonExistingName (); + ByName.Test (); + PrivateByName.Test (); + NullName.Test (); + EmptyName.Test (); + NoValueName.Test (); + WithBindingFlags.Test (); + UnknownBindingFlags.Test (BindingFlags.Public); + UnknownBindingFlagsAndName.Test (BindingFlags.Public, "DoesntMatter"); + NonExistingName.Test (); TestNullType (); TestNoValue (); - TestIgnoreCaseBindingFlags (); - TestFailIgnoreCaseBindingFlags (); - TestUnsupportedBindingFlags (); - } + IgnoreCaseBindingFlags.Test (); + FailIgnoreCaseBindingFlags.Test (); + UnsupportedBindingFlags.Test (); - [Kept] - public static class NestedType { } + MemberOnNestedType.Test (); + } [Kept] - static void TestByName () + static class ByName { - _ = typeof (NestedTypeUsedViaReflection).GetNestedType (nameof (NestedType)); - } + [Kept] + public static class NestedType { } - static class PrivateUnreferencedNestedType { } + [Kept] + public static void Test () + { + _ = typeof (ByName).GetNestedType (nameof (NestedType)); + } + } - [Kept] - static void TestPrivateByName () + static class PrivateByName { - _ = typeof (NestedTypeUsedViaReflection).GetNestedType (nameof (PrivateUnreferencedNestedType)); // This will not mark the nested type as GetNestedType(string) only returns public - _ = typeof (NestedTypeUsedViaReflection).GetNestedType (nameof (PrivateUnreferencedNestedType), BindingFlags.Public); + static class PrivateUnreferencedNestedType { } + + [Kept] + public static void Test () + { + _ = typeof (PrivateByName).GetNestedType (nameof (PrivateUnreferencedNestedType)); // This will not mark the nested type as GetNestedType(string) only returns public + _ = typeof (PrivateByName).GetNestedType (nameof (PrivateUnreferencedNestedType), BindingFlags.Public); + } } - [Kept] - static void TestNullName () + static class NullName { - _ = typeof (NestedTypeUsedViaReflection).GetNestedType (null); + public static class UnusedNestedType { } + + [Kept] + public static void Test () + { + _ = typeof (NullName).GetNestedType (null); + } } - [Kept] - static void TestEmptyName () + static class EmptyName { - _ = typeof (NestedTypeUsedViaReflection).GetNestedType (string.Empty); + public static class UnusedNestedType { } + + [Kept] + public static void Test () + { + _ = typeof (EmptyName).GetNestedType (string.Empty); + } } - [Kept] - static void TestNoValueName () + static class NoValueName { - Type t = null; - string noValue = t.AssemblyQualifiedName; - var method = typeof (NestedTypeUsedViaReflection).GetNestedType (noValue); + public static class UnusedNestedType { } + + [Kept] + public static void Test () + { + Type t = null; + string noValue = t.AssemblyQualifiedName; + var method = typeof (NoValueName).GetNestedType (noValue); + } } - [Kept] - public static class PublicNestedType { } + static class WithBindingFlags + { + [Kept] + public static class PublicNestedType { } - [Kept] - private static class PrivateNestedType { } + [Kept] + private static class PrivateNestedType { } - [Kept] - protected static class ProtectedNestedType { } + [Kept] + protected static class ProtectedNestedType { } - [Kept] - static void TestByBindingFlags () - { - _ = typeof (NestedTypeUsedViaReflection).GetNestedType (nameof (PrivateNestedType), BindingFlags.NonPublic); - _ = typeof (NestedTypeUsedViaReflection).GetNestedType (nameof (PublicNestedType), BindingFlags.Public); - _ = typeof (NestedTypeUsedViaReflection).GetNestedType (nameof (ProtectedNestedType), BindingFlags.NonPublic); + public static class UnusedPublicNestedType { } + + [Kept] + public static void Test () + { + _ = typeof (WithBindingFlags).GetNestedType (nameof (PrivateNestedType), BindingFlags.NonPublic); + _ = typeof (WithBindingFlags).GetNestedType (nameof (PublicNestedType), BindingFlags.Public); + _ = typeof (WithBindingFlags).GetNestedType (nameof (ProtectedNestedType), BindingFlags.NonPublic); + } } - [Kept] - static void TestByUnknownBindingFlags (BindingFlags bindingFlags) + static class UnknownBindingFlags { - // Since the binding flags are not known linker should mark all nested types on the type - _ = typeof (UnknownBindingFlags).GetNestedType (nameof (PublicNestedType), bindingFlags); + [Kept] + public static class PublicNestedType { } + + [Kept] + public static class AnotherPublicNestedType { } + + [Kept] + private static class PrivateNestedType { } + + [Kept] + protected static class ProtectedNestedType { } + + [Kept] + public static void Test (BindingFlags bindingFlags) + { + // Since the binding flags are not known linker should mark all nested types on the type + _ = typeof (UnknownBindingFlags).GetNestedType (nameof (PublicNestedType), bindingFlags); + } } - [Kept] - static void TestByUnknownBindingFlagsAndName (BindingFlags bindingFlags, string name) + static class UnknownBindingFlagsAndName { - // Since the binding flags and name are not known linker should mark all nested types on the type - _ = typeof (UnknownBindingFlagsAndName).GetNestedType (name, bindingFlags); + [Kept] + public static class PublicNestedType { } + + [Kept] + public static class AnotherPublicNestedType { } + + [Kept] + private static class PrivateNestedType { } + + [Kept] + protected static class ProtectedNestedType { } + + [Kept] + public static void Test (BindingFlags bindingFlags, string name) + { + // Since the binding flags and name are not known linker should mark all nested types on the type + _ = typeof (UnknownBindingFlagsAndName).GetNestedType (name, bindingFlags); + } } - [Kept] - static void TestNonExistingName () + static class NonExistingName { - _ = typeof (NestedTypeUsedViaReflection).GetNestedType ("NonExisting"); + public static class UnusedNestedType { } + + + [Kept] + public static void Test () + { + _ = typeof (NonExistingName).GetNestedType ("NonExisting"); + } } [Kept] @@ -120,67 +185,66 @@ namespace Mono.Linker.Tests.Cases.Reflection } [Kept] - static void TestIgnoreCaseBindingFlags () - { - _ = typeof (IgnoreCaseClass).GetNestedType ("ignorecasepublicnestedtype", BindingFlags.IgnoreCase | BindingFlags.Public); - } - - [Kept] - static void TestFailIgnoreCaseBindingFlags () - { - _ = typeof (FailIgnoreCaseClass).GetNestedType ("failignorecasepublicnestedtype", BindingFlags.Public); - } - - [Kept] - static void TestUnsupportedBindingFlags () - { - _ = typeof (SuppressChangeTypeClass).GetNestedType ("SuppressChangeTypeNestedType", BindingFlags.SuppressChangeType); - } - - [Kept] - private class UnknownBindingFlags + private class MemberOnNestedType { [Kept] - public static class PublicNestedType { } - - [Kept] - private static class PrivateNestedType { } - } + public static class PublicNestedTypeWithMembers + { + public static void UnusedMethod () { } - [Kept] - private class UnknownBindingFlagsAndName - { - [Kept] - public static class PublicNestedType { } + [Kept] + public static void UsedMethod () { } + } [Kept] - private static class PrivateNestedType { } + public static void Test () + { + typeof (MemberOnNestedType).GetNestedType (nameof (PublicNestedTypeWithMembers)).GetMethod (nameof (PublicNestedTypeWithMembers.UsedMethod)); + } } [Kept] - private class IgnoreCaseClass + static class IgnoreCaseBindingFlags { [Kept] public static class IgnoreCasePublicNestedType { } [Kept] public static class MarkedDueToIgnoreCase { } + + [Kept] + public static void Test () + { + _ = typeof (IgnoreCaseBindingFlags).GetNestedType ("ignorecasepublicnestedtype", BindingFlags.IgnoreCase | BindingFlags.Public); + } } [Kept] - private class FailIgnoreCaseClass + private class FailIgnoreCaseBindingFlags { public static class FailIgnoreCasePublicNestedType { } + + [Kept] + public static void Test () + { + _ = typeof (FailIgnoreCaseBindingFlags).GetNestedType ("failignorecasepublicnestedtype", BindingFlags.Public); + } } [Kept] - private class SuppressChangeTypeClass + private class UnsupportedBindingFlags { [Kept] public static class SuppressChangeTypeNestedType { } [Kept] private static class MarkedDueToSuppressChangeType { } + + [Kept] + public static void Test () + { + _ = typeof (UnsupportedBindingFlags).GetNestedType ("SuppressChangeTypeNestedType", BindingFlags.SuppressChangeType); + } } } } diff --git a/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresOnClass.cs b/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresOnClass.cs index f32949af3..64fed96f2 100644 --- a/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresOnClass.cs +++ b/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresOnClass.cs @@ -540,9 +540,9 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability typeof (DerivedWithRequiresOnBaseWithoutRequires).RequiresPublicConstructors (); } - [ExpectedWarning ("IL2026", "BaseWithRequires.BaseWithRequires()", ProducedBy = ProducedBy.Trimmer)] - [ExpectedWarning ("IL2026", "DerivedWithRequiresOnBaseWithRequires.DerivedWithRequiresOnBaseWithRequires()", ProducedBy = ProducedBy.Trimmer)] - [ExpectedWarning ("IL2026", "DerivedWithRequiresOnBaseWithoutRequires.DerivedWithRequiresOnBaseWithoutRequires()", ProducedBy = ProducedBy.Trimmer)] + [ExpectedWarning ("IL2026", "BaseWithRequires.BaseWithRequires()")] + [ExpectedWarning ("IL2026", "DerivedWithRequiresOnBaseWithRequires.DerivedWithRequiresOnBaseWithRequires()")] + [ExpectedWarning ("IL2026", "DerivedWithRequiresOnBaseWithoutRequires.DerivedWithRequiresOnBaseWithoutRequires()")] static void TestDirectReflectionAccess () { typeof (BaseWithRequires).GetConstructor (Type.EmptyTypes); |