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

[CoreCLR and native AOT] UnsafeAccessorAttribute supports generic parameters #99468

Merged

Conversation

AaronRobinsonMSFT
Copy link
Member

@AaronRobinsonMSFT AaronRobinsonMSFT commented Mar 8, 2024

Support in CoreCLR and native AOT.

Contributes to #89439

The behavior expects type parameters to be supplied from a type and method generic parameters supplied from method declaration. Examples below. See also tests in PR.

// Target class has no generic type parameters
class Accessors
{
    // class B
    // {
    //     private T M<T>(T arg);
    // }
    [UnsafeAccessor(UnsafeAccessorKind.Method, Name = "M")]
    public extern static T CallM<T>(B b, T t);
}

// Target class has generic type parameters
class Accessors<T>
{
    [UnsafeAccessor(UnsafeAccessorKind.Field, Name = "_items")]
    public extern static ref T[] GetItems(List<T> list);

    [UnsafeAccessor(UnsafeAccessorKind.StaticField, Name = "s_emptyArray")]
    public extern static ref T[] GetEmptyArray(List<T> list);

    // Case where a type parameter and method parameter both exist.
    // class C<T>
    // {
    //     private U M<U>(U arg);
    // }
    [UnsafeAccessor(UnsafeAccessorKind.Method, Name = "M")]
    public extern static U CallM<U>(C<T> c, U arg);
}

Instance and static fields on generic types
Re-enable and add to field tests
Generic types with non-generic methods.
Update tests
@AaronRobinsonMSFT
Copy link
Member Author

@AaronRobinsonMSFT AaronRobinsonMSFT marked this pull request as ready for review March 9, 2024 20:37
@AaronRobinsonMSFT
Copy link
Member Author

/azp list

Copy link

CI/CD Pipelines for this repository:

@AaronRobinsonMSFT
Copy link
Member Author

/azp run runtime-coreclr gcstress-extra

Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@AaronRobinsonMSFT
Copy link
Member Author

/azp run runtime-coreclr ilasm

Copy link

Azure Pipelines could not run because the pipeline triggers exclude this branch/path.

@AaronRobinsonMSFT AaronRobinsonMSFT changed the title UnsafeAccessorAttribute supports generic attributes [CoreCLR and native AOT] UnsafeAccessorAttribute supports generic attributes Mar 9, 2024
@AaronRobinsonMSFT AaronRobinsonMSFT added the runtime-coreclr specific to the CoreCLR runtime label Mar 9, 2024
@AaronRobinsonMSFT AaronRobinsonMSFT changed the title [CoreCLR and native AOT] UnsafeAccessorAttribute supports generic attributes [CoreCLR and native AOT] UnsafeAccessorAttribute supports generic parameters Mar 10, 2024
@MichalPetryka
Copy link
Contributor

MichalPetryka commented Mar 12, 2024

What's the behaviour with constraints here? I assume they have to match? Asking since exposing the idea from #89439 (comment) might be interesting, either by default or with some new , DontMatchConstraints = true (EDIT: or maybe LazyConstraintChecks would be a better name) that'd cause UnsafeAccessor to match methods with different constraints and throw if they don't match at runtime.

@AaronRobinsonMSFT
Copy link
Member Author

What's the behaviour with constraints here? I assume they have to match? Asking since exposing the idea from #89439 (comment) might be interesting, either by default or with some new , DontMatchConstraints = true that'd cause UnsafeAccessor to match methods with different constraints and throw if they don't match at runtime.

Still discussing that at present. The constraint aspect is not being addressed in this PR. Since there are a number of assumptions about using this API in general and it is considered "unsafe", it is possible it is something the user needs to ensure is correct. An official decision will be made for .NET 9 though.

@MichalPetryka
Copy link
Contributor

Since there are a number of assumptions about using this API in general and it is considered "unsafe", it is possible it is something the user needs to ensure is correct.

@SingleAccretion mentioned before that checking at runtime would be an additional cost for shared generics so exposing both options could be the best solution.

@AaronRobinsonMSFT
Copy link
Member Author

/azp run runtime

Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@AaronRobinsonMSFT
Copy link
Member Author

Ah, I assumed the default would rather be that you need to match the constraints at declaration:

This is what I am currently exploring now.

Add strict check for precisely matched Generic constraints
@AaronRobinsonMSFT
Copy link
Member Author

@lambdageek Nope. I am defining "lookup" very precisely. Happy to relax this if we see compelling scenarios but I think, like the first iteration, strictness is helpful. It is for the same reason I am requiring constraints to match exactly.

    // also ok? - all variables, but some are rearranged
   [UnsafeAccessor(UnsafeAccessorKind.Method, Name = "M")]
   public extern static Tuple<U,T,V,W> CallM2<V,W>(C<U,T> c, U arg1, T arg2, V arg3, W arg4);

No. They must match precisely.

   // also ok? - some type args are constructed types
   [UnsafeAccessor(UnsafeAccessorKind.Method, Name = "M")]
   public extern static Tuple<List<T>,U, V, W> CallM3<V, W>(C<List<T>, U> c, List<T> arg1, U arg2, V arg3, W arg4);

No, the target signature doesn't match so lookup for M will fail.

   // also ok? - we need to guess the method instantiation based on the arguments?
   [UnsafeAccessor(UnsafeAccessorKind.Method, Name = "M")]
   public extern static Tuple<T,U, V[], W[]> CallM4<V, W>(C<T, U> c, T arg1, U arg2, V[] arg3, W[] arg4);

No, the target signature doesn't match so lookup for M will fail.

src/coreclr/vm/prestub.cpp Outdated Show resolved Hide resolved
src/coreclr/vm/prestub.cpp Outdated Show resolved Hide resolved
Add constraint test
Update tests to use unique parameter names
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.

Looks great! Thank you

@jkotas
Copy link
Member

jkotas commented Mar 19, 2024

We should make sure to update the docs: https://learn.microsoft.com/dotnet/api/system.runtime.compilerservices.unsafeaccessorattribute

@AaronRobinsonMSFT
Copy link
Member Author

We should make sure to update the docs: https://learn.microsoft.com/dotnet/api/system.runtime.compilerservices.unsafeaccessorattribute

Yep, that is being tracked in #89439.

Copy link
Member

@davidwrighton davidwrighton left a comment

Choose a reason for hiding this comment

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

:shipit:

@AaronRobinsonMSFT AaronRobinsonMSFT merged commit d58c541 into dotnet:main Mar 20, 2024
136 of 154 checks passed
@AaronRobinsonMSFT AaronRobinsonMSFT deleted the generic_unsafe_accessors branch March 20, 2024 20:25
@github-actions github-actions bot locked and limited conversation to collaborators Apr 20, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants