Skip to content

Added an override for IsCollectible in RuntimeType to fix inconsistency between Mono and CoreCLR #115785

New issue

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

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

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
May 24, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -173,6 +173,7 @@ public override IList<CustomAttributeData> GetCustomAttributesData()
internal RuntimeType GetRuntimeType() { return m_declaringType; }
internal RuntimeModule GetRuntimeModule() { return RuntimeTypeHandle.GetModule(m_declaringType); }
internal RuntimeAssembly GetRuntimeAssembly() { return GetRuntimeModule().GetRuntimeAssembly(); }
public override bool IsCollectible => m_declaringType.IsCollectible;
#endregion

#region MethodBase Overrides
Original file line number Diff line number Diff line change
@@ -129,6 +129,7 @@ public override IList<CustomAttributeData> GetCustomAttributesData()
public override int MetadataToken => m_token;
public override Module Module => GetRuntimeModule();
internal RuntimeModule GetRuntimeModule() { return m_declaringType.GetRuntimeModule(); }
public override bool IsCollectible => m_declaringType.IsCollectible;
#endregion

#region EventInfo Overrides
Original file line number Diff line number Diff line change
@@ -95,6 +95,8 @@ internal abstract partial class RuntimeConstructorInfo
public sealed override bool IsSecurityCritical => true;
public sealed override bool IsSecuritySafeCritical => false;
public sealed override bool IsSecurityTransparent => false;

public sealed override bool IsCollectible => false;
}
}

@@ -105,6 +107,8 @@ internal abstract partial class RuntimeEventInfo
public sealed override MethodInfo GetAddMethod(bool nonPublic) => AddMethod.FilterAccessor(nonPublic);
public sealed override MethodInfo GetRemoveMethod(bool nonPublic) => RemoveMethod.FilterAccessor(nonPublic);
public sealed override MethodInfo GetRaiseMethod(bool nonPublic) => RaiseMethod?.FilterAccessor(nonPublic);

public sealed override bool IsCollectible => false;
}
}

@@ -119,6 +123,16 @@ internal abstract partial class RuntimeMethodInfo
public sealed override bool IsSecurityCritical => true;
public sealed override bool IsSecuritySafeCritical => false;
public sealed override bool IsSecurityTransparent => false;

public sealed override bool IsCollectible => false;
}
}

namespace System.Reflection.Runtime.FieldInfos
{
internal abstract partial class RuntimeFieldInfo
{
public sealed override bool IsCollectible => false;
}
}

@@ -145,6 +159,8 @@ public sealed override MethodInfo[] GetAccessors(bool nonPublic)
accessors[index++] = setter;
return accessors;
}

public sealed override bool IsCollectible => false;
}
}

Original file line number Diff line number Diff line change
@@ -17,6 +17,40 @@ public TestAssemblyLoadContext() : base(true) {}
protected override Assembly Load(AssemblyName assemblyName) => null;
}

public class BasicIsCollectibleTests
{
[Fact]
public void CoreLib_IsCollectibleFalse()
{
Assert.False(typeof(object).IsCollectible);
Assert.False(typeof(Console).Assembly.IsCollectible);
Assert.False(typeof(Math).Assembly.IsCollectible);
Assert.False(typeof(string).Assembly.IsCollectible);
Assert.False(typeof(List<>).Assembly.IsCollectible);
Assert.False(typeof(object).Assembly.IsCollectible);
Assert.False(typeof(IDisposable).Assembly.IsCollectible);
Assert.False(typeof(Span<>).Assembly.IsCollectible);
Assert.False(typeof(Enumerable).Assembly.IsCollectible);
Assert.False(typeof(string).GetMethods().First(m => m.Name == "Substring" && m.GetParameters().Length == 1).IsCollectible);
Assert.False(typeof(Dictionary<,>).Assembly.IsCollectible);
Assert.False(typeof(object).GetMethod("ToString").IsCollectible);
Assert.False(typeof(string).GetMethod("Contains", new[] { typeof(string) }).IsCollectible);
Assert.False(typeof(IntPtr).GetField("Zero").IsCollectible);
Assert.False(typeof(IntPtr).GetProperty("MaxValue").IsCollectible);
Assert.False(typeof(IntPtr).GetProperty("MinValue").IsCollectible);
Assert.False(typeof(DateTime).GetProperty("Now").IsCollectible);
Assert.False(typeof(AppDomain).GetMethod("GetData").IsCollectible);
Assert.False(typeof(AppDomain).GetMethod("ToString").IsCollectible);
Assert.False(typeof(string).GetConstructor(new[] { typeof(char[]), typeof(int), typeof(int) })!.IsCollectible);
Assert.False(typeof(string).GetConstructor(new[] { typeof(char), typeof(int) })!.IsCollectible);
Assert.False(typeof(TimeSpan).GetConstructor(new[] { typeof(int), typeof(int), typeof(int) })!.IsCollectible);
Assert.False(typeof(Uri).GetConstructor(new[] { typeof(string) })!.IsCollectible);
Assert.False(typeof(AppDomain).GetEvent("AssemblyLoad")!.IsCollectible);
Assert.False(typeof(AppDomain).GetEvent("ProcessExit")!.IsCollectible);

}
}

[ActiveIssue("https://github.com/mono/mono/issues/15142", TestRuntimes.Mono)]
public class IsCollectibleTests
{
Original file line number Diff line number Diff line change
@@ -87,6 +87,8 @@ internal RuntimeModule GetRuntimeModule()
return GetDeclaringTypeInternal().GetRuntimeModule();
}

public override bool IsCollectible => false;

internal BindingFlags GetBindingFlags()
{
MonoEventInfo info = GetEventInfo(this);
Original file line number Diff line number Diff line change
@@ -69,6 +69,8 @@ internal RuntimeModule GetRuntimeModule()
return GetDeclaringTypeInternal().GetRuntimeModule();
}

public override bool IsCollectible => false;

[MethodImplAttribute(MethodImplOptions.InternalCall)]
internal extern override object UnsafeGetValue(object obj);

Original file line number Diff line number Diff line change
@@ -181,6 +181,8 @@ public override Module Module
}
}

public override bool IsCollectible => false;

private string FormatNameAndSig()
{
// Serialization uses ToString to resolve MethodInfo overloads.
@@ -747,6 +749,8 @@ public override Module Module
}
}

public override bool IsCollectible => false;

internal RuntimeModule GetRuntimeModule()
{
return RuntimeTypeHandle.GetModule((RuntimeType)DeclaringType);
Original file line number Diff line number Diff line change
@@ -136,6 +136,8 @@ internal RuntimeModule GetRuntimeModule()
return GetDeclaringTypeInternal().GetRuntimeModule();
}

public override bool IsCollectible => false;

#region Object Overrides
public override string ToString()
{
Original file line number Diff line number Diff line change
@@ -1327,6 +1327,8 @@ protected override bool IsValueTypeImpl()
// Returns true for generic parameters with the Enum constraint.
public override bool IsEnum => GetBaseType() == EnumType;

public override bool IsCollectible => false;

// Returns true for actual enum types only, ignoring generic parameter constraints.
internal bool IsActualEnum
{
Loading
Oops, something went wrong.