Skip to content

IL2091 errors for all APIs using an annotated type as parameter, is this by design? #2938

Open
@Sergio0694

Description

@Sergio0694

I'm working on adding NativeAOT support to my swap chain Win32 sample for ComputeSharp (see here) and I'm having trouble understanding a lot of linker errors I'm getting. I've fixed them adding the necessary annotations, but I'm still quite confused as to why they're needed in the first place.

You can see the full code in this PR, but to summarize, I have this:

// I have some type like this
public class SomeType<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields)] T>
{
    public SomeTime()
    {
        SomeMethodDoingReflectionOnTheTypeArgument<T>(); // This is why I need the annotation
    }
}

// And then somewhere else
public class SomeClass
{
    public static void SomeMethod<T>(SomeType<T> foo)
    {
        // Do stuff...
    }
}

Now, I'm getting a whole bunch of linker errors like this:

error IL2091: 'T' generic argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicFields', 'DynamicallyAccessedMemberTypes.NonPublicFields' in 'ComputeSharp.ReadWriteBuffer'. The generic parameter 'T' of 'ComputeSharp.ComputeContextExtensions.Barrier(in ComputeContext, ReadWriteBuffer)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to.

But like... Why? I do need the annotation for the type, because I'm doing reflection in the constructor, sure. But if I have a generic method that receives an instance of this method, why does it also need the trimming annotation? The input type would have already be constructed there, so this method will never reach any code paths doing reflection. Is this just because the linker can't know the constructor is the only place where this will happen, and it assumes every API on this type might also reflect on T? If so, is there a more narrow annotation I can use so that only callsites constructing the type require the annotation?

Right now otherwise I have to add a whole bunch of annotations everywhere that I'm not sure are actually needed 🤔

Side question: if I need to reflect on the fields of a type and all their fields, recursively, what annotation do I need? I'm using [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.NonPublicFields)] but then I still get a linker error when recursive on the method on the type of one of the explored fields. Is there some annotation to imply I want to retain all fields of a type, recursively so I could use it here? Thank you! 😄

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    Status

    No status

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions