Skip to content

Commit

Permalink
Extend RunClassConstructor intrinsic handling to accept NonPublicCons…
Browse files Browse the repository at this point in the history
…tructors (#103947)

This should not generate a warning since the static constructor will be kept.
  • Loading branch information
MichalStrehovsky committed Jun 26, 2024
1 parent d6581f8 commit eb29166
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -266,8 +266,6 @@ public static void PrepareDelegate(Delegate d)
{
}

[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2059:UnrecognizedReflectionPattern",
Justification = "We keep class constructors of all types with an MethodTable")]
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2072:UnrecognizedReflectionPattern",
Justification = "Constructed MethodTable of a Nullable forces a constructed MethodTable of the element type")]
public static unsafe object GetUninitializedObject(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,8 @@ RuntimeTypeHandleValue typeHandle
=> new SystemTypeValue (typeHandle.RepresentedType),
RuntimeTypeHandleForGenericParameterValue genericParam
=> _annotations.GetGenericParameterValue (genericParam.GenericParameter),
RuntimeTypeHandleForValueWithDynamicallyAccessedMembers valueWithDynamicallyAccessedMembers
=> valueWithDynamicallyAccessedMembers.UnderlyingTypeValue,
_ => annotatedMethodReturnValue
});
}
Expand All @@ -157,6 +159,8 @@ SystemTypeValue typeHandle
=> new RuntimeTypeHandleValue (typeHandle.RepresentedType),
GenericParameterValue genericParam
=> new RuntimeTypeHandleForGenericParameterValue (genericParam.GenericParameter),
ValueWithDynamicallyAccessedMembers valueWithDynamicallyAccessedMembers
=> new RuntimeTypeHandleForValueWithDynamicallyAccessedMembers(valueWithDynamicallyAccessedMembers),
_ => annotatedMethodReturnValue
});
else
Expand Down Expand Up @@ -286,6 +290,9 @@ GenericParameterValue genericParam
foreach (var typeHandleValue in argumentValues[0].AsEnumerable ()) {
if (typeHandleValue is RuntimeTypeHandleValue runtimeTypeHandleValue) {
MarkStaticConstructor (runtimeTypeHandleValue.RepresentedType);
} else if (typeHandleValue is RuntimeTypeHandleForValueWithDynamicallyAccessedMembers damAnnotatedHandle
&& (damAnnotatedHandle.UnderlyingTypeValue.DynamicallyAccessedMemberTypes & DynamicallyAccessedMemberTypes.NonPublicConstructors) != 0) {
// No action needed, NonPublicConstructors keeps the static constructor on the type
} else {
_diagnosticContext.AddDiagnostic (DiagnosticId.UnrecognizedTypeInRuntimeHelpersRunClassConstructor, calledMethod.GetDisplayName ());
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System.Diagnostics;
using ILLink.Shared.DataFlow;
using ILLink.Shared.TypeSystemProxy;

// This is needed due to NativeAOT which doesn't enable nullable globally yet
#nullable enable

namespace ILLink.Shared.TrimAnalysis
{
/// <summary>
/// This represents a type handle obtained from a Type with DynamicallyAccessedMembers annotations.
/// </summary>
internal sealed record RuntimeTypeHandleForValueWithDynamicallyAccessedMembers : SingleValue
{
public RuntimeTypeHandleForValueWithDynamicallyAccessedMembers (in ValueWithDynamicallyAccessedMembers underlyingTypeValue)
{
UnderlyingTypeValue = underlyingTypeValue;
}

public readonly ValueWithDynamicallyAccessedMembers UnderlyingTypeValue;

public override SingleValue DeepCopy () => this; // This value is immutable

public override string ToString () => this.ValueToString (UnderlyingTypeValue);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public static void Main ()
TestTypeOfFromGeneric<TestType> ();
TestGetTypeHandle ();
TestGetTypeHandleFromGeneric<TestType> ();
TestUnsupportedPatterns (typeof (TestType));
TestFlowThroughGetTypeHandleGetTypeFromHandle (typeof (TestType));
TestNull ();
TestNoValue ();
}
Expand Down Expand Up @@ -58,8 +58,7 @@ static void TestGetTypeHandle ()
Type.GetTypeFromHandle (typeof (T).TypeHandle).RequiresPublicFields ();
}

[ExpectedWarning ("IL2072", nameof (Type.GetTypeFromHandle), nameof (DataFlowTypeExtensions.RequiresPublicMethods))]
static void TestUnsupportedPatterns ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] Type typeWithMethods)
static void TestFlowThroughGetTypeHandleGetTypeFromHandle ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] Type typeWithMethods)
{
Type.GetTypeFromHandle (typeWithMethods.TypeHandle).RequiresPublicMethods ();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
using Mono.Linker.Tests.Cases.Expectations.Assertions;
using Mono.Linker.Tests.Cases.Expectations.Metadata;
Expand All @@ -16,6 +17,8 @@ public static void Main ()
TestNull ();
TestNoValue ();
TestDataFlowType ();
TestNonPublicConstructorDataFlowType ();
TestPublicConstructorDataFlowType ();
TestIfElseUsingRuntimeTypeHandle (1);
TestIfElseUsingType (1);
}
Expand Down Expand Up @@ -62,6 +65,37 @@ static void TestDataFlowType ()
RuntimeHelpers.RunClassConstructor (type.TypeHandle);
}

[Kept]
[return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.NonPublicConstructors)]
[return: KeptAttributeAttribute (typeof (DynamicallyAccessedMembersAttribute))]
static Type FindTypeWithNonPublicConstructors ()
{
return null;
}

[Kept]
static void TestNonPublicConstructorDataFlowType ()
{
Type type = FindTypeWithNonPublicConstructors ();
RuntimeHelpers.RunClassConstructor (type.TypeHandle);
}

[Kept]
[return: KeptAttributeAttribute(typeof (DynamicallyAccessedMembersAttribute))]
[return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicConstructors)]
static Type FindTypeWithPublicConstructors ()
{
return null;
}

[Kept]
[ExpectedWarning ("IL2059", nameof (RuntimeHelpers) + "." + nameof (RuntimeHelpers.RunClassConstructor))]
static void TestPublicConstructorDataFlowType ()
{
Type type = FindTypeWithPublicConstructors ();
RuntimeHelpers.RunClassConstructor (type.TypeHandle);
}

[Kept]
[ExpectedWarning ("IL2059", nameof (RuntimeHelpers) + "." + nameof (RuntimeHelpers.RunClassConstructor))]
static void TestIfElseUsingRuntimeTypeHandle (int i)
Expand Down Expand Up @@ -147,4 +181,4 @@ public ElseClass2 (int foo)
{ }
}
}
}
}

0 comments on commit eb29166

Please sign in to comment.