Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/linker.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVitek Karas <10670590+vitek-karas@users.noreply.github.com>2022-03-12 00:33:31 +0300
committerGitHub <noreply@github.com>2022-03-12 00:33:31 +0300
commit98c81d59e153a5bf4329470b9d0fbf6d58fdd6e8 (patch)
tree15d2a8541b0da2caf115d0b73dc66a8918efaa34
parent93eac59827cae579c0889e293b715cec93b48c62 (diff)
Share Type.Base intrinsic (#2681)
-rw-r--r--src/ILLink.RoslynAnalyzer/TrimAnalysis/HandleCallAction.cs11
-rw-r--r--src/ILLink.Shared/TrimAnalysis/HandleCallAction.cs51
-rw-r--r--src/linker/Linker.Dataflow/HandleCallAction.cs11
-rw-r--r--src/linker/Linker.Dataflow/ReflectionMethodBodyScanner.cs52
-rw-r--r--test/ILLink.RoslynAnalyzer.Tests/DataFlowTests.cs3
-rw-r--r--test/ILLink.RoslynAnalyzer.Tests/ReflectionTests.cs6
-rw-r--r--test/ILLink.RoslynAnalyzer.Tests/generated/ILLink.RoslynAnalyzer.Tests.Generator/ILLink.RoslynAnalyzer.Tests.TestCaseGenerator/ReflectionTests.g.cs6
-rw-r--r--test/Mono.Linker.Tests.Cases/DataFlow/TypeBaseTypeDataFlow.cs6
8 files changed, 87 insertions, 59 deletions
diff --git a/src/ILLink.RoslynAnalyzer/TrimAnalysis/HandleCallAction.cs b/src/ILLink.RoslynAnalyzer/TrimAnalysis/HandleCallAction.cs
index 6e743f9b7..f05a5d3e1 100644
--- a/src/ILLink.RoslynAnalyzer/TrimAnalysis/HandleCallAction.cs
+++ b/src/ILLink.RoslynAnalyzer/TrimAnalysis/HandleCallAction.cs
@@ -62,6 +62,17 @@ namespace ILLink.Shared.TrimAnalysis
yield return new SystemTypeValue (new TypeProxy (nestedType));
}
+ private partial bool TryGetBaseType (TypeProxy type, out TypeProxy? baseType)
+ {
+ if (type.Type.BaseType is not null) {
+ baseType = new TypeProxy (type.Type.BaseType);
+ return true;
+ }
+
+ baseType = null;
+ return false;
+ }
+
// TODO: Does the analyzer need to do something here?
private partial void MarkStaticConstructor (TypeProxy type) { }
diff --git a/src/ILLink.Shared/TrimAnalysis/HandleCallAction.cs b/src/ILLink.Shared/TrimAnalysis/HandleCallAction.cs
index 002c213b9..c20e3b6f0 100644
--- a/src/ILLink.Shared/TrimAnalysis/HandleCallAction.cs
+++ b/src/ILLink.Shared/TrimAnalysis/HandleCallAction.cs
@@ -540,6 +540,55 @@ namespace ILLink.Shared.TrimAnalysis
}
break;
+ //
+ // Type.BaseType
+ //
+ case IntrinsicId.Type_get_BaseType: {
+ foreach (var value in instanceValue) {
+ if (value is ValueWithDynamicallyAccessedMembers valueWithDynamicallyAccessedMembers) {
+ DynamicallyAccessedMemberTypes propagatedMemberTypes = DynamicallyAccessedMemberTypes.None;
+ if (valueWithDynamicallyAccessedMembers.DynamicallyAccessedMemberTypes == DynamicallyAccessedMemberTypes.All)
+ propagatedMemberTypes = DynamicallyAccessedMemberTypes.All;
+ else {
+ // PublicConstructors are not propagated to base type
+
+ if (valueWithDynamicallyAccessedMembers.DynamicallyAccessedMemberTypes.HasFlag (DynamicallyAccessedMemberTypes.PublicEvents))
+ propagatedMemberTypes |= DynamicallyAccessedMemberTypes.PublicEvents;
+
+ if (valueWithDynamicallyAccessedMembers.DynamicallyAccessedMemberTypes.HasFlag (DynamicallyAccessedMemberTypes.PublicFields))
+ propagatedMemberTypes |= DynamicallyAccessedMemberTypes.PublicFields;
+
+ if (valueWithDynamicallyAccessedMembers.DynamicallyAccessedMemberTypes.HasFlag (DynamicallyAccessedMemberTypes.PublicMethods))
+ propagatedMemberTypes |= DynamicallyAccessedMemberTypes.PublicMethods;
+
+ // PublicNestedTypes are not propagated to base type
+
+ // PublicParameterlessConstructor is not propagated to base type
+
+ if (valueWithDynamicallyAccessedMembers.DynamicallyAccessedMemberTypes.HasFlag (DynamicallyAccessedMemberTypes.PublicProperties))
+ propagatedMemberTypes |= DynamicallyAccessedMemberTypes.PublicProperties;
+
+ if (valueWithDynamicallyAccessedMembers.DynamicallyAccessedMemberTypes.HasFlag (DynamicallyAccessedMemberTypes.Interfaces))
+ propagatedMemberTypes |= DynamicallyAccessedMemberTypes.Interfaces;
+ }
+
+ AddReturnValue (GetMethodReturnValue (calledMethod, propagatedMemberTypes));
+ } else if (value is SystemTypeValue systemTypeValue) {
+ if (TryGetBaseType (systemTypeValue.RepresentedType, out var baseType))
+ AddReturnValue (new SystemTypeValue (baseType.Value));
+ else
+ AddReturnValue (GetMethodReturnValue (calledMethod, returnValueDynamicallyAccessedMemberTypes));
+ } else if (value == NullValue.Instance) {
+ // Ignore nulls - null.BaseType will fail at runtime, but it has no effect on static analysis
+ continue;
+ } else {
+ // Unknown input - propagate a return value without any annotation - we know it's a Type but we know nothing about it
+ AddReturnValue (GetMethodReturnValue (calledMethod, returnValueDynamicallyAccessedMemberTypes));
+ }
+ }
+ }
+ break;
+
case IntrinsicId.None:
methodReturnValue = MultiValueLattice.Top;
return false;
@@ -686,6 +735,8 @@ namespace ILLink.Shared.TrimAnalysis
private partial IEnumerable<SystemTypeValue> GetNestedTypesOnType (TypeProxy type, string name, BindingFlags? bindingFlags);
+ private partial bool TryGetBaseType (TypeProxy type, [NotNullWhen (true)] out TypeProxy? baseType);
+
private partial void MarkStaticConstructor (TypeProxy type);
private partial void MarkEventsOnTypeHierarchy (TypeProxy type, string name, BindingFlags? bindingFlags);
diff --git a/src/linker/Linker.Dataflow/HandleCallAction.cs b/src/linker/Linker.Dataflow/HandleCallAction.cs
index de8dcf8f2..00371df07 100644
--- a/src/linker/Linker.Dataflow/HandleCallAction.cs
+++ b/src/linker/Linker.Dataflow/HandleCallAction.cs
@@ -68,6 +68,17 @@ namespace ILLink.Shared.TrimAnalysis
yield return new SystemTypeValue (new TypeProxy (nestedType));
}
+ private partial bool TryGetBaseType (TypeProxy type, out TypeProxy? baseType)
+ {
+ if (type.Type.BaseType is TypeReference baseTypeRef && _context.TryResolve (baseTypeRef) is TypeDefinition baseTypeDefinition) {
+ baseType = new TypeProxy (baseTypeDefinition);
+ return true;
+ }
+
+ baseType = null;
+ return false;
+ }
+
private partial void MarkStaticConstructor (TypeProxy type)
=> _reflectionMethodBodyScanner.MarkStaticConstructor (_analysisContext, type.Type);
diff --git a/src/linker/Linker.Dataflow/ReflectionMethodBodyScanner.cs b/src/linker/Linker.Dataflow/ReflectionMethodBodyScanner.cs
index 61325ae6b..8531974cc 100644
--- a/src/linker/Linker.Dataflow/ReflectionMethodBodyScanner.cs
+++ b/src/linker/Linker.Dataflow/ReflectionMethodBodyScanner.cs
@@ -289,7 +289,8 @@ namespace Mono.Linker.Dataflow
case IntrinsicId.Type_GetMethod:
case IntrinsicId.Type_GetNestedType:
case IntrinsicId.Expression_Property when calledMethod.HasParameterOfType (1, "System.Reflection.MethodInfo"):
- case var fieldOrPropertyInstrinsic when fieldOrPropertyInstrinsic == IntrinsicId.Expression_Field || fieldOrPropertyInstrinsic == IntrinsicId.Expression_Property: {
+ case var fieldOrPropertyInstrinsic when fieldOrPropertyInstrinsic == IntrinsicId.Expression_Field || fieldOrPropertyInstrinsic == IntrinsicId.Expression_Property:
+ case IntrinsicId.Type_get_BaseType: {
var instanceValue = MultiValueLattice.Top;
IReadOnlyList<MultiValue> parameterValues = methodParams;
if (calledMethodDefinition.HasImplicitThis ()) {
@@ -577,55 +578,6 @@ namespace Mono.Linker.Dataflow
break;
//
- // Type.BaseType
- //
- case IntrinsicId.Type_get_BaseType: {
- foreach (var value in methodParams[0]) {
- if (value is ValueWithDynamicallyAccessedMembers valueWithDynamicallyAccessedMembers) {
- DynamicallyAccessedMemberTypes propagatedMemberTypes = DynamicallyAccessedMemberTypes.None;
- if (valueWithDynamicallyAccessedMembers.DynamicallyAccessedMemberTypes == DynamicallyAccessedMemberTypes.All)
- propagatedMemberTypes = DynamicallyAccessedMemberTypes.All;
- else {
- // PublicConstructors are not propagated to base type
-
- if (valueWithDynamicallyAccessedMembers.DynamicallyAccessedMemberTypes.HasFlag (DynamicallyAccessedMemberTypes.PublicEvents))
- propagatedMemberTypes |= DynamicallyAccessedMemberTypes.PublicEvents;
-
- if (valueWithDynamicallyAccessedMembers.DynamicallyAccessedMemberTypes.HasFlag (DynamicallyAccessedMemberTypes.PublicFields))
- propagatedMemberTypes |= DynamicallyAccessedMemberTypes.PublicFields;
-
- if (valueWithDynamicallyAccessedMembers.DynamicallyAccessedMemberTypes.HasFlag (DynamicallyAccessedMemberTypes.PublicMethods))
- propagatedMemberTypes |= DynamicallyAccessedMemberTypes.PublicMethods;
-
- // PublicNestedTypes are not propagated to base type
-
- // PublicParameterlessConstructor is not propagated to base type
-
- if (valueWithDynamicallyAccessedMembers.DynamicallyAccessedMemberTypes.HasFlag (DynamicallyAccessedMemberTypes.PublicProperties))
- propagatedMemberTypes |= DynamicallyAccessedMemberTypes.PublicProperties;
-
- if (valueWithDynamicallyAccessedMembers.DynamicallyAccessedMemberTypes.HasFlag (DynamicallyAccessedMemberTypes.Interfaces))
- propagatedMemberTypes |= DynamicallyAccessedMemberTypes.Interfaces;
- }
-
- methodReturnValue = MultiValueLattice.Meet (methodReturnValue, GetMethodReturnValue (calledMethodDefinition, propagatedMemberTypes));
- } else if (value is SystemTypeValue systemTypeValue) {
- if (systemTypeValue.RepresentedType.Type.BaseType is TypeReference baseTypeRef && _context.TryResolve (baseTypeRef) is TypeDefinition baseTypeDefinition)
- methodReturnValue = MultiValueLattice.Meet (methodReturnValue, new SystemTypeValue (baseTypeDefinition));
- else
- methodReturnValue = MultiValueLattice.Meet (methodReturnValue, GetMethodReturnValue (calledMethodDefinition));
- } else if (value == NullValue.Instance) {
- // Ignore nulls - null.BaseType will fail at runtime, but it has no effect on static analysis
- continue;
- } else {
- // Unknown input - propagate a return value without any annotation - we know it's a Type but we know nothing about it
- methodReturnValue = MultiValueLattice.Meet (methodReturnValue, GetMethodReturnValue (calledMethodDefinition));
- }
- }
- }
- break;
-
- //
// System.Activator
//
// static CreateInstance (System.Type type)
diff --git a/test/ILLink.RoslynAnalyzer.Tests/DataFlowTests.cs b/test/ILLink.RoslynAnalyzer.Tests/DataFlowTests.cs
index 955d7ba04..8ada1cff3 100644
--- a/test/ILLink.RoslynAnalyzer.Tests/DataFlowTests.cs
+++ b/test/ILLink.RoslynAnalyzer.Tests/DataFlowTests.cs
@@ -201,8 +201,7 @@ namespace ILLink.RoslynAnalyzer.Tests
[Fact]
public Task TypeBaseTypeDataFlow ()
{
- // https://github.com/dotnet/linker/issues/2273
- return RunTest (allowMissingWarnings: true);
+ return RunTest ();
}
[Fact]
diff --git a/test/ILLink.RoslynAnalyzer.Tests/ReflectionTests.cs b/test/ILLink.RoslynAnalyzer.Tests/ReflectionTests.cs
index 0e12517ab..395ec25c8 100644
--- a/test/ILLink.RoslynAnalyzer.Tests/ReflectionTests.cs
+++ b/test/ILLink.RoslynAnalyzer.Tests/ReflectionTests.cs
@@ -164,6 +164,12 @@ namespace ILLink.RoslynAnalyzer.Tests
}
[Fact]
+ public Task TypeBaseTypeUseViaReflection ()
+ {
+ return RunTest ();
+ }
+
+ [Fact]
public Task TypeHierarchyReflectionWarnings ()
{
// https://github.com/dotnet/linker/issues/2578
diff --git a/test/ILLink.RoslynAnalyzer.Tests/generated/ILLink.RoslynAnalyzer.Tests.Generator/ILLink.RoslynAnalyzer.Tests.TestCaseGenerator/ReflectionTests.g.cs b/test/ILLink.RoslynAnalyzer.Tests/generated/ILLink.RoslynAnalyzer.Tests.Generator/ILLink.RoslynAnalyzer.Tests.TestCaseGenerator/ReflectionTests.g.cs
index 6e1bf553d..353ac8968 100644
--- a/test/ILLink.RoslynAnalyzer.Tests/generated/ILLink.RoslynAnalyzer.Tests.Generator/ILLink.RoslynAnalyzer.Tests.TestCaseGenerator/ReflectionTests.g.cs
+++ b/test/ILLink.RoslynAnalyzer.Tests/generated/ILLink.RoslynAnalyzer.Tests.Generator/ILLink.RoslynAnalyzer.Tests.TestCaseGenerator/ReflectionTests.g.cs
@@ -62,12 +62,6 @@ namespace ILLink.RoslynAnalyzer.Tests
}
[Fact]
- public Task TypeBaseTypeUseViaReflection ()
- {
- return RunTest (allowMissingWarnings: true);
- }
-
- [Fact]
public Task TypeDelegator ()
{
return RunTest (allowMissingWarnings: true);
diff --git a/test/Mono.Linker.Tests.Cases/DataFlow/TypeBaseTypeDataFlow.cs b/test/Mono.Linker.Tests.Cases/DataFlow/TypeBaseTypeDataFlow.cs
index f1cfccc3a..646994d11 100644
--- a/test/Mono.Linker.Tests.Cases/DataFlow/TypeBaseTypeDataFlow.cs
+++ b/test/Mono.Linker.Tests.Cases/DataFlow/TypeBaseTypeDataFlow.cs
@@ -67,7 +67,11 @@ namespace Mono.Linker.Tests.Cases.DataFlow
derivedType.BaseType.RequiresAll ();
}
- [ExpectedWarning ("IL2062", nameof (TestAllPropagated))]
+ // This is a very special case - normally there's basically no way to "new up" a Type instance via the "new" operator
+ // so the analyzer doesn't handle this case at all - meaning it sees it as empty value.
+ // Unlike linker which sees an unknown value and thus warns that it doesn't fulfill the All annotation.
+ // It's OK for the analyzer to be more forgiving in this case, due to the very special circumstances.
+ [ExpectedWarning ("IL2062", nameof (TestAllPropagated), ProducedBy = ProducedBy.Trimmer)]
public static void Test ()
{
TestAllPropagated (new TestSystemTypeBase ());