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

[API Proposal]: UnsafeAccessor for member handles #94975

Open
MichalPetryka opened this issue Nov 19, 2023 · 2 comments
Open

[API Proposal]: UnsafeAccessor for member handles #94975

MichalPetryka opened this issue Nov 19, 2023 · 2 comments
Labels
api-suggestion Early API idea and discussion, it is NOT ready for implementation area-System.Runtime.CompilerServices needs-further-triage Issue has been initially triaged, but needs deeper consideration or reconsideration
Milestone

Comments

@MichalPetryka
Copy link
Contributor

MichalPetryka commented Nov 19, 2023

Background and motivation

IL has always exposed ldtoken instruction, but C# only exposed the type variant of it, making the method and field variants inaccessible. Requests for exposing those have been denied for either unclear semantics or the language team disliking the fact it'd promote reflection.
With the handles being useful for some low level code and exposing things like function pointers, I'd say there's still value in adding a way for cheaply obtaining them with trimming and AOT friendly, fast and visiblity-ignoring way. UnsafeAccessors from #81741 meets all 3 criteria (unlike reflection or IL weaving without IgnoreAccessChecksTo).

One question would be whether those should return RuntimeXHandles or XInfos, since the API is low level and there are existing APIs to get XInfos from handles, I'd suggest it to be the former.

Since IL exposes return type overloading on methods and fields (the latter is non CLS compliant though), the signature would need to indicate the type of those, for example with a dummy parameter at the end. The issue with this would be methods returning void.

If field Offset would be exposed on RuntimeFieldInfo in #94976, this could supersede #93946.

API Proposal

namespace System.Runtime.CompilerServices;

public enum UnsafeAccessorKind
{
    StaticFieldHandle, // handle to static field on the type (`ldtoken` in IL)
    FieldHandle, // handle to instance field on the type (`ldtoken` in IL)
    StaticMethodHandle, // handle to static method on the type (`ldtoken` in IL)
    MethodHandle, // handle to instance method on the type (`ldtoken` in IL)
    VirtualMethodHandle // same as InstanceMethodHandle but with virtual method resolving on the object instance, let's you emulate `ldvirtftn`
}

API Usage

public class C
{
    private int i;
    protected virtual string B() => "C";
}

public class D : C
{
    protected override void B() => "D";
}

[UnsafeAccessor(UnsafeAccessorKind.InstanceFieldHandled, Name = "i")]
public static RuntimeFieldHandle GetI(C c = null, int i = 0);
[UnsafeAccessor(UnsafeAccessorKind.InstanceMethodHandled, Name = "B")]
public static RuntimeMethodHandle GetB(C c = null, string s = null);
[UnsafeAccessor(UnsafeAccessorKind.VirtualMethodHandled, Name = "B")]
public static RuntimeMethodHandle GetBVirtual(C c, string s = null);

Console.WriteLine(FieldInfo.GetFieldFromHandle(GetI()).Attributes);
Console.WriteLine(MethodBase.GetMethodFromHandle(GetB())); // prints C.B
Console.WriteLine(MethodBase.GetMethodFromHandle(GetBVirtual(new D()))); // prints D.B

Alternative Designs

Exposing infoof/methodof/fieldof and IgnoreAccessChecksTo would be a possible alternative but both have already been rejected.

Risks

Popularising reflection use.

@MichalPetryka MichalPetryka added the api-suggestion Early API idea and discussion, it is NOT ready for implementation label Nov 19, 2023
@ghost ghost added the untriaged New issue has not been triaged by the area owner label Nov 19, 2023
@ghost
Copy link

ghost commented Nov 19, 2023

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

Issue Details

Background and motivation

IL has always exposed ldtoken instruction, but C# only exposed the type variant of it, making the method and field variants inaccessible. Requests for exposing those have been denied for either unclear semantics or the language team disliking the fact it'd promote reflection.
With the handles being useful for some low level code and exposing things like function pointers, I'd say there's still value in adding a way for cheaply obtaining them with trimming and AOT friendly, fast and visiblity-ignoring way. UnsafeAccessor meets all 3 criteria (unlike reflection or IL weaving without IgnoreAccessChecksTo).

One question would be whether those should return RuntimeXHandles or XInfos, since the API is low level and there are existing APIs to get XInfos from handles, I'd suggest it to be the former.

Since IL exposes return type overloading on methods and fields (the latter is non CLS compliant though), the signature would need to indicate the type of those, for example with a dummy parameter at the end. The issue with this would be methods returning void.

If FieldOffset would be exposed on RuntimeFieldInfo, this could supersede #93946.

API Proposal

namespace System.Runtime.CompilerServices;

public enum UnsafeAccessorKind
{
    StaticFieldHandle, // handle to static field on the type (`ldtoken` in IL)
    InstanceFieldHandle, // handle to instance field on the type (`ldtoken` in IL)
    StaticMethodHandle, // handle to static method on the type (`ldtoken` in IL)
    InstanceMethodHandle, // handle to instance method on the type (`ldtoken` in IL)
    VirtualMethodHandle // same as InstanceMethodHandle but with virtual method resolving on the object instance
}

API Usage

public class C
{
    private int i;
    protected virtual string B() => "C";
}

public class D : C
{
    protected override void B() => "D";
}

[UnsafeAccessor(UnsafeAccessorKind.InstanceFieldHandled, Name = "i")]
public static RuntimeFieldHandle GetI(C c = null, int i = 0);
[UnsafeAccessor(UnsafeAccessorKind.InstanceMethodHandled, Name = "B")]
public static RuntimeMethodHandle GetB(C c = null, string s = null);
[UnsafeAccessor(UnsafeAccessorKind.VirtualMethodHandled, Name = "B")]
public static RuntimeMethodHandle GetBVirtual(C c, string s = null);
Console.WriteLine(FieldInfo.GetFieldFromHandle(GetI()).Attributes);
Console.WriteLine(MethodBase.GetMethodFromHandle(GetB())); // prints C.B
Console.WriteLine(MethodBase.GetMethodFromHandle(GetBVirtual(new D()))); // prints D.B

Alternative Designs

Exposing infoof/methodof/fieldof and IgnoreAccessChecksTo would be a possible alternative but both have already been rejected.

Risks

Popularising reflection use.

Author: MichalPetryka
Assignees: -
Labels:

api-suggestion, area-System.Reflection

Milestone: -

@ghost
Copy link

ghost commented Nov 19, 2023

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

Issue Details

Background and motivation

IL has always exposed ldtoken instruction, but C# only exposed the type variant of it, making the method and field variants inaccessible. Requests for exposing those have been denied for either unclear semantics or the language team disliking the fact it'd promote reflection.
With the handles being useful for some low level code and exposing things like function pointers, I'd say there's still value in adding a way for cheaply obtaining them with trimming and AOT friendly, fast and visiblity-ignoring way. UnsafeAccessors from #81741 meets all 3 criteria (unlike reflection or IL weaving without IgnoreAccessChecksTo).

One question would be whether those should return RuntimeXHandles or XInfos, since the API is low level and there are existing APIs to get XInfos from handles, I'd suggest it to be the former.

Since IL exposes return type overloading on methods and fields (the latter is non CLS compliant though), the signature would need to indicate the type of those, for example with a dummy parameter at the end. The issue with this would be methods returning void.

If field Offset would be exposed on RuntimeFieldInfo in #94976, this could supersede #93946.

API Proposal

namespace System.Runtime.CompilerServices;

public enum UnsafeAccessorKind
{
    StaticFieldHandle, // handle to static field on the type (`ldtoken` in IL)
    InstanceFieldHandle, // handle to instance field on the type (`ldtoken` in IL)
    StaticMethodHandle, // handle to static method on the type (`ldtoken` in IL)
    InstanceMethodHandle, // handle to instance method on the type (`ldtoken` in IL)
    VirtualMethodHandle // same as InstanceMethodHandle but with virtual method resolving on the object instance, let's you emulate `ldvirtftn`
}

API Usage

public class C
{
    private int i;
    protected virtual string B() => "C";
}

public class D : C
{
    protected override void B() => "D";
}

[UnsafeAccessor(UnsafeAccessorKind.InstanceFieldHandled, Name = "i")]
public static RuntimeFieldHandle GetI(C c = null, int i = 0);
[UnsafeAccessor(UnsafeAccessorKind.InstanceMethodHandled, Name = "B")]
public static RuntimeMethodHandle GetB(C c = null, string s = null);
[UnsafeAccessor(UnsafeAccessorKind.VirtualMethodHandled, Name = "B")]
public static RuntimeMethodHandle GetBVirtual(C c, string s = null);

Console.WriteLine(FieldInfo.GetFieldFromHandle(GetI()).Attributes);
Console.WriteLine(MethodBase.GetMethodFromHandle(GetB())); // prints C.B
Console.WriteLine(MethodBase.GetMethodFromHandle(GetBVirtual(new D()))); // prints D.B

Alternative Designs

Exposing infoof/methodof/fieldof and IgnoreAccessChecksTo would be a possible alternative but both have already been rejected.

Risks

Popularising reflection use.

Author: MichalPetryka
Assignees: -
Labels:

api-suggestion, area-System.Runtime.CompilerServices, untriaged

Milestone: -

@tannergooding tannergooding added needs-further-triage Issue has been initially triaged, but needs deeper consideration or reconsideration and removed untriaged New issue has not been triaged by the area owner labels Jun 24, 2024
@stephentoub stephentoub added this to the Future milestone Jul 19, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
api-suggestion Early API idea and discussion, it is NOT ready for implementation area-System.Runtime.CompilerServices needs-further-triage Issue has been initially triaged, but needs deeper consideration or reconsideration
Projects
None yet
Development

No branches or pull requests

4 participants