dotnet / dotnet/linker

EnableAOTAnalyzer doesn't catch members marked RequiresDynamicCode when used by DynamicallyAccessedMembers

Open
#2,959 1 comment 0 reactions 0 assignees View on GitHub
Dominant language
C#
Stars
392
Forks
128
Avg merge
2d 10h
Merged PRs (30d)
2

Description

### Description

When a member that is marked as `RequiresDynamicCode` is passed into a function that is annotated with `DynamicallyAccessedMembers`, the `RequiresDynamicCode` should "flow" through that method.

In the example below `ServiceDescriptor.Singleton` is annotated that the 2nd generic type's "public constructors" will be used accessed dynamically. Since the `MyClass`'s constructor has `RequiresDynamicCode` on it, this should cause a warning. However, no warnings are produced, and publish succeeds.

### Repro

`dotnet publish -r win-x64` the following application:

```xml


Exe
net7.0
enable
enable
true
true

```

```C#
using System.Diagnostics.CodeAnalysis;
using System.Reflection;
using System.Reflection.Emit;

var s = ServiceDescriptor.Singleton();
var c = (IMyInterface)Activator.CreateInstance(s.ImplementationType!)!;
c.Run();

public class ServiceDescriptor
{
public Type ServiceType { get; }

[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)]
public Type? ImplementationType { get; }

public ServiceDescriptor(
Type serviceType,
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type implementationType)
{
ServiceType = serviceType;
ImplementationType = implementationType;
}

public static ServiceDescriptor Singleton()
where TService : class
where TImplementation : class, TService
{
return new ServiceDescriptor(typeof(TService), typeof(TImplementation));
}
}

interface IMyInterface
{
void Run();
}

public class MyClass : IMyInterface
{
private MethodInfo _m;

[RequiresDynamicCode("dynamic code is required.")]
public MyClass()
{
var m = new DynamicMethod("MyMethod", typeof(string), null);
var il = m.GetILGenerator();
il.Emit(OpCodes.Ldstr, "Hello, World!");
il.Emit(OpCodes.Ret);

_m = m;
}

public void Run()
{
Console.WriteLine((string)_m.Invoke(null, null)!);
}
}
```

### Expected Results

I should get a warning since this app is using DynamicMethod. This can be proven because `MyClass`'s constructor is marked with `RequiresDynamicCode`, and `MyClass` is passed into a method that says "I'm going to dynamically access the constructors of this type".

### Actual Results

Publish succeeds without any warnings. The app is broken at runtime.

cc @MichalStrehovsky @tlakollo

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.