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

Conversation

Venkad000
Copy link
Contributor

In Mono, calling IsCollectible on a Type was returned True, whereas in CoreCLR it returned False for the same scenario. This discrepancy was caused by a missing override of IsCollectible in the RuntimeType class in Mono.

The discrepancy could also be seen here link

@github-actions github-actions bot added the needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners label May 20, 2025
@dotnet-policy-service dotnet-policy-service bot added the community-contribution Indicates that the PR has been added by a community member label May 20, 2025
@Venkad000
Copy link
Contributor Author

@saitama951
Copy link
Contributor

cc: @nealef

@@ -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 => RuntimeTypeHandle.GetAssembly(this)!.IsCollectible;
Copy link
Member

Choose a reason for hiding this comment

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

Should this just return false given that collectible assemblies are not implemented in Mono?

This is not a correct implementation in case collectible assemblies were ever implemented in Mono. Correct implementation would have to take into account all generic instantiation arguments.

@jkotas
Copy link
Member

jkotas commented May 20, 2025

Does MethodInfo, etc. have the same bug? If I am reading the code correctly, the following program is going to print true on Mono:

public class Program
{
    public static void Main() { Console.WriteLine(typeof(Program).GetMethod("Main").IsCollectible); }
}

We have a lot of advanced tests for collectible property that are disabled on Mono, but we are missing the basic ones. Could you please add some basic tests
https://github.com/dotnet/runtime/blob/main/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Reflection/IsCollectibleTests.cs ? Something like:

public class BasicIsCollectibleTests
{
    [Fact]
    public void CoreLib_IsCollectibleFalse
    {
        Assert.False(typeof(object).IsCollectible);
        Assert.False(typeof(object).Assembly.IsCollectible);
        Assert.False(typeof(object).GetMethod("ToString).IsCollectible);
        Assert.False(typeof(object).GetConstructor(Types.Empty).IsCollectible);
        Assert.False(typeof(IntPtr).GetField("Zero").IsCollectible);
        Assert.False(typeof(IntPtr).GetProperty("Zero").IsCollectible);
        Assert.False(typeof(AppDomain).GetEvent("ProcessExit").IsCollectible);
   }
}

@jkotas jkotas added area-System.Reflection and removed needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners labels May 21, 2025
Copy link
Contributor

Tagging subscribers to this area: @dotnet/area-system-reflection
See info in area-owners.md if you want to be subscribed.

@Venkad000
Copy link
Contributor Author

Yes, MethodInfo and PropertyInfo too have differing values. They are true in Mono but are false in CoreCLR.
Unless an assembly is loaded via a custom AssemblyLoadContext with isCollectible: true, it is always going to have IsCollectible as False right?

@jkotas
Copy link
Member

jkotas commented May 21, 2025

Yes, that's correct on CoreCLR.

Mono does not support collectible assemblies. isCollectible: true is ignored on Mono. The easiest way to fix this issue on Mono is to unconditionally return false from IsCollectible properties of runtime provided reflection types.

@Venkad000
Copy link
Contributor Author

Venkad000 commented May 22, 2025

@dotnet-policy-service agree company="IBM"

@Venkad000
Copy link
Contributor Author

@dotnet-policy-service agree company="IBM"

@jkotas
Copy link
Member

jkotas commented May 22, 2025

It turns out NativeAOT has the same bug. Could you please add overrides bool IsCollectible => false for NativeAOT to make the new test to pass on NativeAOT?

A good place to add them is:

internal abstract partial class RuntimeConstructorInfo
{
public sealed override MethodImplAttributes GetMethodImplementationFlags() => MethodImplementationFlags;
// Partial trust doesn't exist in Aot so these legacy apis are meaningless. Will report everything as SecurityCritical by fiat.
public sealed override bool IsSecurityCritical => true;
public sealed override bool IsSecuritySafeCritical => false;
public sealed override bool IsSecurityTransparent => false;
}
}
namespace System.Reflection.Runtime.EventInfos
{
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);
}
}
namespace System.Reflection.Runtime.MethodInfos
{
internal abstract partial class RuntimeMethodInfo
{
public sealed override MethodImplAttributes GetMethodImplementationFlags() => MethodImplementationFlags;
public sealed override ICustomAttributeProvider ReturnTypeCustomAttributes => ReturnParameter;
// Partial trust doesn't exist in Aot so these legacy apis are meaningless. Will report everything as SecurityCritical by fiat.
public sealed override bool IsSecurityCritical => true;
public sealed override bool IsSecuritySafeCritical => false;
public sealed override bool IsSecurityTransparent => false;
}
}
namespace System.Reflection.Runtime.PropertyInfos
{
internal abstract partial class RuntimePropertyInfo
{

@jkotas
Copy link
Member

jkotas commented May 23, 2025

The new test is still failing on NAOT. I have pushed a fix to add missing FieldInfo override for NAOT.

@Venkad000
Copy link
Contributor Author

Thank you!

@jkotas
Copy link
Member

jkotas commented May 24, 2025

/ba-g Known issue #115955

Copy link
Member

@jkotas jkotas left a comment

Choose a reason for hiding this comment

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

Thank you!

@jkotas jkotas merged commit 6944091 into dotnet:main May 24, 2025
134 of 140 checks passed
@Venkad000 Venkad000 deleted the new_branch branch May 26, 2025 05:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-System.Reflection community-contribution Indicates that the PR has been added by a community member
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants