Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Covariant returns for RuntimeType #45355

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ protected virtual MethodInfo GetMethodImpl()
// we get from the method is probably shared and those in the hierarchy we're
// walking won't be we compare using the generic type definition forms instead.
Type? currentType = _target!.GetType();
Type targetType = declaringType.GetGenericTypeDefinition();
RuntimeType targetType = declaringType.GetGenericTypeDefinition();
while (currentType != null)
{
if (currentType.IsGenericType &&
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -391,9 +391,9 @@ internal static IntroducedMethodEnumerator GetIntroducedMethods(RuntimeType type
[DllImport(RuntimeHelpers.QCall, CharSet = CharSet.Unicode)]
private static extern void GetConstraints(QCallTypeHandle handle, ObjectHandleOnStack types);

internal Type[] GetConstraints()
internal RuntimeType[] GetConstraints()
{
Type[]? types = null;
RuntimeType[]? types = null;
RuntimeTypeHandle nativeHandle = GetNativeHandle();

GetConstraints(new QCallTypeHandle(ref nativeHandle), ObjectHandleOnStack.Create(ref types));
Expand Down Expand Up @@ -550,9 +550,9 @@ internal RuntimeType[] GetInstantiationInternal()
return types!;
}

internal Type[] GetInstantiationPublic()
internal RuntimeType[] GetInstantiationPublic()
{
Type[]? types = null;
RuntimeType[]? types = null;
RuntimeTypeHandle nativeHandle = GetNativeHandle();
GetInstantiation(new QCallTypeHandle(ref nativeHandle), ObjectHandleOnStack.Create(ref types), Interop.BOOL.FALSE);
return types!;
Expand Down

Large diffs are not rendered by default.

31 changes: 17 additions & 14 deletions src/coreclr/src/vm/appdomain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1448,13 +1448,27 @@ void SystemDomain::LoadBaseSystemClasses()
g_pEnumClass = CoreLibBinder::GetClass(CLASS__ENUM);
_ASSERTE(!g_pEnumClass->IsValueType());

// Load Array class
g_pArrayClass = CoreLibBinder::GetClass(CLASS__ARRAY);

// Load the Object array class.
g_pPredefinedArrayTypes[ELEMENT_TYPE_OBJECT] = ClassLoader::LoadArrayTypeThrowing(TypeHandle(g_pObjectClass));

// We have delayed allocation of CoreLib's static handles until we load the object class
CoreLibBinder::GetModule()->AllocateRegularStaticHandles(DefaultDomain());

// Make sure all primitive types are loaded
for (int et = ELEMENT_TYPE_VOID; et <= ELEMENT_TYPE_R8; et++)
CoreLibBinder::LoadPrimitiveType((CorElementType)et);

#ifndef CROSSGEN_COMPILE
CastCache::Initialize();
#endif // CROSSGEN_COMPILE

// Load System.RuntimeType
g_pRuntimeTypeClass = CoreLibBinder::GetClass(CLASS__CLASS);
_ASSERTE(g_pRuntimeTypeClass->IsFullyLoaded());

// Load Array class
g_pArrayClass = CoreLibBinder::GetClass(CLASS__ARRAY);

// Calling a method on IList<T> for an array requires redirection to a method on
// the SZArrayHelper class. Retrieving such methods means calling
// GetActualImplementationForArrayGenericIListMethod, which calls FetchMethod for
Expand All @@ -1472,16 +1486,6 @@ void SystemDomain::LoadBaseSystemClasses()
// Load Nullable class
g_pNullableClass = CoreLibBinder::GetClass(CLASS__NULLABLE);

// Load the Object array class.
g_pPredefinedArrayTypes[ELEMENT_TYPE_OBJECT] = ClassLoader::LoadArrayTypeThrowing(TypeHandle(g_pObjectClass));

// We have delayed allocation of CoreLib's static handles until we load the object class
CoreLibBinder::GetModule()->AllocateRegularStaticHandles(DefaultDomain());

// Make sure all primitive types are loaded
for (int et = ELEMENT_TYPE_VOID; et <= ELEMENT_TYPE_R8; et++)
CoreLibBinder::LoadPrimitiveType((CorElementType)et);

CoreLibBinder::LoadPrimitiveType(ELEMENT_TYPE_I);
CoreLibBinder::LoadPrimitiveType(ELEMENT_TYPE_U);

Expand All @@ -1503,7 +1507,6 @@ void SystemDomain::LoadBaseSystemClasses()
// further loading of nonprimitive types may need casting support.
// initialize cast cache here.
#ifndef CROSSGEN_COMPILE
CastCache::Initialize();
ECall::PopulateManagedCastHelpers();
#endif // CROSSGEN_COMPILE

Expand Down
37 changes: 33 additions & 4 deletions src/libraries/System.Private.CoreLib/src/System/DefaultBinder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -769,12 +769,12 @@ public sealed override void ReorderArgumentArray(ref object?[] args, object stat

// Return any exact bindings that may exist. (This method is not defined on the
// Binder and is used by RuntimeType.)
public static MethodBase? ExactBinding(MethodBase[] match, Type[] types, ParameterModifier[]? modifiers)
public static RuntimeConstructorInfo? ExactBinding(RuntimeConstructorInfo[] match, Type[] types, ParameterModifier[]? modifiers)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using RuntimeConstructorInfo will make sharing of this code problematic with NativeAOT.

DefaultBinder is a super slow path. An extra casts here won't make difference.

{
if (match == null)
throw new ArgumentNullException(nameof(match));

MethodBase[] aExactMatches = new MethodBase[match.Length];
RuntimeConstructorInfo[] aExactMatches = new RuntimeConstructorInfo[match.Length];
int cExactMatches = 0;

for (int i = 0; i < match.Length; i++)
Expand Down Expand Up @@ -1109,10 +1109,39 @@ private static int GetHierarchyDepth(Type t)
return depth;
}

internal static MethodBase? FindMostDerivedNewSlotMeth(MethodBase[] match, int cMatches)
internal static RuntimeMethodInfo? FindMostDerivedNewSlotMeth(RuntimeMethodInfo[] match, int cMatches)
{
int deepestHierarchy = 0;
MethodBase? methWithDeepestHierarchy = null;
RuntimeMethodInfo? methWithDeepestHierarchy = null;

for (int i = 0; i < cMatches; i++)
{
// Calculate the depth of the hierarchy of the declaring type of the
// current method.
int currentHierarchyDepth = GetHierarchyDepth(match[i].DeclaringType!);

// The two methods have the same name, signature, and hierarchy depth.
// This can only happen if at least one is vararg or generic.
if (currentHierarchyDepth == deepestHierarchy)
{
throw new AmbiguousMatchException(SR.Arg_AmbiguousMatchException);
}

// Check to see if this method is on the most derived class.
if (currentHierarchyDepth > deepestHierarchy)
{
deepestHierarchy = currentHierarchyDepth;
methWithDeepestHierarchy = match[i];
}
}

return methWithDeepestHierarchy;
}

internal static RuntimeConstructorInfo? FindMostDerivedNewSlotMeth(RuntimeConstructorInfo[] match, int cMatches)
{
int deepestHierarchy = 0;
RuntimeConstructorInfo? methWithDeepestHierarchy = null;

for (int i = 0; i < cMatches; i++)
{
Expand Down
23 changes: 12 additions & 11 deletions src/libraries/System.Private.CoreLib/src/System/RuntimeType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@ namespace System
{
internal sealed partial class RuntimeType : TypeInfo, ICloneable
{
public override Assembly Assembly => RuntimeTypeHandle.GetAssembly(this);
public override Type? BaseType => GetBaseType();
public static new readonly RuntimeType[] EmptyTypes = Array.Empty<RuntimeType>();
public override RuntimeAssembly Assembly => RuntimeTypeHandle.GetAssembly(this);
public override RuntimeType? BaseType => GetBaseType();
public override bool IsByRefLike => RuntimeTypeHandle.IsByRefLike(this);
public override bool IsConstructedGenericType => IsGenericType && !IsGenericTypeDefinition;
public override bool IsGenericType => RuntimeTypeHandle.HasInstantiation(this);
Expand All @@ -23,10 +24,10 @@ internal sealed partial class RuntimeType : TypeInfo, ICloneable
public override bool IsSecurityTransparent => false;
public override MemberTypes MemberType => (IsPublic || IsNotPublic) ? MemberTypes.TypeInfo : MemberTypes.NestedType;
public override int MetadataToken => RuntimeTypeHandle.GetToken(this);
public override Module Module => GetRuntimeModule();
public override Type? ReflectedType => DeclaringType;
public override RuntimeModule Module => GetRuntimeModule();
public override RuntimeType? ReflectedType => DeclaringType;
public override RuntimeTypeHandle TypeHandle => new RuntimeTypeHandle(this);
public override Type UnderlyingSystemType => this;
public override RuntimeType UnderlyingSystemType => this;

public object Clone() => this;

Expand Down Expand Up @@ -92,7 +93,7 @@ public override MemberInfo[] GetDefaultMembers()
return members ?? Array.Empty<MemberInfo>();
}

public override Type GetElementType() => RuntimeTypeHandle.GetElementType(this);
public override RuntimeType GetElementType() => RuntimeTypeHandle.GetElementType(this);

public override string? GetEnumName(object value)
{
Expand Down Expand Up @@ -140,15 +141,15 @@ public override Array GetEnumValues()
return ret;
}

public override Type GetEnumUnderlyingType()
public override RuntimeType GetEnumUnderlyingType()
{
if (!IsEnum)
throw new ArgumentException(SR.Arg_MustBeEnum, "enumType");

return Enum.InternalGetUnderlyingType(this);
}

public override Type GetGenericTypeDefinition()
public override RuntimeType GetGenericTypeDefinition()
{
if (!IsGenericType)
throw new InvalidOperationException(SR.InvalidOperation_NotGenericType);
Expand Down Expand Up @@ -268,7 +269,7 @@ public override bool IsEnumDefined(object value)
if (!valueType.IsEquivalentTo(this))
throw new ArgumentException(SR.Format(SR.Arg_EnumAndObjectMustBeSameType, valueType, this));

valueType = (RuntimeType)valueType.GetEnumUnderlyingType();
valueType = valueType.GetEnumUnderlyingType();
}

// If a string is passed in
Expand Down Expand Up @@ -374,13 +375,13 @@ public override bool IsAssignableFrom([NotNullWhen(true)] Type? c)

if (RuntimeTypeHandle.IsGenericVariable(this))
{
Type[] constraints = GetGenericParameterConstraints();
RuntimeType[] constraints = GetGenericParameterConstraints();

RuntimeType baseType = ObjectType;

for (int i = 0; i < constraints.Length; i++)
{
RuntimeType constraint = (RuntimeType)constraints[i];
RuntimeType constraint = constraints[i];

if (constraint.IsInterface)
continue;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,18 +96,18 @@ internal RuntimeGenericParamInfoHandle(IntPtr ptr)
this.value = (RuntimeStructs.GenericParamInfo*)ptr;
}

internal Type[] Constraints => GetConstraints();
internal RuntimeType[] Constraints => GetConstraints();

internal GenericParameterAttributes Attributes => (GenericParameterAttributes)value->flags;

private Type[] GetConstraints()
private RuntimeType[] GetConstraints()
{
int n = GetConstraintsCount();
var a = new Type[n];
var a = new RuntimeType[n];
for (int i = 0; i < n; i++)
{
RuntimeClassHandle c = new RuntimeClassHandle(value->constraints[i]);
a[i] = Type.GetTypeFromHandle(c.GetTypeHandle());
a[i] = RuntimeType.GetTypeFromHandle(c.GetTypeHandle());
}

return a;
Expand Down
Loading