Skip to content

Commit

Permalink
Do not warn when accessing fields on T constrained to be enum (#100814)
Browse files Browse the repository at this point in the history
Fixes #97737.

Trimming ensures we keep all the public fields on enums. `typeof(T).GetFields()` is safe when the `T` is constrained to be `System.Enum` or a derived type.
  • Loading branch information
MichalStrehovsky authored Apr 9, 2024
1 parent 129c6a7 commit 3462976
Show file tree
Hide file tree
Showing 6 changed files with 46 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,17 @@ internal readonly partial struct GenericParameterProxy

internal partial bool HasDefaultConstructorConstraint() => GenericParameter.HasDefaultConstructorConstraint;

internal partial bool HasEnumConstraint()
{
foreach (TypeDesc constraint in GenericParameter.TypeConstraints)
{
if (constraint.IsWellKnownType(Internal.TypeSystem.WellKnownType.Enum))
return true;
}

return false;
}

public readonly GenericParameterDesc GenericParameter;

public override string ToString() => GenericParameter.ToString();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,16 @@ internal partial bool HasDefaultConstructorConstraint () =>
TypeParameterSymbol.HasValueTypeConstraint |
TypeParameterSymbol.HasUnmanagedTypeConstraint;

internal partial bool HasEnumConstraint ()
{
foreach (ITypeSymbol constraintType in TypeParameterSymbol.ConstraintTypes) {
if (constraintType.SpecialType == SpecialType.System_Enum)
return true;
}

return false;
}

public readonly ITypeParameterSymbol TypeParameterSymbol;

public override string ToString () => TypeParameterSymbol.ToString ();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ public void Invoke (in MultiValue value, ValueWithDynamicallyAccessedMembers tar
&& uniqueValue is GenericParameterValue genericParam
&& genericParam.GenericParameter.HasDefaultConstructorConstraint ()) {
// We allow a new() constraint on a generic parameter to satisfy DynamicallyAccessedMemberTypes.PublicParameterlessConstructor
} else if (targetValue.DynamicallyAccessedMemberTypes == DynamicallyAccessedMemberTypes.PublicFields
&& uniqueValue is GenericParameterValue maybeEnumConstrainedGenericParam
&& maybeEnumConstrainedGenericParam.GenericParameter.HasEnumConstraint ()) {
// We allow a System.Enum constraint on a generic parameter to satisfy DynamicallyAccessedMemberTypes.PublicFields
} else if (uniqueValue is ValueWithDynamicallyAccessedMembers valueWithDynamicallyAccessedMembers) {
if (uniqueValue is NullableValueWithDynamicallyAccessedMembers nullableValue) {
MarkTypeForDynamicallyAccessedMembers (nullableValue.NullableType, nullableValue.DynamicallyAccessedMemberTypes);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,7 @@ namespace ILLink.Shared.TypeSystemProxy
internal readonly partial struct GenericParameterProxy
{
internal partial bool HasDefaultConstructorConstraint ();

internal partial bool HasEnumConstraint ();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,18 @@ internal readonly partial struct GenericParameterProxy

internal partial bool HasDefaultConstructorConstraint () => GenericParameter.HasDefaultConstructorConstraint;

internal partial bool HasEnumConstraint ()
{
if (GenericParameter.HasConstraints) {
foreach (GenericParameterConstraint? constraint in GenericParameter.Constraints) {
if (constraint.ConstraintType.Name == "Enum" && constraint.ConstraintType.Namespace == "System")
return true;
}
}

return false;
}

public readonly GenericParameter GenericParameter;

public override string ToString () => GenericParameter.ToString ();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ public static void Main ()
TestStructConstraintSatisfiesParameterlessConstructor<TestStruct> ();
TestUnmanagedConstraintSatisfiesParameterlessConstructor<byte> ();

TestEnumConstraintSatisfiesPublicFields<Enum> ();

TestGenericParameterFlowsToField ();
TestGenericParameterFlowsToReturnValue ();

Expand Down Expand Up @@ -798,6 +800,11 @@ static void TestUnmanagedConstraintSatisfiesParameterlessConstructor<T> () where
{
}

static void TestEnumConstraintSatisfiesPublicFields<T> () where T : Enum
{
typeof (T).RequiresPublicFields ();
}

// Warn about calls to static methods:
[ExpectedWarning ("IL2026", "TypeRequiresPublicFields", "RUCTest()", "message")]
[ExpectedWarning ("IL2026", "RUCMethodRequiresPublicMethods", "message")]
Expand Down

0 comments on commit 3462976

Please sign in to comment.