Skip to content

Commit

Permalink
Make ImplementsInterfaceOfSelf more precise for canonical subtypes (d…
Browse files Browse the repository at this point in the history
  • Loading branch information
jkotas authored Aug 4, 2023
1 parent d19a146 commit 9c06438
Showing 1 changed file with 26 additions and 27 deletions.
53 changes: 26 additions & 27 deletions src/coreclr/tools/Common/TypeSystem/IL/Stubs/ComparerIntrinsics.cs
Original file line number Diff line number Diff line change
Expand Up @@ -146,9 +146,8 @@ private static TypeDesc[] GetPotentialComparersForTypeCommon(TypeDesc type, stri
universalComparers.Add(context.SystemModule.GetKnownType("System.Collections.Generic", $"Nullable{flavor}`1")
.MakeInstantiatedType(type));

if (flavor == "EqualityComparer")
universalComparers.Add(context.SystemModule.GetKnownType("System.Collections.Generic", $"Enum{flavor}`1")
.MakeInstantiatedType(type));
universalComparers.Add(context.SystemModule.GetKnownType("System.Collections.Generic", $"Enum{flavor}`1")
.MakeInstantiatedType(type));

universalComparers.Add(context.SystemModule.GetKnownType("System.Collections.Generic", $"Generic{flavor}`1")
.MakeInstantiatedType(type));
Expand All @@ -167,7 +166,7 @@ private static TypeDesc[] GetPotentialComparersForTypeCommon(TypeDesc type, stri
{
TypeDesc nullableType = type.Instantiation[0];

// This should only be reachabe for universal canon code.
// This should only be reachable for universal canon code.
// For specific canon, this should have been an exact match above.
Debug.Assert(context.IsCanonicalDefinitionType(nullableType, CanonicalFormKind.Universal));

Expand Down Expand Up @@ -195,15 +194,7 @@ private static TypeDesc[] GetPotentialComparersForTypeCommon(TypeDesc type, stri
private static bool? ImplementsInterfaceOfSelf(TypeDesc type, string interfaceName)
{
MetadataType interfaceType = null;
bool canonicalSubtype = false;

if (type.IsCanonicalSubtype(CanonicalFormKind.Any))
{
type = type.GetTypeDefinition();
canonicalSubtype = true;
}

bool candidateFound = false;
foreach (TypeDesc implementedInterface in type.RuntimeInterfaces)
{
Instantiation interfaceInstantiation = implementedInterface.Instantiation;
Expand All @@ -213,25 +204,33 @@ private static TypeDesc[] GetPotentialComparersForTypeCommon(TypeDesc type, stri

if (implementedInterface.GetTypeDefinition() == interfaceType)
{
// Exact match
if (interfaceInstantiation[0] == type)
return true;

candidateFound = true;
break;
if (type.IsCanonicalSubtype(CanonicalFormKind.Any))
{
// Ignore interface instantiations that cannot possibly be the interface of self
if (implementedInterface.ConvertToCanonForm(CanonicalFormKind.Specific) !=
interfaceType.MakeInstantiatedType(type).ConvertToCanonForm(CanonicalFormKind.Specific))
{
continue;
}
// Try to prove that the interface of self is always implemented using the type definition.
TypeDesc typeDefinition = type.GetTypeDefinition();
return typeDefinition.CanCastTo(interfaceType.MakeInstantiatedType(typeDefinition)) ? true : null;
}
else
{
// Shortcut for exact match
if (interfaceInstantiation[0] == type)
{
Debug.Assert(type.CanCastTo(interfaceType.MakeInstantiatedType(type)));
return true;
}
return type.CanCastTo(interfaceType.MakeInstantiatedType(type));
}
}
}
}

if (!candidateFound)
return false;

// Try inexact match
if (type.CanCastTo(interfaceType.MakeInstantiatedType(type)))
return true;

// Specific instantiation of the canonical subtype may implement the interface.
return canonicalSubtype ? null : false;
return false;
}

public static bool CanCompareValueTypeBits(MetadataType type, MethodDesc objectEqualsMethod)
Expand Down

0 comments on commit 9c06438

Please sign in to comment.