From ab9e2862d357a1a45b9908f431913255fd7b240a Mon Sep 17 00:00:00 2001 From: vitek-karas <10670590+vitek-karas@users.noreply.github.com> Date: Mon, 3 Jan 2022 05:27:39 -0800 Subject: [PATCH 1/2] Propagate Interfaces annotation through Type.BaseType The Interfaces annotation makes sure the type has all interfaces, meaning `GetInterfaces` reflection call will work on it. That means that all interfaces of the base type are also preserved, so the `Interfaces` annotation should be propagated to the base type as well. --- .../ReflectionMethodBodyScanner.cs | 3 ++ .../DataFlow/TypeBaseTypeDataFlow.cs | 8 ++++ .../Reflection/TypeUsedViaReflection.cs | 38 +++++++++++++++++++ 3 files changed, 49 insertions(+) diff --git a/src/linker/Linker.Dataflow/ReflectionMethodBodyScanner.cs b/src/linker/Linker.Dataflow/ReflectionMethodBodyScanner.cs index d90565b6dd4c..476e86bcf6e6 100644 --- a/src/linker/Linker.Dataflow/ReflectionMethodBodyScanner.cs +++ b/src/linker/Linker.Dataflow/ReflectionMethodBodyScanner.cs @@ -1294,6 +1294,9 @@ public override bool HandleCall (MethodBody callingMethodBody, MethodReference c if (dynamicallyAccessedMemberNode.DynamicallyAccessedMemberTypes.HasFlag (DynamicallyAccessedMemberTypes.PublicProperties)) propagatedMemberTypes |= DynamicallyAccessedMemberTypes.PublicProperties; + + if (dynamicallyAccessedMemberNode.DynamicallyAccessedMemberTypes.HasFlag (DynamicallyAccessedMemberTypes.Interfaces)) + propagatedMemberTypes |= DynamicallyAccessedMemberTypes.Interfaces; } methodReturnValue = MergePointValue.MergeValues (methodReturnValue, CreateMethodReturnValue (calledMethod, propagatedMemberTypes)); diff --git a/test/Mono.Linker.Tests.Cases/DataFlow/TypeBaseTypeDataFlow.cs b/test/Mono.Linker.Tests.Cases/DataFlow/TypeBaseTypeDataFlow.cs index abe5aaadadc1..68d232252d9a 100644 --- a/test/Mono.Linker.Tests.Cases/DataFlow/TypeBaseTypeDataFlow.cs +++ b/test/Mono.Linker.Tests.Cases/DataFlow/TypeBaseTypeDataFlow.cs @@ -34,6 +34,8 @@ public static void Main () TestNonPublicNestedTypesAreNotPropagated (typeof (TestType)); TestNonPublicPropertiesAreNotPropagated (typeof (TestType)); + TestInterfacesPropagated (typeof (TestType)); + TestCombinationOfPublicsIsPropagated (typeof (TestType)); TestCombinationOfNonPublicsIsNotPropagated (typeof (TestType)); TestCombinationOfPublicAndNonPublicsPropagatesPublicOnly (typeof (TestType)); @@ -164,6 +166,12 @@ static void TestNonPublicPropertiesAreNotPropagated ([DynamicallyAccessedMembers derivedType.BaseType.RequiresNonPublicProperties (); } + [RecognizedReflectionAccessPattern] + static void TestInterfacesPropagated ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.Interfaces)] Type derivedType) + { + derivedType.BaseType.RequiresInterfaces (); + } + [RecognizedReflectionAccessPattern] static void TestCombinationOfPublicsIsPropagated ( [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.PublicProperties)] Type derivedType) diff --git a/test/Mono.Linker.Tests.Cases/Reflection/TypeUsedViaReflection.cs b/test/Mono.Linker.Tests.Cases/Reflection/TypeUsedViaReflection.cs index 1907cd6536a6..8bfe08da3845 100644 --- a/test/Mono.Linker.Tests.Cases/Reflection/TypeUsedViaReflection.cs +++ b/test/Mono.Linker.Tests.Cases/Reflection/TypeUsedViaReflection.cs @@ -42,6 +42,8 @@ public static void Main () TestUnkownIgnoreCase3Params (1); TestUnkownIgnoreCase5Params (1); TestGenericTypeWithAnnotations (); + + BaseTypeInterfaces.Test (); } [Kept] @@ -409,5 +411,41 @@ static void TestGenericTypeWithAnnotations () " test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null"; Type.GetType (reflectionTypeKeptString); } + + [Kept] + class BaseTypeInterfaces + { + [Kept] + interface ITest + { + [Kept] + void Method (); + } + + [Kept] + [KeptInterface (typeof (ITest))] + class BaseType : ITest + { + [Kept] + public void Method () { } + } + + [Kept] + [KeptBaseType (typeof (BaseType))] + [KeptInterface (typeof (ITest))] + class DerivedType : BaseType, ITest + { + [Kept] + public void Method () { } + } + + [Kept] + public static void Test() + { + ITest t = null; + t.Method (); + typeof (DerivedType).GetInterfaces (); + } + } } } From b2c12f0b80b0dc8b191833a909e3e8a1e39519c6 Mon Sep 17 00:00:00 2001 From: vitek-karas <10670590+vitek-karas@users.noreply.github.com> Date: Mon, 3 Jan 2022 05:33:54 -0800 Subject: [PATCH 2/2] Formatting --- .../Mono.Linker.Tests.Cases/Reflection/TypeUsedViaReflection.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Mono.Linker.Tests.Cases/Reflection/TypeUsedViaReflection.cs b/test/Mono.Linker.Tests.Cases/Reflection/TypeUsedViaReflection.cs index 8bfe08da3845..0f660e6ede62 100644 --- a/test/Mono.Linker.Tests.Cases/Reflection/TypeUsedViaReflection.cs +++ b/test/Mono.Linker.Tests.Cases/Reflection/TypeUsedViaReflection.cs @@ -440,7 +440,7 @@ public void Method () { } } [Kept] - public static void Test() + public static void Test () { ITest t = null; t.Method ();