dotnet/runtime

Developers using Reflection should be able to use pointers and function pointers

Closed this issue · 11 comments

Treatment of pointers in general is hit-and-miss especially with the newer function pointer (delegate*) feature.

Currently with function pointers, an IntPtr or fnptr* types are returned, so it is not possible today to distinguish between function pointers and other uses of IntPtr, for example. It is also not possible to determine the parameter types, return type or the calling convention.

What about ref in general? Eg ref prop ref returning methods etc? This part historically was half assed since support for it was added relatively recently in languages (several years at this point). Is this on the table?

What about ref in general?

Any common use case that is not supported is being considered. @BreyerW can you share an example so this is properly captured here? Thanks

@steveharter im not expert on reflection but i remember having trouble with ref return methods when generating dynamic methods it simply fails (dont remember exact exception since its year ago by now). Although theres workaround by defining entire assembly then generating ref return method inside that assembly but it isnt easy to discover i myself found that solution on accident in stackoverflow thread. Ref prop probably has similar issue since its method behind the scene.

Also frontline reflection API (or in other words most easily discoverable API) like GetValue dont have ref alternatives at all. I think even @jkotas or someone from net core team made a thread about this API type few years ago when dotnet/runtime was dotnet/corefx but you never fully committed resources to this and as such they never materialized

Last gripe is in System.Linq.Expression. this namespace is often bugged in presence of new uses of ref eg when trying to generate assignment to ref prop it fails because ref prop is defined as CanWrite=false despite being obviously wrong. Then again you killed this namespace's future so i guess this particular case is of no interest to you

Last gripe is in System.Linq.Expression

@BreyerW it looks like you added this issue previously: #25700. If you consider it blocking key scenarios, add the "blocking" label to it.

@steveharter not anymore due to this bug i simply moved away from S.L.E.

However i would consider it a bug in System.Reflection not in S.L.E in other words much higher priority than S.L.E i think? The root of evil here is in fact located in PropertyInfo.CanWrite NOT in S.L.E itself. Currently for ref returning props PropertyInfo.CanWrite reports false (because no setter available) while it should be true unless ref return is readonly ref

Currently for ref returning props PropertyInfo.CanWrite reports false (because no setter available) while it should be true unless ref return is readonly ref

If PropertyInfo.CanWrite semantics are changed for ref-returning properties that would likely be considered a breaking change as the documentation today states the calculation is based on whether there is a setter.

I see this S.L.E issue discusses it in more detail. It should also be basing it on whether the return type is a reference or byref type. Similar logic would be needed for parameter (not just return value). For example the code below outputs:

RefInt CanModify: True
RefType CanModify: True
Int CanModify: True
internal class Program
{
    private static void Main(string[] args)
    {
        CanModify(typeof(MyClass).GetProperty("RefInt")!);
        CanModify(typeof(MyClass).GetProperty("RefType")!);
        CanModify(typeof(MyClass).GetProperty("Int")!);

        static void CanModify(PropertyInfo info)
        {
            // Sample logic; not complete since they don't check if value type is readonly via [IsReadOnlyAttribute]
            bool canModify = info.CanWrite || !info.PropertyType.IsValueType || info.PropertyType.IsByRef;
            Console.WriteLine($"{info.Name} CanModify: {canModify}");
        }
    }
}
public class MyClass
{
    private int _refInt;
    public ref int RefInt => ref _refInt;
    public MyClass RefType => this;
    public int Int { get; set; }
}

@steveharter i see too bad but makes sense

Moving to 7.0; many of the features require language support while others were not funded.

Note the "fast invoke" and "ref struct" feature was moved to it's own user story at #45152.

cc @tannergooding in case of interest, since it came up this morning.

Closing for 8.0 since the remaining functionality is now tracked by #75358