Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Accessing constructors with UnsafeAccessor throws exception on generic types in .NET9 #104879

Closed
yushroom opened this issue Jul 15, 2024 · 5 comments

Comments

@yushroom
Copy link

yushroom commented Jul 15, 2024

Description

Accessing constructors with UnsafeAccessor throws exception on generic types in .NET9 preview 6.

Reproduction Steps

using System.Runtime.CompilerServices;

class Program
{
    static List<int> CallConstructorByUnsafeAccessor()
    {
        var c = (List<int>)RuntimeHelpers.GetUninitializedObject(typeof(List<int>));
        CtorAsMethod(c);
        return c;

        [UnsafeAccessor(UnsafeAccessorKind.Method, Name = ".ctor")]
        extern static void CtorAsMethod(List<int> c);
    }

    static void Main()
    {
        var c = CallConstructorByUnsafeAccessor();
        Console.WriteLine(c.Count);
    }
}

Expected behavior

The code works on .NET 8 and .NET 9

Actual behavior

  • No error on .NET 8
  • Fails on .NET 9 preview 6

Unhandled exception. System.InvalidProgramException: Generic type constraints do not match.

Also fails with NativeAOT

dotnet publish -r win-x64 -c Debug /p:PublishAot=true

EXEC : error : Index was outside the bounds of the array.

Regression?

Yes as it works on .NET 8

Known Workarounds

No response

Configuration

No response

Other information

No response

@dotnet-issue-labeler dotnet-issue-labeler bot added the needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners label Jul 15, 2024
@dotnet-policy-service dotnet-policy-service bot added the untriaged New issue has not been triaged by the area owner label Jul 15, 2024
@jkotas
Copy link
Member

jkotas commented Jul 15, 2024

cc @AaronRobinsonMSFT

@vcsjones vcsjones added area-System.Runtime.CompilerServices and removed needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners labels Jul 15, 2024
Copy link
Contributor

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

@AaronRobinsonMSFT
Copy link
Member

So most generic support was deemed broken in .NET 8. I tried to capture that in #89439. It clearly wasn't properly expressed nor was the fact that generic parameters now must match in location and number. The documentation for UnsafeAccessor was recently updated specifically talking about generics.

For context, this was part of type parameters must be type parameters and method parameters must be method parameters so signature matching was simpler. The result is that we match signatures precisely. For the above scenario it is relatively simple and we could make it work, but it quickly becomes much more complicated when generic parameters are involved. I'm inclined to report a breaking change issue here for .NET 8 instead.

The workaround is to follow the supported generic way to handle this:

    static List<int> CallConstructorByUnsafeAccessor()
    {
        var c = (List<int>)RuntimeHelpers.GetUninitializedObject(typeof(List<int>));
        Accessor<int>.CtorAsMethod(c);
        return c;
    }

    class Accessor<T>
    {
        [UnsafeAccessor(UnsafeAccessorKind.Method, Name = ".ctor")]
        public extern static void CtorAsMethod(List<T> c);
    }

    static void Main(string[] args)
    {
        var c = CallConstructorByUnsafeAccessor();
        Console.WriteLine(c.Count);
    }

@AaronRobinsonMSFT
Copy link
Member

I'm inclined to report a breaking change issue here for .NET 8 instead.

Re-reading through the history of the original feature PR, specifically here, this sounds like this could be considered a bug. I genuinely don't think that is fair so think a breaking change issue is more appropriate because it wasn't blocked in .NET 8.

@AaronRobinsonMSFT AaronRobinsonMSFT added this to the 9.0.0 milestone Jul 15, 2024
@AaronRobinsonMSFT
Copy link
Member

After some additional discussion, we've decide to document this as a breaking change. It can be tracked at dotnet/docs#41769.

@dotnet-policy-service dotnet-policy-service bot removed the untriaged New issue has not been triaged by the area owner label Jul 16, 2024
@github-actions github-actions bot locked and limited conversation to collaborators Aug 15, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

4 participants