diff options
author | Andrii Kurdiumov <kant2002@gmail.com> | 2021-06-03 17:37:55 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-06-03 17:37:55 +0300 |
commit | f39ba1a20374ac6af0f2a866a7381192d28b8c37 (patch) | |
tree | dcaf644126f86e6d0503a20f89c42927860357d9 | |
parent | 0f3ea71923fdc93800103ec4d8f59bbe15e2813b (diff) |
Handle different dynamic member access for multiple branches (#2076)
This case assume that all code branches should have same minimal dynamic access pattern
Was discovered as part of https://github.com/dotnet/runtimelab/issues/1187
Issue happens when 2 code blocks has diferent requirements for dynamic code access, and this produce MergePoint. This case was not handled.
-rw-r--r-- | src/linker/Linker.Dataflow/ReflectionMethodBodyScanner.cs | 18 | ||||
-rw-r--r-- | test/Mono.Linker.Tests.Cases/DataFlow/GetInterfaceDataFlow.cs | 11 |
2 files changed, 21 insertions, 8 deletions
diff --git a/src/linker/Linker.Dataflow/ReflectionMethodBodyScanner.cs b/src/linker/Linker.Dataflow/ReflectionMethodBodyScanner.cs index ecf07120d..9459ce1d7 100644 --- a/src/linker/Linker.Dataflow/ReflectionMethodBodyScanner.cs +++ b/src/linker/Linker.Dataflow/ReflectionMethodBodyScanner.cs @@ -1777,15 +1777,17 @@ namespace Mono.Linker.Dataflow } // Validate that the return value has the correct annotations as per the method return value annotations - if (returnValueDynamicallyAccessedMemberTypes != 0 && methodReturnValue != null) { - if (methodReturnValue is LeafValueWithDynamicallyAccessedMemberNode methodReturnValueWithMemberTypes) { - if (!methodReturnValueWithMemberTypes.DynamicallyAccessedMemberTypes.HasFlag (returnValueDynamicallyAccessedMemberTypes)) + if (returnValueDynamicallyAccessedMemberTypes != 0) { + foreach (var uniqueValue in methodReturnValue.UniqueValues ()) { + if (uniqueValue is LeafValueWithDynamicallyAccessedMemberNode methodReturnValueWithMemberTypes) { + if (!methodReturnValueWithMemberTypes.DynamicallyAccessedMemberTypes.HasFlag (returnValueDynamicallyAccessedMemberTypes)) + throw new InvalidOperationException ($"Internal linker error: processing of call from {callingMethodDefinition.GetDisplayName ()} to {calledMethod.GetDisplayName ()} returned value which is not correctly annotated with the expected dynamic member access kinds."); + } else if (uniqueValue is SystemTypeValue) { + // SystemTypeValue can fullfill any requirement, so it's always valid + // The requirements will be applied at the point where it's consumed (passed as a method parameter, set as field value, returned from the method) + } else { throw new InvalidOperationException ($"Internal linker error: processing of call from {callingMethodDefinition.GetDisplayName ()} to {calledMethod.GetDisplayName ()} returned value which is not correctly annotated with the expected dynamic member access kinds."); - } else if (methodReturnValue is SystemTypeValue) { - // SystemTypeValue can fullfill any requirement, so it's always valid - // The requirements will be applied at the point where it's consumed (passed as a method parameter, set as field value, returned from the method) - } else { - throw new InvalidOperationException ($"Internal linker error: processing of call from {callingMethodDefinition.GetDisplayName ()} to {calledMethod.GetDisplayName ()} returned value which is not correctly annotated with the expected dynamic member access kinds."); + } } } diff --git a/test/Mono.Linker.Tests.Cases/DataFlow/GetInterfaceDataFlow.cs b/test/Mono.Linker.Tests.Cases/DataFlow/GetInterfaceDataFlow.cs index 630fc3c14..4a9d8c39f 100644 --- a/test/Mono.Linker.Tests.Cases/DataFlow/GetInterfaceDataFlow.cs +++ b/test/Mono.Linker.Tests.Cases/DataFlow/GetInterfaceDataFlow.cs @@ -66,6 +66,16 @@ namespace Mono.Linker.Tests.Cases.DataFlow type.GetInterface ("ITestInterface").RequiresAll (); // Warns since only one of the values is guaranteed All } + [ExpectedWarning ("IL2075", nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.Interfaces))] + static void TestMergedValues (int p, [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)] Type typeWithAll) + { + Type type = new TestType ().GetType (); + if (p == 0) { + type = typeWithAll; + type.GetInterface ("ITestInterface").RequiresInterfaces (); + } + } + public static void Test () { TestNoAnnotation (typeof (TestType)); @@ -74,6 +84,7 @@ namespace Mono.Linker.Tests.Cases.DataFlow TestWithAll (typeof (TestType)); TestKnownType (); TestMultipleValues (0, typeof (TestType)); + TestMergedValues (0, typeof (TestType)); } } |