From e19bcfd7a3af1f76273051bcc8dd1579be40446a Mon Sep 17 00:00:00 2001 From: Ben Adams Date: Sun, 29 Nov 2020 23:25:27 +0000 Subject: [PATCH 1/2] Covariant returns for RuntimeType --- .../src/System/Delegate.CoreCLR.cs | 2 +- .../src/System/RuntimeHandles.cs | 8 +- .../src/System/RuntimeType.CoreCLR.cs | 96 +++++++++---------- .../src/System/DefaultBinder.cs | 37 ++++++- .../src/System/RuntimeType.cs | 23 ++--- .../src/Mono/RuntimeHandles.cs | 8 +- .../src/System/RuntimeType.Mono.cs | 64 +++++++------ .../src/System/RuntimeTypeHandle.cs | 4 +- .../src/System/Type.Mono.cs | 2 +- 9 files changed, 141 insertions(+), 103 deletions(-) diff --git a/src/coreclr/src/System.Private.CoreLib/src/System/Delegate.CoreCLR.cs b/src/coreclr/src/System.Private.CoreLib/src/System/Delegate.CoreCLR.cs index ab338cd0bc9cdf..ddd47ef04146b0 100644 --- a/src/coreclr/src/System.Private.CoreLib/src/System/Delegate.CoreCLR.cs +++ b/src/coreclr/src/System.Private.CoreLib/src/System/Delegate.CoreCLR.cs @@ -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 && diff --git a/src/coreclr/src/System.Private.CoreLib/src/System/RuntimeHandles.cs b/src/coreclr/src/System.Private.CoreLib/src/System/RuntimeHandles.cs index fbca319a20c229..4ecfe182549d5b 100644 --- a/src/coreclr/src/System.Private.CoreLib/src/System/RuntimeHandles.cs +++ b/src/coreclr/src/System.Private.CoreLib/src/System/RuntimeHandles.cs @@ -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)); @@ -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!; diff --git a/src/coreclr/src/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs b/src/coreclr/src/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs index 6e2c218e31bfa0..7b9f8b5e06d021 100644 --- a/src/coreclr/src/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs +++ b/src/coreclr/src/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs @@ -1090,7 +1090,7 @@ private RuntimeType[] PopulateNestedClasses(Filter filter) // For example, TypeDescs do not have metadata tokens if (MdToken.IsNullToken(tkEnclosingType)) - return Array.Empty(); + return EmptyTypes; ListBuilder list = default; @@ -2456,7 +2456,7 @@ private RuntimeTypeCache InitializeCache() private const int GenericParameterCountAny = -1; - private ListBuilder GetMethodCandidates( + private ListBuilder GetMethodCandidates( string? name, int genericParameterCount, BindingFlags bindingAttr, CallingConventions callConv, Type[]? types, bool allowPrefixLookup) { @@ -2464,7 +2464,7 @@ private ListBuilder GetMethodCandidates( RuntimeMethodInfo[] cache = Cache.GetMethodList(listType, name); - ListBuilder candidates = new ListBuilder(cache.Length); + ListBuilder candidates = new ListBuilder(cache.Length); for (int i = 0; i < cache.Length; i++) { RuntimeMethodInfo methodInfo = cache[i]; @@ -2481,7 +2481,7 @@ private ListBuilder GetMethodCandidates( return candidates; } - private ListBuilder GetConstructorCandidates( + private ListBuilder GetConstructorCandidates( string? name, BindingFlags bindingAttr, CallingConventions callConv, Type[]? types, bool allowPrefixLookup) { @@ -2489,7 +2489,7 @@ private ListBuilder GetConstructorCandidates( RuntimeConstructorInfo[] cache = Cache.GetConstructorList(listType, name); - ListBuilder candidates = new ListBuilder(cache.Length); + ListBuilder candidates = new ListBuilder(cache.Length); for (int i = 0; i < cache.Length; i++) { RuntimeConstructorInfo constructorInfo = cache[i]; @@ -2549,7 +2549,7 @@ private ListBuilder GetEventCandidates(string? name, BindingFlags bin return candidates; } - private ListBuilder GetFieldCandidates(string? name, BindingFlags bindingAttr, bool allowPrefixLookup) + private ListBuilder GetFieldCandidates(string? name, BindingFlags bindingAttr, bool allowPrefixLookup) { FilterHelper(bindingAttr, ref name, allowPrefixLookup, out bool prefixLookup, out bool ignoreCase, out MemberListType listType); @@ -2557,7 +2557,7 @@ private ListBuilder GetFieldCandidates(string? name, BindingFlags bin bindingAttr ^= BindingFlags.DeclaredOnly; - ListBuilder candidates = new ListBuilder(cache.Length); + ListBuilder candidates = new ListBuilder(cache.Length); for (int i = 0; i < cache.Length; i++) { RuntimeFieldInfo fieldInfo = cache[i]; @@ -2571,7 +2571,7 @@ private ListBuilder GetFieldCandidates(string? name, BindingFlags bin return candidates; } - private ListBuilder GetNestedTypeCandidates(string? fullname, BindingFlags bindingAttr, bool allowPrefixLookup) + private ListBuilder GetNestedTypeCandidates(string? fullname, BindingFlags bindingAttr, bool allowPrefixLookup) { bindingAttr &= ~BindingFlags.Static; SplitName(fullname, out string? name, out string? ns); @@ -2579,7 +2579,7 @@ private ListBuilder GetNestedTypeCandidates(string? fullname, BindingFlags RuntimeType[] cache = Cache.GetNestedTypeList(listType, name); - ListBuilder candidates = new ListBuilder(cache.Length); + ListBuilder candidates = new ListBuilder(cache.Length); for (int i = 0; i < cache.Length; i++) { RuntimeType nestedClass = cache[i]; @@ -2619,19 +2619,19 @@ public override EventInfo[] GetEvents(BindingFlags bindingAttr) } [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.NonPublicFields)] - public override FieldInfo[] GetFields(BindingFlags bindingAttr) + public override RuntimeFieldInfo[] GetFields(BindingFlags bindingAttr) { return GetFieldCandidates(null, bindingAttr, false).ToArray(); } - public override Type[] GetInterfaces() + public override RuntimeType[] GetInterfaces() { RuntimeType[] candidates = Cache.GetInterfaceList(MemberListType.All, null); - return new ReadOnlySpan(candidates).ToArray(); + return new ReadOnlySpan(candidates).ToArray(); } [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicNestedTypes | DynamicallyAccessedMemberTypes.NonPublicNestedTypes)] - public override Type[] GetNestedTypes(BindingFlags bindingAttr) + public override RuntimeType[] GetNestedTypes(BindingFlags bindingAttr) { return GetNestedTypeCandidates(null, bindingAttr, false).ToArray(); } @@ -2639,12 +2639,12 @@ public override Type[] GetNestedTypes(BindingFlags bindingAttr) [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] public override MemberInfo[] GetMembers(BindingFlags bindingAttr) { - ListBuilder methods = GetMethodCandidates(null, GenericParameterCountAny, bindingAttr, CallingConventions.Any, null, false); - ListBuilder constructors = GetConstructorCandidates(null, bindingAttr, CallingConventions.Any, null, false); + ListBuilder methods = GetMethodCandidates(null, GenericParameterCountAny, bindingAttr, CallingConventions.Any, null, false); + ListBuilder constructors = GetConstructorCandidates(null, bindingAttr, CallingConventions.Any, null, false); ListBuilder properties = GetPropertyCandidates(null, bindingAttr, null, false); ListBuilder events = GetEventCandidates(null, bindingAttr, false); - ListBuilder fields = GetFieldCandidates(null, bindingAttr, false); - ListBuilder nestedTypes = GetNestedTypeCandidates(null, bindingAttr, false); + ListBuilder fields = GetFieldCandidates(null, bindingAttr, false); + ListBuilder nestedTypes = GetNestedTypeCandidates(null, bindingAttr, false); // Interfaces are excluded from the result of GetMembers MemberInfo[] members = new MemberInfo[ @@ -2748,18 +2748,18 @@ public override InterfaceMapping GetInterfaceMap(Type ifaceType) return GetMethodImplCommon(name, genericParameterCount, bindingAttr, binder, callConv, types, modifiers); } - private MethodInfo? GetMethodImplCommon( + private RuntimeMethodInfo? GetMethodImplCommon( string? name, int genericParameterCount, BindingFlags bindingAttr, Binder? binder, CallingConventions callConv, Type[]? types, ParameterModifier[]? modifiers) { - ListBuilder candidates = GetMethodCandidates(name, genericParameterCount, bindingAttr, callConv, types, false); + ListBuilder candidates = GetMethodCandidates(name, genericParameterCount, bindingAttr, callConv, types, false); if (candidates.Count == 0) return null; if (types == null || types.Length == 0) { - MethodInfo firstCandidate = candidates[0]; + RuntimeMethodInfo firstCandidate = candidates[0]; if (candidates.Count == 1) { @@ -2777,27 +2777,27 @@ public override InterfaceMapping GetInterfaceMap(Type ifaceType) } // All the methods have the exact same name and sig so return the most derived one. - return System.DefaultBinder.FindMostDerivedNewSlotMeth(candidates.ToArray(), candidates.Count) as MethodInfo; + return System.DefaultBinder.FindMostDerivedNewSlotMeth(candidates.ToArray(), candidates.Count); } } binder ??= DefaultBinder; - return binder.SelectMethod(bindingAttr, candidates.ToArray(), types, modifiers) as MethodInfo; + return binder.SelectMethod(bindingAttr, candidates.ToArray(), types, modifiers) as RuntimeMethodInfo; } [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)] - protected override ConstructorInfo? GetConstructorImpl( + protected override RuntimeConstructorInfo? GetConstructorImpl( BindingFlags bindingAttr, Binder? binder, CallingConventions callConvention, Type[] types, ParameterModifier[]? modifiers) { - ListBuilder candidates = GetConstructorCandidates(null, bindingAttr, CallingConventions.Any, types, false); + ListBuilder candidates = GetConstructorCandidates(null, bindingAttr, CallingConventions.Any, types, false); if (candidates.Count == 0) return null; if (types.Length == 0 && candidates.Count == 1) { - ConstructorInfo firstCandidate = candidates[0]; + RuntimeConstructorInfo firstCandidate = candidates[0]; ParameterInfo[] parameters = firstCandidate.GetParametersNoCopy(); if (parameters == null || parameters.Length == 0) @@ -2807,10 +2807,10 @@ public override InterfaceMapping GetInterfaceMap(Type ifaceType) } if ((bindingAttr & BindingFlags.ExactBinding) != 0) - return System.DefaultBinder.ExactBinding(candidates.ToArray(), types, modifiers) as ConstructorInfo; + return System.DefaultBinder.ExactBinding(candidates.ToArray(), types, modifiers); binder ??= DefaultBinder; - return binder.SelectMethod(bindingAttr, candidates.ToArray(), types, modifiers) as ConstructorInfo; + return binder.SelectMethod(bindingAttr, candidates.ToArray(), types, modifiers) as RuntimeConstructorInfo; } [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.NonPublicProperties)] @@ -2879,14 +2879,14 @@ public override InterfaceMapping GetInterfaceMap(Type ifaceType) } [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.NonPublicFields)] - public override FieldInfo? GetField(string name, BindingFlags bindingAttr) + public override RuntimeFieldInfo? GetField(string name, BindingFlags bindingAttr) { if (name is null) throw new ArgumentNullException(); FilterHelper(bindingAttr, ref name, out _, out MemberListType listType); RuntimeFieldInfo[] cache = Cache.GetFieldList(listType, name); - FieldInfo? match = null; + RuntimeFieldInfo? match = null; bindingAttr ^= BindingFlags.DeclaredOnly; bool multipleStaticFieldMatches = false; @@ -2916,7 +2916,7 @@ public override InterfaceMapping GetInterfaceMap(Type ifaceType) return match; } - public override Type? GetInterface(string fullname, bool ignoreCase) + public override RuntimeType? GetInterface(string fullname, bool ignoreCase) { if (fullname is null) throw new ArgumentNullException(nameof(fullname)); @@ -2951,7 +2951,7 @@ public override InterfaceMapping GetInterfaceMap(Type ifaceType) } [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicNestedTypes | DynamicallyAccessedMemberTypes.NonPublicNestedTypes)] - public override Type? GetNestedType(string fullname, BindingFlags bindingAttr) + public override RuntimeType? GetNestedType(string fullname, BindingFlags bindingAttr) { if (fullname is null) throw new ArgumentNullException(nameof(fullname)); @@ -2984,12 +2984,12 @@ public override MemberInfo[] GetMember(string name, MemberTypes type, BindingFla { if (name is null) throw new ArgumentNullException(nameof(name)); - ListBuilder methods = default; - ListBuilder constructors = default; + ListBuilder methods = default; + ListBuilder constructors = default; ListBuilder properties = default; ListBuilder events = default; - ListBuilder fields = default; - ListBuilder nestedTypes = default; + ListBuilder fields = default; + ListBuilder nestedTypes = default; int totalCount = 0; @@ -3154,7 +3154,7 @@ public override string? AssemblyQualifiedName if (fullname == null) return null; - return Assembly.CreateQualifiedName(Assembly.FullName, fullname); + return System.Reflection.Assembly.CreateQualifiedName(Assembly.FullName, fullname); } } @@ -3221,10 +3221,10 @@ internal RuntimeType[] GetGenericArgumentsInternal() return GetRootElementType().GetTypeHandleInternal().GetInstantiationInternal(); } - public override Type[] GetGenericArguments() + public override RuntimeType[] GetGenericArguments() { - Type[] types = GetRootElementType().GetTypeHandleInternal().GetInstantiationPublic(); - return types ?? Type.EmptyTypes; + RuntimeType[] types = GetRootElementType().GetTypeHandleInternal().GetInstantiationPublic(); + return types ?? EmptyTypes; } public override Type MakeGenericType(Type[] instantiation) @@ -3287,7 +3287,7 @@ public override Type MakeGenericType(Type[] instantiation) SanityCheckGenericArguments(instantiationRuntimeType, genericParameters); - Type ret; + RuntimeType ret; try { ret = new RuntimeTypeHandle(this).Instantiate(instantiationRuntimeType); @@ -3315,26 +3315,26 @@ public override int GenericParameterPosition public override bool ContainsGenericParameters => GetRootElementType().GetTypeHandleInternal().ContainsGenericVariables(); - public override Type[] GetGenericParameterConstraints() + public override RuntimeType[] GetGenericParameterConstraints() { if (!IsGenericParameter) throw new InvalidOperationException(SR.Arg_NotGenericParameter); - Type[] constraints = new RuntimeTypeHandle(this).GetConstraints(); - return constraints ?? Type.EmptyTypes; + RuntimeType[] constraints = new RuntimeTypeHandle(this).GetConstraints(); + return constraints ?? EmptyTypes; } #endregion #region Misc public sealed override bool HasSameMetadataDefinitionAs(MemberInfo other) => HasSameMetadataDefinitionAsCore(other); - public override Type MakePointerType() => new RuntimeTypeHandle(this).MakePointer(); + public override RuntimeType MakePointerType() => new RuntimeTypeHandle(this).MakePointer(); - public override Type MakeByRefType() => new RuntimeTypeHandle(this).MakeByRef(); + public override RuntimeType MakeByRefType() => new RuntimeTypeHandle(this).MakeByRef(); - public override Type MakeArrayType() => new RuntimeTypeHandle(this).MakeSZArray(); + public override RuntimeType MakeArrayType() => new RuntimeTypeHandle(this).MakeSZArray(); - public override Type MakeArrayType(int rank) + public override RuntimeType MakeArrayType(int rank) { if (rank <= 0) throw new IndexOutOfRangeException(); @@ -3852,7 +3852,7 @@ public override Type MakeArrayType(int rank) [MethodImpl(MethodImplOptions.NoInlining)] private string? GetCachedName(TypeNameKind kind) => Cache.GetName(kind); - public override Type? DeclaringType => Cache.GetEnclosingType(); + public override RuntimeType? DeclaringType => Cache.GetEnclosingType(); #endregion diff --git a/src/libraries/System.Private.CoreLib/src/System/DefaultBinder.cs b/src/libraries/System.Private.CoreLib/src/System/DefaultBinder.cs index 6b275ff8b21ca9..23f042cf4fc921 100644 --- a/src/libraries/System.Private.CoreLib/src/System/DefaultBinder.cs +++ b/src/libraries/System.Private.CoreLib/src/System/DefaultBinder.cs @@ -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) { 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++) @@ -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++) { diff --git a/src/libraries/System.Private.CoreLib/src/System/RuntimeType.cs b/src/libraries/System.Private.CoreLib/src/System/RuntimeType.cs index 6bc3ddf5cc8214..3a1ad63810ffe4 100644 --- a/src/libraries/System.Private.CoreLib/src/System/RuntimeType.cs +++ b/src/libraries/System.Private.CoreLib/src/System/RuntimeType.cs @@ -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(); + 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); @@ -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; @@ -92,7 +93,7 @@ public override MemberInfo[] GetDefaultMembers() return members ?? Array.Empty(); } - public override Type GetElementType() => RuntimeTypeHandle.GetElementType(this); + public override RuntimeType GetElementType() => RuntimeTypeHandle.GetElementType(this); public override string? GetEnumName(object value) { @@ -140,7 +141,7 @@ public override Array GetEnumValues() return ret; } - public override Type GetEnumUnderlyingType() + public override RuntimeType GetEnumUnderlyingType() { if (!IsEnum) throw new ArgumentException(SR.Arg_MustBeEnum, "enumType"); @@ -148,7 +149,7 @@ public override Type GetEnumUnderlyingType() return Enum.InternalGetUnderlyingType(this); } - public override Type GetGenericTypeDefinition() + public override RuntimeType GetGenericTypeDefinition() { if (!IsGenericType) throw new InvalidOperationException(SR.InvalidOperation_NotGenericType); @@ -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 @@ -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; diff --git a/src/mono/netcore/System.Private.CoreLib/src/Mono/RuntimeHandles.cs b/src/mono/netcore/System.Private.CoreLib/src/Mono/RuntimeHandles.cs index 7e655adbbe66e9..3ce583169ce9ca 100644 --- a/src/mono/netcore/System.Private.CoreLib/src/Mono/RuntimeHandles.cs +++ b/src/mono/netcore/System.Private.CoreLib/src/Mono/RuntimeHandles.cs @@ -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; diff --git a/src/mono/netcore/System.Private.CoreLib/src/System/RuntimeType.Mono.cs b/src/mono/netcore/System.Private.CoreLib/src/System/RuntimeType.Mono.cs index eb514d171cf690..290631825069fe 100644 --- a/src/mono/netcore/System.Private.CoreLib/src/System/RuntimeType.Mono.cs +++ b/src/mono/netcore/System.Private.CoreLib/src/System/RuntimeType.Mono.cs @@ -578,7 +578,7 @@ private static bool FilterApplyMethodBase( #region Type Overrides #region Get XXXInfo Candidates - private ListBuilder GetMethodCandidates( + private ListBuilder GetMethodCandidates( string? name, BindingFlags bindingAttr, CallingConventions callConv, Type[]? types, int genericParamCount, bool allowPrefixLookup) { @@ -587,7 +587,7 @@ private ListBuilder GetMethodCandidates( FilterHelper(bindingAttr, ref name, allowPrefixLookup, out prefixLookup, out ignoreCase, out listType); RuntimeMethodInfo[] cache = GetMethodsByName(name, bindingAttr, listType, this); - ListBuilder candidates = new ListBuilder(cache.Length); + ListBuilder candidates = new ListBuilder(cache.Length); for (int i = 0; i < cache.Length; i++) { @@ -613,7 +613,7 @@ private ListBuilder GetMethodCandidates( return candidates; } - private ListBuilder GetConstructorCandidates( + private ListBuilder GetConstructorCandidates( string? name, BindingFlags bindingAttr, CallingConventions callConv, Type[]? types, bool allowPrefixLookup) { @@ -622,9 +622,9 @@ private ListBuilder GetConstructorCandidates( FilterHelper(bindingAttr, ref name, allowPrefixLookup, out prefixLookup, out ignoreCase, out listType); if (!string.IsNullOrEmpty(name) && name != ConstructorInfo.ConstructorName && name != ConstructorInfo.TypeConstructorName) - return new ListBuilder(0); + return new ListBuilder(0); RuntimeConstructorInfo[] cache = GetConstructors_internal(bindingAttr, this); - ListBuilder candidates = new ListBuilder(cache.Length); + ListBuilder candidates = new ListBuilder(cache.Length); for (int i = 0; i < cache.Length; i++) { RuntimeConstructorInfo constructorInfo = cache[i]; @@ -775,8 +775,8 @@ public override Type[] GetNestedTypes(BindingFlags bindingAttr) [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] public override MemberInfo[] GetMembers(BindingFlags bindingAttr) { - ListBuilder methods = GetMethodCandidates(null, bindingAttr, CallingConventions.Any, null, -1, false); - ListBuilder constructors = GetConstructorCandidates(null, bindingAttr, CallingConventions.Any, null, false); + ListBuilder methods = GetMethodCandidates(null, bindingAttr, CallingConventions.Any, null, -1, false); + ListBuilder constructors = GetConstructorCandidates(null, bindingAttr, CallingConventions.Any, null, false); ListBuilder properties = GetPropertyCandidates(null, bindingAttr, null, false); ListBuilder events = GetEventCandidates(null, bindingAttr, false); ListBuilder fields = GetFieldCandidates(null, bindingAttr, false); @@ -812,17 +812,17 @@ public override MemberInfo[] GetMembers(BindingFlags bindingAttr) } [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods)] - protected override MethodInfo? GetMethodImpl(string name, int genericParamCount, + protected override RuntimeMethodInfo? GetMethodImpl(string name, int genericParamCount, BindingFlags bindingAttr, Binder? binder, CallingConventions callConv, Type[]? types, ParameterModifier[]? modifiers) { - ListBuilder candidates = GetMethodCandidates(name, bindingAttr, callConv, types, genericParamCount, false); + ListBuilder candidates = GetMethodCandidates(name, bindingAttr, callConv, types, genericParamCount, false); if (candidates.Count == 0) return null; if (types == null || types.Length == 0) { - MethodInfo firstCandidate = candidates[0]; + RuntimeMethodInfo firstCandidate = candidates[0]; if (candidates.Count == 1) { @@ -832,35 +832,35 @@ public override MemberInfo[] GetMembers(BindingFlags bindingAttr) { for (int j = 1; j < candidates.Count; j++) { - MethodInfo methodInfo = candidates[j]; + RuntimeMethodInfo methodInfo = candidates[j]; if (!System.DefaultBinder.CompareMethodSig(methodInfo, firstCandidate)) throw new AmbiguousMatchException(Environment.GetResourceString("Arg_AmbiguousMatchException")); } // All the methods have the exact same name and sig so return the most derived one. - return System.DefaultBinder.FindMostDerivedNewSlotMeth(candidates.ToArray(), candidates.Count) as MethodInfo; + return System.DefaultBinder.FindMostDerivedNewSlotMeth(candidates.ToArray(), candidates.Count); } } if (binder == null) binder = DefaultBinder; - return binder.SelectMethod(bindingAttr, candidates.ToArray(), types, modifiers) as MethodInfo; + return binder.SelectMethod(bindingAttr, candidates.ToArray(), types, modifiers) as RuntimeMethodInfo; } [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)] - protected override ConstructorInfo? GetConstructorImpl( + protected override RuntimeConstructorInfo? GetConstructorImpl( BindingFlags bindingAttr, Binder? binder, CallingConventions callConvention, Type[] types, ParameterModifier[]? modifiers) { - ListBuilder candidates = GetConstructorCandidates(null, bindingAttr, CallingConventions.Any, types, false); + ListBuilder candidates = GetConstructorCandidates(null, bindingAttr, CallingConventions.Any, types, false); if (candidates.Count == 0) return null; if (types.Length == 0 && candidates.Count == 1) { - ConstructorInfo firstCandidate = candidates[0]; + RuntimeConstructorInfo firstCandidate = candidates[0]; ParameterInfo[] parameters = firstCandidate.GetParametersNoCopy(); if (parameters == null || parameters.Length == 0) @@ -870,12 +870,12 @@ public override MemberInfo[] GetMembers(BindingFlags bindingAttr) } if ((bindingAttr & BindingFlags.ExactBinding) != 0) - return System.DefaultBinder.ExactBinding(candidates.ToArray(), types, modifiers) as ConstructorInfo; + return System.DefaultBinder.ExactBinding(candidates.ToArray(), types, modifiers); if (binder == null) binder = DefaultBinder; - return binder.SelectMethod(bindingAttr, candidates.ToArray(), types, modifiers) as ConstructorInfo; + return binder.SelectMethod(bindingAttr, candidates.ToArray(), types, modifiers) as RuntimeConstructorInfo; } [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.NonPublicProperties)] @@ -1073,8 +1073,8 @@ public override MemberInfo[] GetMember(string name, MemberTypes type, BindingFla { if (name == null) throw new ArgumentNullException(nameof(name)); - ListBuilder methods = default; - ListBuilder constructors = default; + ListBuilder methods = default; + ListBuilder constructors = default; ListBuilder properties = default; ListBuilder events = default; ListBuilder fields = default; @@ -1856,7 +1856,7 @@ internal RuntimeType(object obj) if (Volatile.Read(ref cache.default_ctor_cached)) return cache.default_ctor; - ListBuilder ctors = GetConstructorCandidates( + ListBuilder ctors = GetConstructorCandidates( null, BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.DeclaredOnly, CallingConventions.Any, Type.EmptyTypes, false); @@ -2243,26 +2243,26 @@ public override bool ContainsGenericParameters } } - public override Type[] GetGenericParameterConstraints() + public override RuntimeType[] GetGenericParameterConstraints() { if (!IsGenericParameter) throw new InvalidOperationException(Environment.GetResourceString("Arg_NotGenericParameter")); var paramInfo = new Mono.RuntimeGenericParamInfoHandle(RuntimeTypeHandle.GetGenericParameterInfo(this)); - Type[] constraints = paramInfo.Constraints; + RuntimeType[] constraints = paramInfo.Constraints; - return constraints ?? Type.EmptyTypes; + return constraints ?? EmptyTypes; } internal static object CreateInstanceForAnotherGenericParameter(Type genericType, RuntimeType genericArgument) { - var gt = (RuntimeType)MakeGenericType(genericType, new Type[] { genericArgument }); + var gt = MakeGenericType(genericType, new Type[] { genericArgument }); RuntimeConstructorInfo ctor = gt.GetDefaultConstructor()!; return ctor.InternalInvoke(null, null, wrapExceptions: true)!; } [MethodImplAttribute(MethodImplOptions.InternalCall)] - private static extern Type MakeGenericType(Type gt, Type[] types); + private static extern RuntimeType MakeGenericType(Type gt, Type[] types); [MethodImplAttribute(MethodImplOptions.InternalCall)] internal extern IntPtr GetMethodsByName_native(IntPtr namePtr, BindingFlags bindingAttr, MemberListType listType); @@ -2454,12 +2454,20 @@ private RuntimeType[] GetNestedTypes_internal(string? displayName, BindingFlags for (int i = 0; i < n; i++) { var th = new RuntimeTypeHandle(h[i]); - a[i] = (RuntimeType)GetTypeFromHandle(th); + a[i] = GetTypeFromHandle(th); } return a; } } + public static new RuntimeType GetTypeFromHandle(RuntimeTypeHandle handle) + { + if (handle.Value == IntPtr.Zero) + return null!; // FIXME: shouldn't return null + + return internal_from_handle(handle.Value); + } + public override string? AssemblyQualifiedName { get @@ -2468,7 +2476,7 @@ public override string? AssemblyQualifiedName } } - public extern override Type? DeclaringType + public extern override RuntimeType? DeclaringType { [MethodImplAttribute(MethodImplOptions.InternalCall)] get; diff --git a/src/mono/netcore/System.Private.CoreLib/src/System/RuntimeTypeHandle.cs b/src/mono/netcore/System.Private.CoreLib/src/System/RuntimeTypeHandle.cs index dc1eaef95e6f97..afbb1bec459fef 100644 --- a/src/mono/netcore/System.Private.CoreLib/src/System/RuntimeTypeHandle.cs +++ b/src/mono/netcore/System.Private.CoreLib/src/System/RuntimeTypeHandle.cs @@ -133,9 +133,9 @@ internal static int GetToken(RuntimeType type) } [MethodImplAttribute(MethodImplOptions.InternalCall)] - private static extern Type GetGenericTypeDefinition_impl(RuntimeType type); + private static extern RuntimeType GetGenericTypeDefinition_impl(RuntimeType type); - internal static Type GetGenericTypeDefinition(RuntimeType type) + internal static RuntimeType GetGenericTypeDefinition(RuntimeType type) { return GetGenericTypeDefinition_impl(type); } diff --git a/src/mono/netcore/System.Private.CoreLib/src/System/Type.Mono.cs b/src/mono/netcore/System.Private.CoreLib/src/System/Type.Mono.cs index 085dc6aaac221b..f1e35fd136b712 100644 --- a/src/mono/netcore/System.Private.CoreLib/src/System/Type.Mono.cs +++ b/src/mono/netcore/System.Private.CoreLib/src/System/Type.Mono.cs @@ -132,7 +132,7 @@ internal virtual FieldInfo GetField(FieldInfo fromNoninstanciated) } [MethodImplAttribute(MethodImplOptions.InternalCall)] - private static extern Type internal_from_handle(IntPtr handle); + internal static extern RuntimeType internal_from_handle(IntPtr handle); [Intrinsic] public static bool operator ==(Type? left, Type? right) => left == right; From 08934ac4719b42b441d8cff96da793c3c3c7a14c Mon Sep 17 00:00:00 2001 From: Jan Vorlicek Date: Mon, 30 Nov 2020 21:54:41 +0100 Subject: [PATCH 2/2] Fix problem with covariant returns with RuntimeType Ben Adams has tried to add usage of covariant returns for the RuntimeType as the overriding return type and it has uncovered an ordering issue in the SystemDomain::LoadBaseSystemClasses w.r.t. This change fixes it by shuffling parts of initialization around a bit. --- src/coreclr/src/vm/appdomain.cpp | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/src/coreclr/src/vm/appdomain.cpp b/src/coreclr/src/vm/appdomain.cpp index f703b4214cea61..792f0caa593bd4 100644 --- a/src/coreclr/src/vm/appdomain.cpp +++ b/src/coreclr/src/vm/appdomain.cpp @@ -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 for an array requires redirection to a method on // the SZArrayHelper class. Retrieving such methods means calling // GetActualImplementationForArrayGenericIListMethod, which calls FetchMethod for @@ -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); @@ -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