You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
[CoreCLR and native AOT] UnsafeAccessorAttribute supports generic parameters (#99468)
* Generic type support
Instance and static fields on generic types
Re-enable and add to field tests
Generic types with non-generic methods.
Generic static methods
* Native AOT support
* Add design document
Add strict check for precisely matched Generic constraints
Number of existing .NET serializers depend on skipping member visibility checks for data serialization. Examples include System.Text.Json or EF Core. In order to skip the visibility checks, the serializers typically use dynamically emitted code (Reflection.Emit or Linq.Expressions) and classic reflection APIs as slow fallback. Neither of these two options are great for source generated serializers and native AOT compilation. This API proposal introduces a first class zero-overhead mechanism for skipping visibility checks.
6
+
7
+
## Semantics
8
+
9
+
This attribute will be applied to an `extern static` method. The implementation of the `extern static` method annotated with this attribute will be provided by the runtime based on the information in the attribute and the signature of the method that the attribute is applied to. The runtime will try to find the matching method or field and forward the call to it. If the matching method or field is not found, the body of the `extern static` method will throw `MissingFieldException` or `MissingMethodException`.
10
+
11
+
For `Method`, `StaticMethod`, `Field`, and `StaticField`, the type of the first argument of the annotated `extern static` method identifies the owning type. Only the specific type defined will be examined for inaccessible members. The type hierarchy is not walked looking for a match.
12
+
13
+
The value of the first argument is treated as `this` pointer for instance fields and methods.
14
+
15
+
The first argument must be passed as `ref` for instance fields and methods on structs.
16
+
17
+
The value of the first argument is not used by the implementation for static fields and methods.
18
+
19
+
The return value for an accessor to a field can be `ref` if setting of the field is desired.
20
+
21
+
Constructors can be accessed using Constructor or Method.
22
+
23
+
The return type is considered for the signature match. Modreqs and modopts are initially not considered for the signature match. However, if an ambiguity exists ignoring modreqs and modopts, a precise match is attempted. If an ambiguity still exists, `AmbiguousMatchException` is thrown.
24
+
25
+
By default, the attributed method's name dictates the name of the method/field. This can cause confusion in some cases since language abstractions, like C# local functions, generate mangled IL names. The solution to this is to use the `nameof` mechanism and define the `Name` property.
26
+
27
+
Scenarios involving generics may require creating new generic types to contain the `extern static` method definition. The decision was made to require all `ELEMENT_TYPE_VAR` and `ELEMENT_TYPE_MVAR` instances to match identically type and generic parameter index. This means if the target method for access uses an `ELEMENT_TYPE_VAR`, the `extern static` method must also use an `ELEMENT_TYPE_VAR`. For example:
28
+
29
+
```csharp
30
+
classC<T>
31
+
{
32
+
TM<U>(Uu) =>default;
33
+
}
34
+
35
+
classAccessor<V>
36
+
{
37
+
// Correct - V is an ELEMENT_TYPE_VAR and W is ELEMENT_TYPE_VAR,
38
+
// respectively the same as T and U in the definition of C<T>::M<U>().
// Incorrect - Since Y must be an ELEMENT_TYPE_VAR, but is ELEMENT_TYPE_MVAR below.
43
+
// [UnsafeAccessor(UnsafeAccessorKind.Method, Name = "M")]
44
+
// extern static void CallM<Y, Z>(C<Y> c, Z z);
45
+
}
46
+
```
47
+
48
+
Methods with the `UnsafeAccessorAttribute` that access members with generic parameters are expected to have the same declared constraints with the target member. Failure to do so results in unspecified behavior. For example:
0 commit comments