diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Reflection/Core/Execution/ExecutionDomain.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Reflection/Core/Execution/ExecutionDomain.cs index 02f6a206015db2..85199ce870ed09 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Reflection/Core/Execution/ExecutionDomain.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Reflection/Core/Execution/ExecutionDomain.cs @@ -4,6 +4,7 @@ using System; using System.Reflection; using System.Collections.Generic; +using System.Diagnostics; using System.Reflection.Runtime.General; using System.Reflection.Runtime.TypeInfos; using System.Reflection.Runtime.TypeInfos.NativeFormat; @@ -206,14 +207,8 @@ public Type GetNamedTypeForHandle(RuntimeTypeHandle typeHandle, bool isGenericTy } else { - if (ExecutionEnvironment.IsReflectionBlocked(typeHandle)) - { - return RuntimeBlockedTypeInfo.GetRuntimeBlockedTypeInfo(typeHandle, isGenericTypeDefinition); - } - else - { - return RuntimeNoMetadataNamedTypeInfo.GetRuntimeNoMetadataNamedTypeInfo(typeHandle, isGenericTypeDefinition); - } + Debug.Assert(ExecutionEnvironment.IsReflectionBlocked(typeHandle)); + return RuntimeBlockedTypeInfo.GetRuntimeBlockedTypeInfo(typeHandle, isGenericTypeDefinition); } } @@ -285,23 +280,13 @@ public Type GetConstructedGenericTypeForHandle(RuntimeTypeHandle typeHandle) } //======================================================================================= - // MissingMetadataExceptions. + // Missing metadata exceptions. //======================================================================================= public Exception CreateMissingMetadataException(Type? pertainant) { return this.ReflectionDomainSetup.CreateMissingMetadataException(pertainant); } - public Exception CreateMissingMetadataException(TypeInfo? pertainant) - { - return this.ReflectionDomainSetup.CreateMissingMetadataException(pertainant); - } - - public Exception CreateMissingMetadataException(TypeInfo pertainant, string nestedTypeName) - { - return this.ReflectionDomainSetup.CreateMissingMetadataException(pertainant, nestedTypeName); - } - public Exception CreateNonInvokabilityException(MemberInfo pertainant) { return this.ReflectionDomainSetup.CreateNonInvokabilityException(pertainant); @@ -336,16 +321,13 @@ public bool SupportsReflection(Type type) if (type is not RuntimeType) return false; - RuntimeTypeInfo runtimeType = type.CastToRuntimeTypeInfo(); - if (null == runtimeType.InternalNameIfAvailable) - return false; - if (ExecutionEnvironment.IsReflectionBlocked(type.TypeHandle)) { // The type is an internal framework type and is blocked from reflection return false; } + RuntimeTypeInfo runtimeType = type.CastToRuntimeTypeInfo(); if (runtimeType.InternalFullNameOfAssembly == Internal.Runtime.Augments.RuntimeAugments.HiddenScopeAssemblyName) { // The type is an internal framework type but is reflectable for internal class library use diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Reflection/Core/ReflectionDomainSetup.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Reflection/Core/ReflectionDomainSetup.cs index 17bf45902fdca3..dfb955cf69139d 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Reflection/Core/ReflectionDomainSetup.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Reflection/Core/ReflectionDomainSetup.cs @@ -14,9 +14,7 @@ public abstract class ReflectionDomainSetup { protected ReflectionDomainSetup() { } public abstract AssemblyBinder AssemblyBinder { get; } - public abstract Exception CreateMissingMetadataException(TypeInfo? pertainant); public abstract Exception CreateMissingMetadataException(Type? pertainant); - public abstract Exception CreateMissingMetadataException(TypeInfo pertainant, string nestedTypeName); public abstract Exception CreateNonInvokabilityException(MemberInfo pertainant); public abstract Exception CreateMissingArrayTypeException(Type elementType, bool isMultiDim, int rank); public abstract Exception CreateMissingConstructedGenericTypeException(Type genericTypeDefinition, Type[] genericTypeArguments); diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Reflection/Extensions/NonPortable/CustomAttributeSearcher.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Reflection/Extensions/NonPortable/CustomAttributeSearcher.cs index c01d470b258a6f..ace00c0923f7bd 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Reflection/Extensions/NonPortable/CustomAttributeSearcher.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Reflection/Extensions/NonPortable/CustomAttributeSearcher.cs @@ -45,24 +45,7 @@ public IEnumerable GetMatchingCustomAttributes(E element, T optionalAttributeTypeFilter.IsSubclassOf(typeof(Attribute)))) throw new ArgumentException(SR.Argument_MustHaveAttributeBaseClass); - try - { - typeFilterKnownToBeSealed = optionalAttributeTypeFilter.IsSealed; - } - catch (MissingMetadataException) - { - // If we got here, the custom attribute type itself was not opted into metadata. This can and does happen in the real world when an app - // contains a check for custom attributes that never actually appear on any entity within the app. - // - // Since "typeFilterKnownToBeSealed" is only used to enable an optimization, it's always safe to leave it "false". - // - // Because the NativeAOT toolchain removes any custom attribute that refuses to opt into metadata so at this point, - // we could simply return an empty enumeration and "be correct." However, the code paths following this already do that naturally. - // (i.e. the "passFilter" will never return true, thus we will never attempt to query the custom attribute type for its - // own AttributeUsage custom attribute.) If the toolchain behavior changes in the future, it's preferable that - // this shows up as new MissingMetadataExceptions rather than incorrect results from the api so we will not put - // in an explicit return here. - } + typeFilterKnownToBeSealed = optionalAttributeTypeFilter.IsSealed; } Func passesFilter; diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/MatchingRefApiCompatBaseline.txt b/src/coreclr/nativeaot/System.Private.CoreLib/src/MatchingRefApiCompatBaseline.txt index 666219875bb7cb..5a44b79d56903d 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/MatchingRefApiCompatBaseline.txt +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/MatchingRefApiCompatBaseline.txt @@ -209,7 +209,6 @@ TypesMustExist : Type 'System.MDArray' does not exist in the reference but it do MembersMustExist : Member 'public void System.ModuleHandle..ctor(System.Reflection.Module)' does not exist in the reference but it does exist in the implementation. TypesMustExist : Type 'System.RuntimeExceptionHelpers' does not exist in the reference but it does exist in the implementation. TypesMustExist : Type 'System.RuntimeType' does not exist in the reference but it does exist in the implementation. -MembersMustExist : Member 'public System.String System.Type.InternalNameIfAvailable.get()' does not exist in the reference but it does exist in the implementation. MembersMustExist : Member 'public System.Boolean System.TypedReference.IsNull.get()' does not exist in the reference but it does exist in the implementation. TypesMustExist : Type 'System.Diagnostics.DebugAnnotations' does not exist in the reference but it does exist in the implementation. TypesMustExist : Type 'System.Diagnostics.DebuggerGuidedStepThroughAttribute' does not exist in the reference but it does exist in the implementation. @@ -229,7 +228,6 @@ TypesMustExist : Type 'System.Reflection.DynamicInvokeInfo' does not exist in th TypesMustExist : Type 'System.Reflection.EnumInfo' does not exist in the reference but it does exist in the implementation. MembersMustExist : Member 'public System.Reflection.ParameterInfo[] System.Reflection.MethodBase.GetParametersNoCopy()' does not exist in the reference but it does exist in the implementation. MembersMustExist : Member 'public System.Reflection.MethodBase System.Reflection.MethodBase.MetadataDefinitionMethod.get()' does not exist in the reference but it does exist in the implementation. -TypesMustExist : Type 'System.Reflection.MissingMetadataException' does not exist in the reference but it does exist in the implementation. MembersMustExist : Member 'protected System.ModuleHandle System.Reflection.Module.GetModuleHandleImpl()' does not exist in the reference but it does exist in the implementation. TypesMustExist : Type 'System.Reflection.RuntimeAssembly' does not exist in the reference but it does exist in the implementation. TypesMustExist : Type 'System.Reflection.RuntimeAssemblyName' does not exist in the reference but it does exist in the implementation. diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System.Private.CoreLib.csproj b/src/coreclr/nativeaot/System.Private.CoreLib/src/System.Private.CoreLib.csproj index 3a113147f4eac1..e84f5ed4947036 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System.Private.CoreLib.csproj +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System.Private.CoreLib.csproj @@ -186,7 +186,6 @@ - @@ -461,7 +460,6 @@ - @@ -522,7 +520,6 @@ - diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/MissingMetadataException.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/MissingMetadataException.cs deleted file mode 100644 index 51c5acd7d3905d..00000000000000 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/MissingMetadataException.cs +++ /dev/null @@ -1,19 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System; - -namespace System.Reflection -{ - public sealed class MissingMetadataException : TypeAccessException - { - public MissingMetadataException() - { - } - - public MissingMetadataException(string message) - : base(message) - { - } - } -} diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/BindingFlagSupport/QueriedMemberList.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/BindingFlagSupport/QueriedMemberList.cs index 427d00b8d506b8..ed5cabdba05f1a 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/BindingFlagSupport/QueriedMemberList.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/BindingFlagSupport/QueriedMemberList.cs @@ -29,24 +29,21 @@ private QueriedMemberList() _allFlagsThatMustMatch = new BindingFlags[Grow]; } - private QueriedMemberList(int totalCount, int declaredOnlyCount, M[] members, BindingFlags[] allFlagsThatMustMatch, RuntimeTypeInfo typeThatBlockedBrowsing) + private QueriedMemberList(int totalCount, int declaredOnlyCount, M[] members, BindingFlags[] allFlagsThatMustMatch) { _totalCount = totalCount; _declaredOnlyCount = declaredOnlyCount; _members = members; _allFlagsThatMustMatch = allFlagsThatMustMatch; - _typeThatBlockedBrowsing = typeThatBlockedBrowsing; } /// - /// Returns the # of candidates for a non-DeclaredOnly search. Caution: Can throw MissingMetadataException. Use DeclaredOnlyCount if you don't want to search base classes. + /// Returns the # of candidates for a non-DeclaredOnly search. Use DeclaredOnlyCount if you don't want to search base classes. /// public int TotalCount { get { - if (_typeThatBlockedBrowsing != null) - throw ReflectionCoreExecution.ExecutionDomain.CreateMissingMetadataException(_typeThatBlockedBrowsing); return _totalCount; } } @@ -93,7 +90,7 @@ public QueriedMemberList Filter(Func predicate) } } - return new QueriedMemberList(newTotalCount, newDeclaredOnlyCount, newMembers, newAllFlagsThatMustMatch, _typeThatBlockedBrowsing); + return new QueriedMemberList(newTotalCount, newDeclaredOnlyCount, newMembers, newAllFlagsThatMustMatch); } // @@ -151,16 +148,6 @@ public static QueriedMemberList Create(RuntimeTypeInfo type, string optionalN } type = type.BaseType.CastToRuntimeTypeInfo(); - - if (type != null && !type.CanBrowseWithoutMissingMetadataExceptions) - { - // If we got here, one of the base classes is missing metadata. We don't want to throw a MissingMetadataException now because we may be - // building a cached result for a caller who passed BindingFlags.DeclaredOnly. So we'll mark the results in a way that - // it will throw a MissingMetadataException if a caller attempts to iterate past the declared-only subset. - queriedMembers._typeThatBlockedBrowsing = type; - queriedMembers._totalCount = queriedMembers._declaredOnlyCount; - break; - } } return queriedMembers; @@ -196,7 +183,6 @@ private void Add(M member, BindingFlags allFlagsThatMustMatch) private int _declaredOnlyCount; // # of entries for members only in the most derived class. private M[] _members; // Length is equal to or greater than _totalCount. Entries beyond _totalCount contain null or garbage and should be read. private BindingFlags[] _allFlagsThatMustMatch; // Length will be equal to _members.Length - private RuntimeTypeInfo _typeThatBlockedBrowsing; // If non-null, one of the base classes was missing metadata. private const int Grow = 64; } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/CustomAttributes/NativeFormat/NativeFormatCustomAttributeData.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/CustomAttributes/NativeFormat/NativeFormatCustomAttributeData.cs index f564f311cc7454..07801d02a50f52 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/CustomAttributes/NativeFormat/NativeFormatCustomAttributeData.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/CustomAttributes/NativeFormat/NativeFormatCustomAttributeData.cs @@ -92,16 +92,8 @@ public sealed override ConstructorInfo Constructor } } - internal sealed override string AttributeTypeString - { - get - { - return new QTypeDefRefOrSpec(_reader, _customAttribute.GetAttributeTypeHandle(_reader)).FormatTypeName(new TypeContext(null, null)); - } - } - // - // If throwIfMissingMetadata is false, returns null rather than throwing a MissingMetadataException. + // If throwIfMissingMetadata is false, returns null rather than throwing a missing metadata exception. // internal sealed override IList GetConstructorArguments(bool throwIfMissingMetadata) { @@ -158,7 +150,7 @@ internal sealed override IList GetConstructorArgum } // - // If throwIfMissingMetadata is false, returns null rather than throwing a MissingMetadataException. + // If throwIfMissingMetadata is false, returns null rather than throwing a missing metadata exception. // internal sealed override IList GetNamedArguments(bool throwIfMissingMetadata) { diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/CustomAttributes/RuntimeCustomAttributeData.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/CustomAttributes/RuntimeCustomAttributeData.cs index 2b964c6b0b5605..26b43b401491f7 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/CustomAttributes/RuntimeCustomAttributeData.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/CustomAttributes/RuntimeCustomAttributeData.cs @@ -37,39 +37,32 @@ public sealed override IList NamedArguments public sealed override string ToString() { - try - { - string ctorArgs = ""; - IList constructorArguments = GetConstructorArguments(throwIfMissingMetadata: false); - if (constructorArguments == null) - return LastResortToString; - for (int i = 0; i < constructorArguments.Count; i++) - ctorArgs += string.Format(i == 0 ? "{0}" : ", {0}", ComputeTypedArgumentString(constructorArguments[i], typed: false)); - - string namedArgs = ""; - IList namedArguments = GetNamedArguments(throwIfMissingMetadata: false); - if (namedArguments == null) - return LastResortToString; - for (int i = 0; i < namedArguments.Count; i++) - { - CustomAttributeNamedArgument namedArgument = namedArguments[i]; - - // Legacy: Desktop sets "typed" to "namedArgument.ArgumentType != typeof(Object)" - on Project N, this property is not available - // (nor conveniently computable as it's not captured in the Project N metadata.) The only consequence is that for - // the rare case of fields and properties typed "Object", we won't decorate the argument value with its actual type name. - bool typed = true; - namedArgs += string.Format( - i == 0 && ctorArgs.Length == 0 ? "{0} = {1}" : ", {0} = {1}", - namedArgument.MemberName, - ComputeTypedArgumentString(namedArgument.TypedValue, typed)); - } + string ctorArgs = ""; + IList constructorArguments = GetConstructorArguments(throwIfMissingMetadata: false); + if (constructorArguments == null) + return LastResortToString; + for (int i = 0; i < constructorArguments.Count; i++) + ctorArgs += string.Format(i == 0 ? "{0}" : ", {0}", ComputeTypedArgumentString(constructorArguments[i], typed: false)); - return string.Format("[{0}({1}{2})]", AttributeTypeString, ctorArgs, namedArgs); - } - catch (MissingMetadataException) - { + string namedArgs = ""; + IList namedArguments = GetNamedArguments(throwIfMissingMetadata: false); + if (namedArguments == null) return LastResortToString; + for (int i = 0; i < namedArguments.Count; i++) + { + CustomAttributeNamedArgument namedArgument = namedArguments[i]; + + // Legacy: Desktop sets "typed" to "namedArgument.ArgumentType != typeof(Object)" - on Project N, this property is not available + // (nor conveniently computable as it's not captured in the Project N metadata.) The only consequence is that for + // the rare case of fields and properties typed "Object", we won't decorate the argument value with its actual type name. + bool typed = true; + namedArgs += string.Format( + i == 0 && ctorArgs.Length == 0 ? "{0} = {1}" : ", {0} = {1}", + namedArgument.MemberName, + ComputeTypedArgumentString(namedArgument.TypedValue, typed)); } + + return string.Format("[{0}({1}{2})]", AttributeType.FormatTypeNameForReflection(), ctorArgs, namedArgs); } protected static ConstructorInfo ResolveAttributeConstructor( @@ -95,15 +88,13 @@ protected static ConstructorInfo ResolveAttributeConstructor( throw new MissingMethodException(); } - internal abstract string AttributeTypeString { get; } - // - // If throwIfMissingMetadata is false, returns null rather than throwing a MissingMetadataException. + // If throwIfMissingMetadata is false, returns null rather than throwing a missing metadata exception. // internal abstract IList GetConstructorArguments(bool throwIfMissingMetadata); // - // If throwIfMissingMetadata is false, returns null rather than throwing a MissingMetadataException. + // If throwIfMissingMetadata is false, returns null rather than throwing a missing metadata exception. // internal abstract IList GetNamedArguments(bool throwIfMissingMetadata); diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/CustomAttributes/RuntimePseudoCustomAttributeData.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/CustomAttributes/RuntimePseudoCustomAttributeData.cs index 84e8358f42ab87..a055fd068214de 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/CustomAttributes/RuntimePseudoCustomAttributeData.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/CustomAttributes/RuntimePseudoCustomAttributeData.cs @@ -51,14 +51,6 @@ public sealed override ConstructorInfo Constructor } } - internal sealed override string AttributeTypeString - { - get - { - return _attributeType.FormatTypeNameForReflection(); - } - } - internal sealed override IList GetConstructorArguments(bool throwIfMissingMetadata) { return _constructorArguments; diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/EventInfos/RuntimeEventInfo.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/EventInfos/RuntimeEventInfo.cs index bb46778ed15d46..da4d3743253592 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/EventInfos/RuntimeEventInfo.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/EventInfos/RuntimeEventInfo.cs @@ -115,7 +115,7 @@ public sealed override string ToString() if (parameters.Length == 0) throw new InvalidOperationException(); // Legacy: Why is a ToString() intentionally throwing an exception? RuntimeParameterInfo runtimeParameterInfo = (RuntimeParameterInfo)(parameters[0]); - return runtimeParameterInfo.ParameterTypeString + " " + this.Name; + return runtimeParameterInfo.ParameterType.FormatTypeNameForReflection() + " " + this.Name; } protected RuntimeEventInfo WithDebugName() diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/FieldInfos/NativeFormat/NativeFormatRuntimeFieldInfo.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/FieldInfos/NativeFormat/NativeFormatRuntimeFieldInfo.cs index 83835e4ce9e1b2..d60162242750f4 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/FieldInfos/NativeFormat/NativeFormatRuntimeFieldInfo.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/FieldInfos/NativeFormat/NativeFormatRuntimeFieldInfo.cs @@ -89,9 +89,7 @@ protected sealed override string MetadataName public sealed override string ToString() { - TypeContext typeContext = _contextTypeInfo.TypeContext; - Handle typeHandle = _field.Signature.GetFieldSignature(_reader).Type; - return (new QTypeDefRefOrSpec(_reader, typeHandle).FormatTypeName(typeContext)) + " " + this.Name; + return FieldRuntimeType.FormatTypeNameForReflection() + " " + this.Name; } public sealed override bool HasSameMetadataDefinitionAs(MemberInfo other) diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/QSignatureTypeHandle.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/QSignatureTypeHandle.cs index 59925d98a73fd8..116249d661f409 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/QSignatureTypeHandle.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/QSignatureTypeHandle.cs @@ -61,31 +61,5 @@ internal Type[] GetCustomModifiers(TypeContext typeContext, bool optional) return _handle.GetCustomModifiers((global::Internal.Metadata.NativeFormat.MetadataReader)Reader, typeContext, optional); #endif } - - // - // This is a port of the desktop CLR's RuntimeType.FormatTypeName() routine. This routine is used by various Reflection ToString() methods - // to display the name of a type. Do not use for any other purpose as it inherits some pretty quirky desktop behavior. - // - internal string FormatTypeName(TypeContext typeContext) - { - try - { - // Though we wrap this in a try-catch as a failsafe, this code must still strive to avoid triggering MissingMetadata exceptions - // (non-error exceptions are very annoying when debugging.) - - Exception? exception = null; - RuntimeTypeInfo? runtimeType = TryResolve(typeContext, ref exception); - if (runtimeType == null) - return Type.DefaultTypeNameWhenMissingMetadata; - - // Because this runtimeType came from a successful TryResolve() call, it is safe to querying the TypeInfo's of the type and its component parts. - // If we're wrong, we do have the safety net of a try-catch. - return runtimeType.FormatTypeNameForReflection(); - } - catch (Exception) - { - return Type.DefaultTypeNameWhenMissingMetadata; - } - } } } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/ToStringUtils.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/ToStringUtils.cs deleted file mode 100644 index 0a9ff9c82f83aa..00000000000000 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/ToStringUtils.cs +++ /dev/null @@ -1,39 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Reflection.Runtime.TypeInfos; -using Internal.Reflection.Core.Execution; - -namespace System.Reflection.Runtime.General -{ - internal static class ToStringUtils - { - // - // This is a port of the desktop CLR's RuntimeType.FormatTypeName() routine. This routine is used by various Reflection ToString() methods - // to display the name of a type. Do not use for any other purpose as it inherits some pretty quirky desktop behavior. - // - // The Project N version takes a raw metadata handle rather than a completed type so that it remains robust in the face of missing metadata. - // - public static string FormatTypeName(this QTypeDefRefOrSpec qualifiedTypeHandle, TypeContext typeContext) - { - try - { - // Though we wrap this in a try-catch as a failsafe, this code must still strive to avoid triggering MissingMetadata exceptions - // (non-error exceptions are very annoying when debugging.) - - Exception? exception = null; - RuntimeTypeInfo runtimeType = qualifiedTypeHandle.TryResolve(typeContext, ref exception); - if (runtimeType == null) - return Type.DefaultTypeNameWhenMissingMetadata; - - // Because this runtimeType came from a successful TryResolve() call, it is safe to querying the TypeInfo's of the type and its component parts. - // If we're wrong, we do have the safety net of a try-catch. - return runtimeType.FormatTypeNameForReflection(); - } - catch (Exception) - { - return Type.DefaultTypeNameWhenMissingMetadata; - } - } - } -} diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/TypeResolver.NativeFormat.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/TypeResolver.NativeFormat.cs index 838f6a1f6dfa11..1979b411cabe7e 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/TypeResolver.NativeFormat.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/TypeResolver.NativeFormat.cs @@ -180,7 +180,7 @@ internal static RuntimeTypeInfo ResolveTypeDefinition(this TypeDefinitionHandle RuntimeTypeInfo? outerType = parent.ToTypeReferenceHandle(reader).TryResolveTypeReference(reader, ref exception); if (outerType == null) return null; - outerTypeInfo = outerType; // Since we got to outerType via a metadata reference, we're assured GetTypeInfo() won't throw a MissingMetadataException. + outerTypeInfo = outerType; // Since we got to outerType via a metadata reference, we're assured GetTypeInfo() won't throw a missing metadata exception. } if (outerTypeInfo != null) { @@ -188,7 +188,7 @@ internal static RuntimeTypeInfo ResolveTypeDefinition(this TypeDefinitionHandle TypeInfo? resolvedTypeInfo = outerTypeInfo.GetDeclaredNestedType(name); if (resolvedTypeInfo == null) { - exception = ReflectionCoreExecution.ExecutionDomain.CreateMissingMetadataException(outerTypeInfo, name); + exception = Helpers.CreateTypeLoadException(outerTypeInfo.FullName + "+" + name, outerTypeInfo.Assembly); return null; } return resolvedTypeInfo.CastToRuntimeTypeInfo(); diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/TypeUnifier.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/TypeUnifier.cs index cdc37f01a1b53d..1a42512ea4afe5 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/TypeUnifier.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/TypeUnifier.cs @@ -156,43 +156,6 @@ public static RuntimeTypeInfo GetConstructedGenericType(this RuntimeTypeInfo gen namespace System.Reflection.Runtime.TypeInfos { - //----------------------------------------------------------------------------------------------------------- - // TypeInfos for type definitions (i.e. "Foo" and "Foo<>" but not "Foo") that aren't opted into metadata. - //----------------------------------------------------------------------------------------------------------- - internal sealed partial class RuntimeNoMetadataNamedTypeInfo - { - internal static RuntimeNoMetadataNamedTypeInfo GetRuntimeNoMetadataNamedTypeInfo(RuntimeTypeHandle typeHandle, bool isGenericTypeDefinition) - { - RuntimeNoMetadataNamedTypeInfo type; - if (isGenericTypeDefinition) - type = GenericNoMetadataNamedTypeTable.Table.GetOrAdd(new RuntimeTypeHandleKey(typeHandle)); - else - type = NoMetadataNamedTypeTable.Table.GetOrAdd(new RuntimeTypeHandleKey(typeHandle)); - type.EstablishDebugName(); - return type; - } - - private sealed class NoMetadataNamedTypeTable : ConcurrentUnifierW - { - protected sealed override RuntimeNoMetadataNamedTypeInfo Factory(RuntimeTypeHandleKey key) - { - return new RuntimeNoMetadataNamedTypeInfo(key.TypeHandle, isGenericTypeDefinition: false); - } - - public static readonly NoMetadataNamedTypeTable Table = new NoMetadataNamedTypeTable(); - } - - private sealed class GenericNoMetadataNamedTypeTable : ConcurrentUnifierW - { - protected sealed override RuntimeNoMetadataNamedTypeInfo Factory(RuntimeTypeHandleKey key) - { - return new RuntimeNoMetadataNamedTypeInfo(key.TypeHandle, isGenericTypeDefinition: true); - } - - public static readonly GenericNoMetadataNamedTypeTable Table = new GenericNoMetadataNamedTypeTable(); - } - } - //----------------------------------------------------------------------------------------------------------- // TypeInfos that represent type definitions (i.e. Foo or Foo<>) or constructed generic types (Foo) // that can never be reflection-enabled due to the framework Reflection block. diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeMethodHelpers.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeMethodHelpers.cs index f3377c9c32ec2c..9ece9ba048a5c6 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeMethodHelpers.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeMethodHelpers.cs @@ -73,7 +73,7 @@ internal static string ComputeParametersString(RuntimeParameterInfo[] parameters { if (i != 0) sb.Append(", "); - string parameterTypeString = parameters[i].ParameterTypeString; + string parameterTypeString = parameters[i].ParameterType.FormatTypeNameForReflection(); // Legacy: Why use "ByRef" for by ref parameters? What language is this? // VB uses "ByRef" but it should precede (not follow) the parameter name. @@ -94,7 +94,7 @@ internal static string ComputeParametersString(RuntimeParameterInfo[] parameters internal static string ComputeToString(MethodBase contextMethod, RuntimeTypeInfo[] methodTypeArguments, RuntimeParameterInfo[] parameters, RuntimeParameterInfo returnParameter) { StringBuilder sb = new StringBuilder(30); - sb.Append(returnParameter == null ? "Void" : returnParameter.ParameterTypeString); // ConstructorInfos allowed to pass in null rather than craft a ReturnParameterInfo that's always of type void. + sb.Append(returnParameter == null ? "Void" : returnParameter.ParameterType.FormatTypeNameForReflection()); // ConstructorInfos allowed to pass in null rather than craft a ReturnParameterInfo that's always of type void. sb.Append(' '); sb.Append(contextMethod.Name); if (methodTypeArguments.Length != 0) @@ -105,9 +105,6 @@ internal static string ComputeToString(MethodBase contextMethod, RuntimeTypeInfo { sb.Append(sep); sep = ","; - string name = - methodTypeArgument.InternalNameIfAvailable ?? - Type.DefaultTypeNameWhenMissingMetadata; sb.Append(methodTypeArgument.Name); } sb.Append(']'); diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeNamedMethodInfo.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeNamedMethodInfo.cs index c64b56818aa3b4..6827850879b360 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeNamedMethodInfo.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeNamedMethodInfo.cs @@ -145,7 +145,7 @@ public sealed override MethodInfo MakeGenericMethod(params Type[] typeArguments) if (typeArguments.Length != GenericTypeParameters.Length) throw new ArgumentException(SR.Format(SR.Argument_NotEnoughGenArguments, typeArguments.Length, GenericTypeParameters.Length)); RuntimeMethodInfo methodInfo = (RuntimeMethodInfo)RuntimeConstructedGenericMethodInfo.GetRuntimeConstructedGenericMethodInfo(this, genericTypeArguments); - MethodInvoker _ = methodInfo.MethodInvoker; // For compatibility with other Make* apis, trigger any MissingMetadataExceptions now rather than later. + MethodInvoker _ = methodInfo.MethodInvoker; // For compatibility with other Make* apis, trigger any missing metadata exceptions now rather than later. return methodInfo; } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/ParameterInfos/RuntimeMethodParameterInfo.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/ParameterInfos/RuntimeMethodParameterInfo.cs index 19a8b8a40c8dbd..b146eadb260b99 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/ParameterInfos/RuntimeMethodParameterInfo.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/ParameterInfos/RuntimeMethodParameterInfo.cs @@ -36,14 +36,6 @@ public sealed override Type ParameterType } } - internal sealed override string ParameterTypeString - { - get - { - return QualifiedParameterTypeHandle.FormatTypeName(_typeContext); - } - } - protected readonly QSignatureTypeHandle QualifiedParameterTypeHandle; private readonly TypeContext _typeContext; private volatile Type _lazyParameterType; diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/ParameterInfos/RuntimeParameterInfo.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/ParameterInfos/RuntimeParameterInfo.cs index 24f628042880f9..2707ed7f41c27d 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/ParameterInfos/RuntimeParameterInfo.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/ParameterInfos/RuntimeParameterInfo.cs @@ -72,13 +72,9 @@ public sealed override int Position public sealed override string ToString() { - return this.ParameterTypeString + " " + this.Name; + return this.ParameterType.FormatTypeNameForReflection() + " " + this.Name; } - // Gets the ToString() output of ParameterType in a pay-to-play-safe way: Other Reflection ToString() methods should always use this rather than - // "ParameterType.ToString()". - internal abstract string ParameterTypeString { get; } - private readonly MemberInfo _member; private readonly int _position; } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/ParameterInfos/RuntimePropertyIndexParameterInfo.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/ParameterInfos/RuntimePropertyIndexParameterInfo.cs index 133da4c63e8096..8a2a1a2591d31a 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/ParameterInfos/RuntimePropertyIndexParameterInfo.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/ParameterInfos/RuntimePropertyIndexParameterInfo.cs @@ -87,14 +87,6 @@ public sealed override Type ParameterType } } - internal sealed override string ParameterTypeString - { - get - { - return _backingParameter.ParameterTypeString; - } - } - public sealed override int MetadataToken { get diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/ParameterInfos/RuntimeSyntheticParameterInfo.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/ParameterInfos/RuntimeSyntheticParameterInfo.cs index 2f68d703a80df3..8cd670f755967d 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/ParameterInfos/RuntimeSyntheticParameterInfo.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/ParameterInfos/RuntimeSyntheticParameterInfo.cs @@ -93,14 +93,6 @@ public sealed override int MetadataToken } } - internal sealed override string ParameterTypeString - { - get - { - return _parameterType.FormatTypeNameForReflection(); - } - } - private readonly RuntimeTypeInfo _parameterType; } } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/PropertyInfos/RuntimePropertyInfo.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/PropertyInfos/RuntimePropertyInfo.cs index 0c0a91beb36bb6..50ea6c7a219ae7 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/PropertyInfos/RuntimePropertyInfo.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/PropertyInfos/RuntimePropertyInfo.cs @@ -215,8 +215,7 @@ public sealed override string ToString() { StringBuilder sb = new StringBuilder(30); - TypeContext typeContext = ContextTypeInfo.TypeContext; - sb.Append(PropertyTypeHandle.FormatTypeName(typeContext)); + sb.Append(PropertyType.FormatTypeNameForReflection()); sb.Append(' '); sb.Append(this.Name); ParameterInfo[] indexParameters = this.GetIndexParameters(); diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/NativeFormat/NativeFormatRuntimeGenericParameterTypeInfo.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/NativeFormat/NativeFormatRuntimeGenericParameterTypeInfo.cs index b4789f8af68d17..fc45d8f992e069 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/NativeFormat/NativeFormatRuntimeGenericParameterTypeInfo.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/NativeFormat/NativeFormatRuntimeGenericParameterTypeInfo.cs @@ -58,11 +58,14 @@ protected sealed override int InternalGetHashCode() protected MetadataReader Reader { get; } - internal sealed override string? InternalGetNameIfAvailable(ref Type? rootCauseForFailure) + public sealed override string Name { - if (_genericParameter.Name.IsNull(Reader)) - return string.Empty; - return _genericParameter.Name.GetString(Reader); + get + { + if (_genericParameter.Name.IsNull(Reader)) + return string.Empty; + return _genericParameter.Name.GetString(Reader); + } } protected sealed override QTypeDefRefOrSpec[] Constraints diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/NativeFormat/NativeFormatRuntimeNamedTypeInfo.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/NativeFormat/NativeFormatRuntimeNamedTypeInfo.cs index 3e351f102360e9..fe54edb63ad300 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/NativeFormat/NativeFormatRuntimeNamedTypeInfo.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/NativeFormat/NativeFormatRuntimeNamedTypeInfo.cs @@ -168,12 +168,15 @@ internal sealed override string InternalFullNameOfAssembly } } - internal sealed override string? InternalGetNameIfAvailable(ref Type? rootCauseForFailure) + public sealed override string Name { - ConstantStringValueHandle nameHandle = _typeDefinition.Name; - string name = nameHandle.GetString(_reader); + get + { + ConstantStringValueHandle nameHandle = _typeDefinition.Name; + string name = nameHandle.GetString(_reader); - return name.EscapeTypeNameIdentifier(); + return name.EscapeTypeNameIdentifier(); + } } protected sealed override IEnumerable TrueCustomAttributes => RuntimeCustomAttributeData.GetCustomAttributes(_reader, _typeDefinition.CustomAttributes); diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeBlockedTypeInfo.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeBlockedTypeInfo.cs index 1e560f7f6991df..f3f0d11a40ac80 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeBlockedTypeInfo.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeBlockedTypeInfo.cs @@ -24,7 +24,7 @@ namespace System.Reflection.Runtime.TypeInfos // that can never be reflection-enabled due to the framework Reflection block. // // These types differ from NoMetadata TypeInfos in that properties that inquire about members, - // custom attributes or interfaces return an empty list rather than throwing a MissingMetadataException. + // custom attributes or interfaces return an empty list rather than throwing a missing metadata exception. // // Since these represent "internal framework types", the app cannot prove we are lying. // @@ -154,8 +154,6 @@ internal sealed override RuntimeNamedTypeInfo AnchoringTypeDefinitionForDeclared } } - internal sealed override bool CanBrowseWithoutMissingMetadataExceptions => true; - internal sealed override RuntimeTypeInfo[] RuntimeGenericTypeParameters { get @@ -172,9 +170,12 @@ internal sealed override Type InternalDeclaringType } } - internal sealed override string? InternalGetNameIfAvailable(ref Type? rootCauseForFailure) + public sealed override string Name { - return GeneratedName; + get + { + return GeneratedName; + } } internal sealed override string InternalFullNameOfAssembly diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeClsIdTypeInfo.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeClsIdTypeInfo.cs index 1c767450be9962..03a65e7156d88c 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeClsIdTypeInfo.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeClsIdTypeInfo.cs @@ -28,7 +28,7 @@ private RuntimeCLSIDTypeInfo(Guid clsid, string server) public sealed override bool ContainsGenericParameters => false; public sealed override string FullName => BaseType.FullName; public sealed override Guid GUID => _key.ClsId; - internal sealed override string? InternalGetNameIfAvailable(ref Type? rootCauseForFailure) => BaseType.InternalGetNameIfAvailable(ref rootCauseForFailure); + public sealed override string Name => BaseType.Name; public sealed override bool IsGenericTypeDefinition => false; public sealed override int MetadataToken => BaseType.MetadataToken; public sealed override string Namespace => BaseType.Namespace; @@ -56,7 +56,6 @@ public sealed override bool HasSameMetadataDefinitionAs(MemberInfo other) protected sealed override int InternalGetHashCode() => _key.GetHashCode(); internal sealed override Type BaseTypeWithoutTheGenericParameterQuirk => typeof(object); - internal sealed override bool CanBrowseWithoutMissingMetadataExceptions => BaseType.CastToRuntimeTypeInfo().CanBrowseWithoutMissingMetadataExceptions; internal sealed override Type InternalDeclaringType => null; internal sealed override string InternalFullNameOfAssembly => BaseType.Assembly.FullName; internal sealed override IEnumerable SyntheticConstructors => _constructors; diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeConstructedGenericTypeInfo.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeConstructedGenericTypeInfo.cs index 69779ae9b3ad84..aece6012b1dc74 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeConstructedGenericTypeInfo.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeConstructedGenericTypeInfo.cs @@ -170,26 +170,9 @@ public sealed override int MetadataToken public sealed override string ToString() { - // Get the FullName of the generic type definition in a pay-for-play safe way. - RuntimeTypeInfo genericTypeDefinition = GenericTypeDefinitionTypeInfo; - string? genericTypeDefinitionString = null; - if (genericTypeDefinition.InternalNameIfAvailable != null) // Want to avoid "cry-wolf" exceptions: if we can't even get the simple name, don't bother getting the FullName. - { - // Given our current pay for play policy, it should now be safe to attempt getting the FullName. (But guard with a try-catch in case this assumption is wrong.) - try - { - genericTypeDefinitionString = genericTypeDefinition.FullName; - } - catch (Exception) - { - } - } - // If all else fails, use the ToString() - it won't match the legacy CLR but with no metadata, we can't match it anyway. - genericTypeDefinitionString ??= genericTypeDefinition.ToString(); - // Now, append the generic type arguments. StringBuilder sb = new StringBuilder(); - sb.Append(genericTypeDefinitionString); + sb.Append(GenericTypeDefinitionTypeInfo.FullName); sb.Append('['); RuntimeTypeInfo[] genericTypeArguments = _key.GenericTypeArguments; for (int i = 0; i < genericTypeArguments.Length; i++) @@ -237,8 +220,6 @@ internal sealed override RuntimeNamedTypeInfo AnchoringTypeDefinitionForDeclared } } - internal sealed override bool CanBrowseWithoutMissingMetadataExceptions => GenericTypeDefinitionTypeInfo.CanBrowseWithoutMissingMetadataExceptions; - internal sealed override Type InternalDeclaringType { get @@ -258,9 +239,12 @@ internal sealed override string InternalFullNameOfAssembly } } - internal sealed override string? InternalGetNameIfAvailable(ref Type? rootCauseForFailure) + public sealed override string Name { - return GenericTypeDefinitionTypeInfo.InternalGetNameIfAvailable(ref rootCauseForFailure); + get + { + return GenericTypeDefinitionTypeInfo.Name; + } } internal sealed override RuntimeTypeInfo[] InternalRuntimeGenericTypeArguments diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeGenericParameterTypeInfo.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeGenericParameterTypeInfo.cs index 28f19623348ee9..387255917f24c8 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeGenericParameterTypeInfo.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeGenericParameterTypeInfo.cs @@ -116,8 +116,6 @@ protected sealed override TypeAttributes GetAttributeFlagsImpl() return TypeAttributes.Public; } - internal sealed override bool CanBrowseWithoutMissingMetadataExceptions => true; - internal sealed override string InternalFullNameOfAssembly { get diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeHasElementTypeInfo.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeHasElementTypeInfo.cs index 2c06872ac3c0f5..a1b30994ae51bb 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeHasElementTypeInfo.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeHasElementTypeInfo.cs @@ -152,8 +152,6 @@ protected sealed override int InternalGetHashCode() return _key.ElementType.GetHashCode(); } - internal sealed override bool CanBrowseWithoutMissingMetadataExceptions => true; - internal sealed override Type InternalDeclaringType { get @@ -162,15 +160,12 @@ internal sealed override Type InternalDeclaringType } } - internal sealed override string? InternalGetNameIfAvailable(ref Type? rootCauseForFailure) + public sealed override string Name { - string? elementTypeName = _key.ElementType.InternalGetNameIfAvailable(ref rootCauseForFailure); - if (elementTypeName == null) + get { - rootCauseForFailure = _key.ElementType; - return null; + return _key.ElementType.Name + Suffix; } - return elementTypeName + Suffix; } internal sealed override string InternalFullNameOfAssembly diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeNamedTypeInfo.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeNamedTypeInfo.cs index 1a4f49a8b41b26..4e96a263cc0c50 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeNamedTypeInfo.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeNamedTypeInfo.cs @@ -177,8 +177,6 @@ internal sealed override RuntimeNamedTypeInfo AnchoringTypeDefinitionForDeclared } } - internal sealed override bool CanBrowseWithoutMissingMetadataExceptions => true; - internal sealed override RuntimeTypeHandle InternalTypeHandleIfAvailable { get diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeNoMetadataNamedTypeInfo.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeNoMetadataNamedTypeInfo.cs deleted file mode 100644 index 7176f4901bc6b9..00000000000000 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeNoMetadataNamedTypeInfo.cs +++ /dev/null @@ -1,222 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System; -using System.Reflection; -using System.Diagnostics; -using System.Collections.Generic; -using System.Reflection.Runtime.General; -using System.Reflection.Runtime.TypeInfos; -using System.Reflection.Runtime.Assemblies; -using System.Reflection.Runtime.CustomAttributes; - -using Internal.LowLevelLinq; -using Internal.Reflection.Core.Execution; - -using StructLayoutAttribute = System.Runtime.InteropServices.StructLayoutAttribute; - -namespace System.Reflection.Runtime.TypeInfos -{ - // - // TypeInfos that represent type definitions (i.e. Foo or Foo<>, but not Foo or arrays/pointers/byrefs.) - // that not opted into pay-for-play metadata. - // - internal sealed partial class RuntimeNoMetadataNamedTypeInfo : RuntimeTypeDefinitionTypeInfo - { - private RuntimeNoMetadataNamedTypeInfo(RuntimeTypeHandle typeHandle, bool isGenericTypeDefinition) - { - _typeHandle = typeHandle; - _isGenericTypeDefinition = isGenericTypeDefinition; - } - - public sealed override Assembly Assembly - { - get - { - throw ReflectionCoreExecution.ExecutionDomain.CreateMissingMetadataException(this); - } - } - - public sealed override bool ContainsGenericParameters - { - get - { - return _isGenericTypeDefinition; - } - } - - public sealed override IEnumerable CustomAttributes - { - get - { - throw ReflectionCoreExecution.ExecutionDomain.CreateMissingMetadataException(this); - } - } - - public sealed override string FullName - { - get - { - throw ReflectionCoreExecution.ExecutionDomain.CreateMissingMetadataException(this); - } - } - - public sealed override Guid GUID - { - get - { - throw ReflectionCoreExecution.ExecutionDomain.CreateMissingMetadataException(this); - } - } - - public sealed override bool IsGenericTypeDefinition - { - get - { - return _isGenericTypeDefinition; - } - } - -#if DEBUG - public sealed override bool HasSameMetadataDefinitionAs(MemberInfo other) => base.HasSameMetadataDefinitionAs(other); -#endif - - public sealed override string Namespace - { - get - { - throw ReflectionCoreExecution.ExecutionDomain.CreateMissingMetadataException(this); - } - } - - public sealed override StructLayoutAttribute StructLayoutAttribute - { - get - { - throw ReflectionCoreExecution.ExecutionDomain.CreateMissingMetadataException(this); - } - } - - public sealed override string ToString() - { - return _typeHandle.LastResortString(); - } - - public sealed override int MetadataToken - { - get - { - throw new InvalidOperationException(SR.NoMetadataTokenAvailable); - } - } - - protected sealed override TypeAttributes GetAttributeFlagsImpl() - { - throw ReflectionCoreExecution.ExecutionDomain.CreateMissingMetadataException(this); - } - - protected sealed override int InternalGetHashCode() - { - return _typeHandle.GetHashCode(); - } - - // - // Returns the anchoring typedef that declares the members that this type wants returned by the Declared*** properties. - // The Declared*** properties will project the anchoring typedef's members by overriding their DeclaringType property with "this" - // and substituting the value of this.TypeContext into any generic parameters. - // - // Default implementation returns null which causes the Declared*** properties to return no members. - // - // Note that this does not apply to DeclaredNestedTypes. Nested types and their containers have completely separate generic instantiation environments - // (despite what C# might lead you to think.) Constructed generic types return the exact same same nested types that its generic type definition does - // - i.e. their DeclaringTypes refer back to the generic type definition, not the constructed generic type.) - // - // Note also that we cannot use this anchoring concept for base types because of generic parameters. Generic parameters return - // baseclass and interfaces based on its constraints. - // - internal sealed override RuntimeNamedTypeInfo AnchoringTypeDefinitionForDeclaredMembers - { - get - { - throw ReflectionCoreExecution.ExecutionDomain.CreateMissingMetadataException(this); - } - } - - internal sealed override bool CanBrowseWithoutMissingMetadataExceptions => false; - - internal sealed override Type InternalDeclaringType - { - get - { - throw ReflectionCoreExecution.ExecutionDomain.CreateMissingMetadataException(this); - } - } - - internal sealed override string? InternalGetNameIfAvailable(ref Type? rootCauseForFailure) - { - rootCauseForFailure = this; - return null; - } - - internal sealed override string InternalFullNameOfAssembly - { - get - { - throw ReflectionCoreExecution.ExecutionDomain.CreateMissingMetadataException(this); - } - } - - internal sealed override RuntimeTypeHandle InternalTypeHandleIfAvailable - { - get - { - return _typeHandle; - } - } - - internal sealed override RuntimeTypeInfo[] RuntimeGenericTypeParameters - { - get - { - throw ReflectionCoreExecution.ExecutionDomain.CreateMissingMetadataException(this); - } - } - - // - // Returns the base type as a typeDef, Ref, or Spec. Default behavior is to QTypeDefRefOrSpec.Null, which causes BaseType to return null. - // - internal sealed override QTypeDefRefOrSpec TypeRefDefOrSpecForBaseType - { - get - { - throw ReflectionCoreExecution.ExecutionDomain.CreateMissingMetadataException(this); - } - } - - // - // Returns the *directly implemented* interfaces as typedefs, specs or refs. ImplementedInterfaces will take care of the transitive closure and - // insertion of the TypeContext. - // - internal sealed override QTypeDefRefOrSpec[] TypeRefDefOrSpecsForDirectlyImplementedInterfaces - { - get - { - throw ReflectionCoreExecution.ExecutionDomain.CreateMissingMetadataException(this); - } - } - - // - // Returns the generic parameter substitutions to use when enumerating declared members, base class and implemented interfaces. - // - internal sealed override TypeContext TypeContext - { - get - { - throw ReflectionCoreExecution.ExecutionDomain.CreateMissingMetadataException(this); - } - } - - private readonly RuntimeTypeHandle _typeHandle; - private readonly bool _isGenericTypeDefinition; - } -} diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeInfo.CoreGetDeclared.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeInfo.CoreGetDeclared.cs index d97fada651f205..9ef282eae5bcd4 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeInfo.CoreGetDeclared.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeInfo.CoreGetDeclared.cs @@ -147,12 +147,4 @@ internal sealed override IEnumerable CoreGetDeclaredNestedTypes(NameFilter return Array.Empty(); } } - - internal sealed partial class RuntimeNoMetadataNamedTypeInfo - { - internal sealed override IEnumerable CoreGetDeclaredNestedTypes(NameFilter optionalNameFilter) - { - throw ReflectionCoreExecution.ExecutionDomain.CreateMissingMetadataException(this); - } - } } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeInfo.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeInfo.cs index 870740aaa4c2f3..909d0798c9dae0 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeInfo.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeInfo.cs @@ -53,6 +53,7 @@ protected RuntimeTypeInfo() public abstract override bool IsConstructedGenericType { get; } public abstract override bool IsByRefLike { get; } public sealed override bool IsCollectible => false; + public abstract override string Name { get; } public abstract override Assembly Assembly { get; } @@ -446,7 +447,7 @@ public sealed override Type MakeGenericType(params Type[] typeArguments) throw new InvalidOperationException(SR.Format(SR.Arg_NotGenericTypeDefinition, this)); // We intentionally don't validate the number of arguments or their suitability to the generic type's constraints. - // In a pay-for-play world, this can cause needless MissingMetadataExceptions. There is no harm in creating + // In a pay-for-play world, this can cause needless missing metadata exceptions. There is no harm in creating // the Type object for an inconsistent generic type - no MethodTable will ever match it so any attempt to "invoke" it // will throw an exception. bool foundSignatureType = false; @@ -501,18 +502,6 @@ public sealed override Type DeclaringType } } - public sealed override string Name - { - get - { - Type? rootCauseForFailure = null; - string? name = InternalGetNameIfAvailable(ref rootCauseForFailure); - if (name == null) - throw ReflectionCoreExecution.ExecutionDomain.CreateMissingMetadataException(rootCauseForFailure); - return name; - } - } - public sealed override Type ReflectedType { get @@ -612,8 +601,6 @@ internal virtual RuntimeNamedTypeInfo AnchoringTypeDefinitionForDeclaredMembers // internal abstract string InternalFullNameOfAssembly { get; } - internal abstract override string? InternalGetNameIfAvailable(ref Type? rootCauseForFailure); - // // Left unsealed as HasElement types must override this. // @@ -648,11 +635,6 @@ internal bool IsDelegate } } - // - // Returns true if it's possible to ask for a list of members and the base type without triggering a MissingMetadataException. - // - internal abstract bool CanBrowseWithoutMissingMetadataExceptions { get; } - // // The non-public version of TypeInfo.GenericTypeParameters (does not array-copy.) // diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/RuntimeExceptionHelpers.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/RuntimeExceptionHelpers.cs index e9d090b10c8e01..6d146348ee816d 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/RuntimeExceptionHelpers.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/RuntimeExceptionHelpers.cs @@ -211,7 +211,7 @@ public static void RuntimeFailFast(RhFailFastReason reason, Exception? exception } failFastMessage = string.Format("Runtime-generated FailFast: ({0}): {1}{2}", - reason.ToString(), // Explicit call to ToString() to avoid MissingMetadataException inside String.Format() + reason.ToString(), // Explicit call to ToString() to avoid missing metadata exception inside String.Format() GetStringForFailFastReason(reason), exception != null ? " [exception object available]" : ""); } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/RuntimeType.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/RuntimeType.cs index 719424c6faefd2..0422e7ba82e312 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/RuntimeType.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/RuntimeType.cs @@ -100,7 +100,7 @@ public sealed override Array GetEnumValues() Array values = Enum.GetEnumInfo(this).ValuesAsUnderlyingType; int count = values.Length; // Without universal shared generics, chances are slim that we'll have the appropriate - // array type available. Offer an escape hatch that avoids a MissingMetadataException + // array type available. Offer an escape hatch that avoids a missing metadata exception // at the cost of a small appcompat risk. Array result; if (AppContext.TryGetSwitch("Switch.System.Enum.RelaxedGetValues", out bool isRelaxed) && isRelaxed) diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Type.Internal.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Type.Internal.cs index 23d968e8608718..20df381cbb63b5 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Type.Internal.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Type.Internal.cs @@ -35,98 +35,33 @@ internal bool TryGetEEType(out EETypePtr eeType) return true; } - /// - /// Return Type.Name if sufficient metadata is available to do so - otherwise return null. - /// - public string? InternalNameIfAvailable - { - get - { - Type? ignore = null; - return InternalGetNameIfAvailable(ref ignore); - } - } - - /// - /// Return Type.Name if sufficient metadata is available to do so - otherwise return null and set "rootCauseForFailure" to an object to pass to MissingMetadataException. - /// - internal virtual string? InternalGetNameIfAvailable(ref Type? rootCauseForFailure) => Name; - - /// - /// Return Type.Name if sufficient metadata is available to do so - otherwise return a default (non-null) string. - /// - internal string NameOrDefault - { - get - { - return InternalNameIfAvailable ?? DefaultTypeNameWhenMissingMetadata; - } - } - - /// - /// Return Type.FullName if sufficient metadata is available to do so - otherwise return a default (non-null) string. - /// - internal string FullNameOrDefault - { - get - { - // First, see if Type.Name is available. If Type.Name is available, then we can be reasonably confident that it is safe to call Type.FullName. - // We'll still wrap the call in a try-catch as a failsafe. - if (InternalNameIfAvailable == null) - return DefaultTypeNameWhenMissingMetadata; - - try - { - return FullName; - } - catch (MissingMetadataException) - { - return DefaultTypeNameWhenMissingMetadata; - } - } - } - // // This is a port of the desktop CLR's RuntimeType.FormatTypeName() routine. This routine is used by various Reflection ToString() methods // to display the name of a type. Do not use for any other purpose as it inherits some pretty quirky desktop behavior. // - // The Project N version takes a raw metadata handle rather than a completed type so that it remains robust in the face of missing metadata. - // internal string FormatTypeNameForReflection() { - try + // Legacy: this doesn't make sense, why use only Name for nested types but otherwise + // ToString() which contains namespace. + Type rootElementType = this; + while (rootElementType.HasElementType) + rootElementType = rootElementType.GetElementType()!; + if (rootElementType.IsNested) { - // Though we wrap this in a try-catch as a failsafe, this code must still strive to avoid triggering MissingMetadata exceptions - // (non-error exceptions are very annoying when debugging.) - - // Legacy: this doesn't make sense, why use only Name for nested types but otherwise - // ToString() which contains namespace. - Type rootElementType = this; - while (rootElementType.HasElementType) - rootElementType = rootElementType.GetElementType()!; - if (rootElementType.IsNested) - { - return InternalNameIfAvailable ?? DefaultTypeNameWhenMissingMetadata; - } + return Name!; + } - // Legacy: why removing "System"? Is it just because C# has keywords for these types? - // If so why don't we change it to lower case to match the C# keyword casing? - string typeName = ToString(); - if (typeName.StartsWith("System.")) + // Legacy: why removing "System"? Is it just because C# has keywords for these types? + // If so why don't we change it to lower case to match the C# keyword casing? + string typeName = ToString(); + if (typeName.StartsWith("System.")) + { + if (rootElementType.IsPrimitive || rootElementType == typeof(void)) { - if (rootElementType.IsPrimitive || rootElementType == typeof(void)) - { - typeName = typeName.Substring("System.".Length); - } + typeName = typeName.Substring("System.".Length); } - return typeName; - } - catch (Exception) - { - return DefaultTypeNameWhenMissingMetadata; } + return typeName; } - - internal const string DefaultTypeNameWhenMissingMetadata = "UnknownType"; } } diff --git a/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ExecutionEnvironmentImplementation.MappingTables.cs b/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ExecutionEnvironmentImplementation.MappingTables.cs index b2e3c4a6ec5f01..3654c9c6fd12c9 100644 --- a/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ExecutionEnvironmentImplementation.MappingTables.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ExecutionEnvironmentImplementation.MappingTables.cs @@ -174,7 +174,7 @@ public sealed override unsafe bool TryGetNamedTypeForMetadata(QTypeDefinition qT /// Return the metadata handle for a TypeRef if this type was referenced indirectly by other type that pay-for-play has denoted as browsable /// (for example, as part of a method signature.) /// - /// This is only used in "debug" builds to provide better MissingMetadataException diagnostics. + /// This is only used in "debug" builds to provide better missing metadata diagnostics. /// /// Preconditions: /// runtimeTypeHandle is a typedef (not a constructed type such as an array or generic instance.) diff --git a/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/PayForPlayExperience/DiagnosticMappingTables.cs b/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/PayForPlayExperience/DiagnosticMappingTables.cs index eca67f2164b231..d49f576080a42e 100644 --- a/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/PayForPlayExperience/DiagnosticMappingTables.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/PayForPlayExperience/DiagnosticMappingTables.cs @@ -15,20 +15,11 @@ namespace Internal.Reflection.Execution.PayForPlayExperience { internal static partial class DiagnosticMappingTables { - // Get the diagnostic name string for a type. This attempts to reformat the string into something that is essentially human readable. + // Get the diagnostic name string for a type. // Returns true if the function is successful. // runtimeTypeHandle represents the type to get a name for // diagnosticName is the name that is returned - // - // the genericParameterOffsets list is an optional parameter that contains the list of the locations of where generic parameters may be inserted - // to make the string represent an instantiated generic. - // - // For example for Dictionary, metadata names the type Dictionary`2, but this function will return Dictionary<,> - // For consumers of this function that will be inserting generic arguments, the genericParameterOffsets list is used to find where to insert the generic parameter name. - // - // That isn't all that interesting for Dictionary, but it becomes substantially more interesting for nested generic types, or types which are compiler named as - // those may contain embedded <> pairs and such. - public static bool TryGetDiagnosticStringForNamedType(RuntimeTypeHandle runtimeTypeHandle, out string diagnosticName, List genericParameterOffsets) + public static bool TryGetDiagnosticStringForNamedType(RuntimeTypeHandle runtimeTypeHandle, out string diagnosticName) { diagnosticName = null; ExecutionEnvironmentImplementation executionEnvironment = ReflectionExecution.ExecutionEnvironment; @@ -37,30 +28,30 @@ public static bool TryGetDiagnosticStringForNamedType(RuntimeTypeHandle runtimeT TypeReferenceHandle typeReferenceHandle; if (executionEnvironment.TryGetTypeReferenceForNamedType(runtimeTypeHandle, out reader, out typeReferenceHandle)) { - diagnosticName = GetTypeFullNameFromTypeRef(typeReferenceHandle, reader, genericParameterOffsets); + diagnosticName = GetTypeFullNameFromTypeRef(typeReferenceHandle, reader); return true; } QTypeDefinition qTypeDefinition; if (executionEnvironment.TryGetMetadataForNamedType(runtimeTypeHandle, out qTypeDefinition)) { - TryGetFullNameFromTypeDefEcma(qTypeDefinition, genericParameterOffsets, ref diagnosticName); + TryGetFullNameFromTypeDefEcma(qTypeDefinition, ref diagnosticName); if (diagnosticName != null) return true; if (qTypeDefinition.IsNativeFormatMetadataBased) { TypeDefinitionHandle typeDefinitionHandle = qTypeDefinition.NativeFormatHandle; - diagnosticName = GetTypeFullNameFromTypeDef(typeDefinitionHandle, qTypeDefinition.NativeFormatReader, genericParameterOffsets); + diagnosticName = GetTypeFullNameFromTypeDef(typeDefinitionHandle, qTypeDefinition.NativeFormatReader); return true; } } return false; } - static partial void TryGetFullNameFromTypeDefEcma(QTypeDefinition qTypeDefinition, List genericParameterOffsets, ref string result); + static partial void TryGetFullNameFromTypeDefEcma(QTypeDefinition qTypeDefinition, ref string result); - private static string GetTypeFullNameFromTypeRef(TypeReferenceHandle typeReferenceHandle, MetadataReader reader, List genericParameterOffsets) + private static string GetTypeFullNameFromTypeRef(TypeReferenceHandle typeReferenceHandle, MetadataReader reader) { TypeReference typeReference = typeReferenceHandle.GetTypeReference(reader); string s = typeReference.TypeName.GetString(reader); @@ -68,8 +59,8 @@ private static string GetTypeFullNameFromTypeRef(TypeReferenceHandle typeReferen HandleType parentHandleType = parentHandle.HandleType; if (parentHandleType == HandleType.TypeReference) { - string containingTypeName = GetTypeFullNameFromTypeRef(parentHandle.ToTypeReferenceHandle(reader), reader, genericParameterOffsets); - s = containingTypeName + "." + s; + string containingTypeName = GetTypeFullNameFromTypeRef(parentHandle.ToTypeReferenceHandle(reader), reader); + s = containingTypeName + "+" + s; } else if (parentHandleType == HandleType.NamespaceReference) { @@ -92,40 +83,10 @@ private static string GetTypeFullNameFromTypeRef(TypeReferenceHandle typeReferen // If we got here, the metadata is illegal but this helper is for ToString() - better to // return something partial than throw. } - return ConvertBackTickNameToNameWithReducerInputFormat(s, genericParameterOffsets); + return s; } - public static string ConvertBackTickNameToNameWithReducerInputFormat(string typename, List genericParameterOffsets) - { - int indexOfBackTick = typename.LastIndexOf('`'); - if (indexOfBackTick != -1) - { - string typeNameSansBackTick = typename.Substring(0, indexOfBackTick); - if ((indexOfBackTick + 1) < typename.Length) - { - string textAfterBackTick = typename.Substring(indexOfBackTick + 1); - int genericParameterCount; - if (int.TryParse(textAfterBackTick, out genericParameterCount) && (genericParameterCount > 0)) - { - // Replace the `Number with <,,,> where the count of ',' is one less than Number. - StringBuilder genericTypeName = new StringBuilder(); - genericTypeName.Append(typeNameSansBackTick); - genericTypeName.Append('<'); - genericParameterOffsets?.Add(genericTypeName.Length); - for (int i = 1; i < genericParameterCount; i++) - { - genericTypeName.Append(','); - genericParameterOffsets?.Add(genericTypeName.Length); - } - genericTypeName.Append('>'); - return genericTypeName.ToString(); - } - } - } - return typename; - } - - private static string GetTypeFullNameFromTypeDef(TypeDefinitionHandle typeDefinitionHandle, MetadataReader reader, List genericParameterOffsets) + private static string GetTypeFullNameFromTypeDef(TypeDefinitionHandle typeDefinitionHandle, MetadataReader reader) { string s; @@ -135,8 +96,8 @@ private static string GetTypeFullNameFromTypeDef(TypeDefinitionHandle typeDefini TypeDefinitionHandle enclosingTypeDefHandle = typeDefinition.EnclosingType; if (!enclosingTypeDefHandle.IsNull(reader)) { - string containingTypeName = GetTypeFullNameFromTypeDef(enclosingTypeDefHandle, reader, genericParameterOffsets); - s = containingTypeName + "." + s; + string containingTypeName = GetTypeFullNameFromTypeDef(enclosingTypeDefHandle, reader); + s = containingTypeName + "+" + s; } else { @@ -154,19 +115,7 @@ private static string GetTypeFullNameFromTypeDef(TypeDefinitionHandle typeDefini namespaceHandle = namespaceDefinition.ParentScopeOrNamespace.ToNamespaceDefinitionHandle(reader); } } - return ConvertBackTickNameToNameWithReducerInputFormat(s, genericParameterOffsets); - } - - public static bool TryGetArrayTypeElementType(RuntimeTypeHandle arrayTypeHandle, out RuntimeTypeHandle elementTypeHandle) - { - elementTypeHandle = RuntimeAugments.GetRelatedParameterTypeHandle(arrayTypeHandle); - return true; - } - - public static bool TryGetPointerTypeTargetType(RuntimeTypeHandle pointerTypeHandle, out RuntimeTypeHandle targetTypeHandle) - { - targetTypeHandle = RuntimeAugments.GetRelatedParameterTypeHandle(pointerTypeHandle); - return true; + return s; } } } diff --git a/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/PayForPlayExperience/MissingMetadataExceptionCreator.cs b/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/PayForPlayExperience/MissingMetadataExceptionCreator.cs index ebe6da8349665a..54c485cd4b339a 100644 --- a/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/PayForPlayExperience/MissingMetadataExceptionCreator.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/PayForPlayExperience/MissingMetadataExceptionCreator.cs @@ -15,96 +15,51 @@ namespace Internal.Reflection.Execution.PayForPlayExperience { public static class MissingMetadataExceptionCreator { - internal static MissingMetadataException Create(string resourceId, MemberInfo? pertainant) - { - return CreateFromMetadataObject(resourceId, pertainant); - } - - internal static MissingMetadataException Create(TypeInfo? pertainant) + internal static NotSupportedException Create(Type? pertainant) { return CreateFromMetadataObject(SR.Reflection_InsufficientMetadata_EdbNeeded, pertainant); } - internal static MissingMetadataException Create(TypeInfo? pertainant, string nestedTypeName) + private static NotSupportedException CreateFromString(string? pertainant) { if (pertainant == null) - return new MissingMetadataException(SR.Format(SR.Reflection_InsufficientMetadata_NoHelpAvailable, "")); - - string usefulPertainant = ComputeUsefulPertainantIfPossible(pertainant); - if (usefulPertainant == null) - return new MissingMetadataException(SR.Format(SR.Reflection_InsufficientMetadata_NoHelpAvailable, pertainant.ToString())); + return new NotSupportedException(SR.Format(SR.Reflection_InsufficientMetadata_NoHelpAvailable, "")); else - { - usefulPertainant = usefulPertainant + "." + DiagnosticMappingTables.ConvertBackTickNameToNameWithReducerInputFormat(nestedTypeName, null); - return new MissingMetadataException(SR.Format(SR.Reflection_InsufficientMetadata_EdbNeeded, usefulPertainant)); - } + return new NotSupportedException(SR.Format(SR.Reflection_InsufficientMetadata_EdbNeeded, pertainant)); } - internal static MissingMetadataException Create(Type? pertainant) - { - return CreateFromMetadataObject(SR.Reflection_InsufficientMetadata_EdbNeeded, pertainant); - } - - internal static MissingMetadataException Create(RuntimeTypeHandle pertainant) - { - return CreateFromMetadataObject(SR.Reflection_InsufficientMetadata_EdbNeeded, pertainant); - } - - private static MissingMetadataException CreateFromString(string? pertainant) - { - if (pertainant == null) - return new MissingMetadataException(SR.Format(SR.Reflection_InsufficientMetadata_NoHelpAvailable, "")); - else - return new MissingMetadataException(SR.Format(SR.Reflection_InsufficientMetadata_EdbNeeded, pertainant)); - } - - internal static MissingMetadataException CreateMissingArrayTypeException(Type elementType, bool isMultiDim, int rank) + internal static NotSupportedException CreateMissingArrayTypeException(Type elementType, bool isMultiDim, int rank) { Debug.Assert(rank == 1 || isMultiDim); string s = CreateArrayTypeStringIfAvailable(elementType, rank); return CreateFromString(s); } - internal static MissingMetadataException CreateMissingConstructedGenericTypeException(Type genericTypeDefinition, Type[] genericTypeArguments) + internal static NotSupportedException CreateMissingConstructedGenericTypeException(Type genericTypeDefinition, Type[] genericTypeArguments) { string s = CreateConstructedGenericTypeStringIfAvailable(genericTypeDefinition, genericTypeArguments); return CreateFromString(s); } - internal static MissingMetadataException CreateFromMetadataObject(string resourceId, object? pertainant) + internal static NotSupportedException CreateFromMetadataObject(string resourceId, Type? pertainant) { if (pertainant == null) - return new MissingMetadataException(SR.Format(SR.Reflection_InsufficientMetadata_NoHelpAvailable, "")); + return new NotSupportedException(SR.Format(SR.Reflection_InsufficientMetadata_NoHelpAvailable, "")); - string usefulPertainant = ComputeUsefulPertainantIfPossible(pertainant); + string usefulPertainant = pertainant.ToDisplayStringIfAvailable(); if (usefulPertainant == null) - return new MissingMetadataException(SR.Format(SR.Reflection_InsufficientMetadata_NoHelpAvailable, pertainant.ToString())); + return new NotSupportedException(SR.Format(SR.Reflection_InsufficientMetadata_NoHelpAvailable, pertainant.ToString())); else - return new MissingMetadataException(SR.Format(resourceId, usefulPertainant)); + return new NotSupportedException(SR.Format(resourceId, usefulPertainant)); } - public static string ComputeUsefulPertainantIfPossible(object pertainant) + public static string ComputeUsefulPertainantIfPossible(MemberInfo memberInfo) { { - Type type = null; - - if (pertainant is TypeInfo) - type = ((TypeInfo)pertainant).AsType(); - else if (pertainant is Type) - type = (Type)pertainant; - else if (pertainant is RuntimeTypeHandle) - type = Type.GetTypeFromHandle((RuntimeTypeHandle)pertainant); - - if (type != null) - return type.ToDisplayStringIfAvailable(null); - } - - if (pertainant is MemberInfo memberInfo) - { - StringBuilder friendlyName = new StringBuilder(memberInfo.DeclaringType.ToDisplayStringIfAvailable(null)); + StringBuilder friendlyName = new StringBuilder(memberInfo.DeclaringType.ToDisplayStringIfAvailable()); friendlyName.Append('.'); friendlyName.Append(memberInfo.Name); - if (pertainant is MethodBase method) + if (memberInfo is MethodBase method) { bool first; @@ -112,16 +67,16 @@ public static string ComputeUsefulPertainantIfPossible(object pertainant) if (method.IsConstructedGenericMethod) { first = true; - friendlyName.Append('<'); + friendlyName.Append('['); foreach (Type genericParameter in method.GetGenericArguments()) { if (!first) friendlyName.Append(','); first = false; - friendlyName.Append(genericParameter.ToDisplayStringIfAvailable(null)); + friendlyName.Append(genericParameter.ToDisplayStringIfAvailable()); } - friendlyName.Append('>'); + friendlyName.Append(']'); } // write out actual parameters @@ -133,33 +88,16 @@ public static string ComputeUsefulPertainantIfPossible(object pertainant) friendlyName.Append(','); first = false; - if (parameter.IsOut && parameter.IsIn) - { - friendlyName.Append("ref "); - } - else if (parameter.IsOut) - { - friendlyName.Append("out "); - } - - Type parameterType = parameter.ParameterType; - if (parameterType.IsByRef) - { - parameterType = parameterType.GetElementType(); - } - - friendlyName.Append(parameter.ParameterType.ToDisplayStringIfAvailable(null)); + friendlyName.Append(parameter.ParameterType.ToDisplayStringIfAvailable()); } friendlyName.Append(')'); } return friendlyName.ToString(); } - - return null; //Give up } - internal static string ToDisplayStringIfAvailable(this Type type, List genericParameterOffsets) + internal static string ToDisplayStringIfAvailable(this Type type) { RuntimeTypeHandle runtimeTypeHandle = ReflectionCoreExecution.ExecutionDomain.GetTypeHandleIfAvailable(type); bool hasRuntimeTypeHandle = !runtimeTypeHandle.Equals(default(RuntimeTypeHandle)); @@ -178,7 +116,7 @@ internal static string ToDisplayStringIfAvailable(this Type type, List gene } else { - string s = type.GetElementType().ToDisplayStringIfAvailable(null); + string s = type.GetElementType().ToDisplayStringIfAvailable(); if (s == null) return null; return s + (type.IsPointer ? "*" : "&"); @@ -214,50 +152,20 @@ internal static string ToDisplayStringIfAvailable(this Type type, List gene else if (hasRuntimeTypeHandle) { string s; - if (!DiagnosticMappingTables.TryGetDiagnosticStringForNamedType(runtimeTypeHandle, out s, genericParameterOffsets)) + if (!DiagnosticMappingTables.TryGetDiagnosticStringForNamedType(runtimeTypeHandle, out s)) return null; return s; } else { - // First, see if Type.Name is available. If Type.Name is available, then we can be reasonably confident that it is safe to call Type.FullName. - // We'll still wrap the call in a try-catch as a failsafe. - string s = type.InternalNameIfAvailable; - if (s == null) - return null; - - try - { - s = type.FullName; - } - catch (MissingMetadataException) - { - } - - // Insert commas so that CreateConstructedGenericTypeStringIfAvailable can fill the blanks. - // This is not strictly correct for types nested under generic types, but at this point we're doing - // best effort within reason. - if (type.IsGenericTypeDefinition) - { - s += "["; - int genericArgCount = type.GetGenericArguments().Length; - while (genericArgCount-- > 0) - { - genericParameterOffsets.Add(s.Length); - if (genericArgCount > 0) - s += ","; - } - s += "]"; - } - - return s; + return type.FullName; } } private static string CreateArrayTypeStringIfAvailable(Type elementType, int rank) { - string s = elementType.ToDisplayStringIfAvailable(null); + string s = elementType.ToDisplayStringIfAvailable(); if (s == null) return null; @@ -266,38 +174,22 @@ private static string CreateArrayTypeStringIfAvailable(Type elementType, int ran private static string CreateConstructedGenericTypeStringIfAvailable(Type genericTypeDefinition, Type[] genericTypeArguments) { - List genericParameterOffsets = new List(); - string genericTypeDefinitionString = genericTypeDefinition.ToDisplayStringIfAvailable(genericParameterOffsets); + string genericTypeDefinitionString = genericTypeDefinition.ToDisplayStringIfAvailable(); if (genericTypeDefinitionString == null) return null; - // If we found too many generic arguments to insert things, strip out the excess. This is wrong, but also, nothing is right. - if (genericTypeArguments.Length < genericParameterOffsets.Count) - { - genericParameterOffsets.RemoveRange(genericTypeArguments.Length, genericParameterOffsets.Count - genericTypeArguments.Length); - } - // Similarly, if we found too few, add them at the end. - while (genericTypeArguments.Length > genericParameterOffsets.Count) - { - genericTypeDefinitionString += ","; - genericParameterOffsets.Add(genericTypeDefinitionString.Length); - } - - // Ensure the list is sorted in ascending order - genericParameterOffsets.Sort(); - - // The s string Now contains a string like "Namespace.MoreNamespace.TypeName.NestedGenericType<,,>.MoreNestedGenericType<>" - // where the generic parameters locations are recorded in genericParameterOffsets - // Walk backwards through the generic parameter locations, filling in as needed. StringBuilder genericTypeName = new StringBuilder(genericTypeDefinitionString); - for (int i = genericParameterOffsets.Count - 1; i >= 0; --i) + genericTypeName.Append('['); + for (int i = 0; i < genericTypeArguments.Length; i++) { - genericTypeName.Insert(genericParameterOffsets[i], genericTypeArguments[i].ToDisplayStringIfAvailable(null)); + if (i > 0) + genericTypeName.Append(", "); + genericTypeName.Append(genericTypeArguments[i].ToDisplayStringIfAvailable()); } + genericTypeName.Append(']'); return genericTypeName.ToString(); } - } } diff --git a/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ReflectionDomainSetupImplementation.cs b/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ReflectionDomainSetupImplementation.cs index 143dbf0b2011e7..73506680de2b4a 100644 --- a/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ReflectionDomainSetupImplementation.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ReflectionDomainSetupImplementation.cs @@ -21,21 +21,11 @@ public ReflectionDomainSetupImplementation() // Obtain it lazily to avoid using RuntimeAugments.Callbacks before it is initialized public sealed override AssemblyBinder AssemblyBinder => AssemblyBinderImplementation.Instance; - public sealed override Exception CreateMissingMetadataException(TypeInfo pertainant) - { - return MissingMetadataExceptionCreator.Create(pertainant); - } - public sealed override Exception CreateMissingMetadataException(Type pertainant) { return MissingMetadataExceptionCreator.Create(pertainant); } - public sealed override Exception CreateMissingMetadataException(TypeInfo pertainant, string nestedTypeName) - { - return MissingMetadataExceptionCreator.Create(pertainant, nestedTypeName); - } - public sealed override Exception CreateNonInvokabilityException(MemberInfo pertainant) { string resourceName = SR.Object_NotInvokable; @@ -52,7 +42,7 @@ public sealed override Exception CreateNonInvokabilityException(MemberInfo perta } string pertainantString = MissingMetadataExceptionCreator.ComputeUsefulPertainantIfPossible(pertainant); - return new MissingMetadataException(SR.Format(resourceName, pertainantString ?? "?")); + return new NotSupportedException(SR.Format(resourceName, pertainantString ?? "?")); } public sealed override Exception CreateMissingArrayTypeException(Type elementType, bool isMultiDim, int rank) diff --git a/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ReflectionExecutionDomainCallbacksImplementation.cs b/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ReflectionExecutionDomainCallbacksImplementation.cs index a7941c10e01941..bea0d44a506cc5 100644 --- a/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ReflectionExecutionDomainCallbacksImplementation.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ReflectionExecutionDomainCallbacksImplementation.cs @@ -80,7 +80,7 @@ public sealed override Type GetConstructedGenericTypeForHandle(RuntimeTypeHandle } //======================================================================================= - // MissingMetadataException support. + // Missing metadata exception support. //======================================================================================= public sealed override Exception CreateMissingMetadataException(Type pertainant) { @@ -91,7 +91,7 @@ public sealed override Exception CreateMissingMetadataException(Type pertainant) // This helper makes a "best effort" to give the caller something better than "EETypePtr nnnnnnnnn". public sealed override string GetBetterDiagnosticInfoIfAvailable(RuntimeTypeHandle runtimeTypeHandle) { - return Type.GetTypeFromHandle(runtimeTypeHandle).ToDisplayStringIfAvailable(null); + return Type.GetTypeFromHandle(runtimeTypeHandle).ToDisplayStringIfAvailable(); } public sealed override MethodBase GetMethodBaseFromStartAddressIfAvailable(IntPtr methodStartAddress) diff --git a/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Extensions/NonPortable/DelegateMethodInfoRetriever.cs b/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Extensions/NonPortable/DelegateMethodInfoRetriever.cs index 68cbc9f19918bd..100ba63e959c39 100644 --- a/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Extensions/NonPortable/DelegateMethodInfoRetriever.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Extensions/NonPortable/DelegateMethodInfoRetriever.cs @@ -29,7 +29,7 @@ public static MethodInfo GetDelegateMethodInfo(Delegate del) // This is a special kind of delegate where the invoke method is "ObjectArrayThunk". Typically, // this will be a delegate that points the LINQ Expression interpreter. We could manufacture // a MethodInfo based on the delegate's Invoke signature, but let's just throw for now. - throw new PlatformNotSupportedException(SR.DelegateGetMethodInfo_ObjectArrayDelegate); + throw new NotSupportedException(SR.DelegateGetMethodInfo_ObjectArrayDelegate); } if (originalLdFtnResult == (IntPtr)0) @@ -64,7 +64,7 @@ public static MethodInfo GetDelegateMethodInfo(Delegate del) methodHandle = QMethodDefinition.FromObjectAndInt(resolver->Reader, resolver->Handle); if (!TypeLoaderEnvironment.Instance.TryGetRuntimeMethodHandleComponents(resolver->GVMMethodHandle, out _, out _, out genericMethodTypeArgumentHandles)) - throw new MissingMetadataException(SR.DelegateGetMethodInfo_NoInstantiation); + throw new NotSupportedException(SR.DelegateGetMethodInfo_NoInstantiation); } } } @@ -77,9 +77,9 @@ public static MethodInfo GetDelegateMethodInfo(Delegate del) string methodDisplayString = RuntimeAugments.TryGetMethodDisplayStringFromIp(ip); if (methodDisplayString == null) - throw new MissingMetadataException(SR.DelegateGetMethodInfo_NoDynamic); + throw new NotSupportedException(SR.DelegateGetMethodInfo_NoDynamic); else - throw new MissingMetadataException(SR.Format(SR.DelegateGetMethodInfo_NoDynamic_WithDisplayString, methodDisplayString)); + throw new NotSupportedException(SR.Format(SR.DelegateGetMethodInfo_NoDynamic_WithDisplayString, methodDisplayString)); } } MethodBase methodBase = ReflectionCoreExecution.ExecutionDomain.GetMethod(typeOfFirstParameterIfInstanceDelegate, methodHandle, genericMethodTypeArgumentHandles); diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.Metadata.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.Metadata.cs index 7c619907610f79..367ff35a59f0af 100644 --- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.Metadata.cs +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.Metadata.cs @@ -106,7 +106,7 @@ internal static unsafe NativeReader GetNativeReaderForBlob(NativeFormatModuleInf /// Return the metadata handle for a TypeRef if this type was referenced indirectly by other type that pay-for-play has denoted as browsable /// (for example, as part of a method signature.) /// - /// This is only used in "debug" builds to provide better MissingMetadataException diagnostics. + /// This is only used in "debug" builds to provide better diagnostics when metadata is missing. /// /// Preconditions: /// runtimeTypeHandle is a typedef (not a constructed type such as an array or generic instance.) diff --git a/src/tests/nativeaot/SmokeTests/Reflection/Reflection.cs b/src/tests/nativeaot/SmokeTests/Reflection/Reflection.cs index 676f4e457ed420..02c66ce71430c0 100644 --- a/src/tests/nativeaot/SmokeTests/Reflection/Reflection.cs +++ b/src/tests/nativeaot/SmokeTests/Reflection/Reflection.cs @@ -1620,7 +1620,7 @@ public static void Run() { message1 = ex.Message; } - if (!message1.Contains("ReflectionTest.TypeConstructionTest.Gen")) + if (!message1.Contains("ReflectionTest+TypeConstructionTest+Gen`1[ReflectionTest+TypeConstructionTest+Atom]")) throw new Exception(); string message2 = ""; @@ -1632,7 +1632,7 @@ public static void Run() { message2 = ex.Message; } - if (!message2.Contains("ReflectionTest.TypeConstructionTest.Atom[]")) + if (!message2.Contains("ReflectionTest+TypeConstructionTest+Atom[]")) throw new Exception(); string message3 = ""; @@ -1644,7 +1644,7 @@ public static void Run() { message3 = ex.Message; } - if (!message3.Contains("ReflectionTest.TypeConstructionTest.Atom[]")) + if (!message3.Contains("ReflectionTest+TypeConstructionTest+Atom[]")) throw new Exception(); } }