dotnet / dotnet/linker

ILLinker will sometimes not detect the usage of a generic method and substitute the contents

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

Description

This was detected while trying to annotate a method in the dotnet/runtime repo which depends on a generic method from a generic class. The class in question is:

```c#
[DataContract(Namespace = "http://schemas.datacontract.org/2004/07/System.Collections.Generic")]
internal sealed class KeyValuePairAdapter : IKeyValuePairAdapter
{
// .... other members

internal KeyValuePair GetKeyValuePair()
{
return new KeyValuePair(_kvpKey, _kvpValue);
}
}
```

In a different class, we then use it like:

```c#
private sealed class ClassDataContractCriticalHelper : DataContract.DataContractCriticalHelper
{
private static readonly MethodInfo s_getKeyValuePairMethod = typeof(KeyValuePairAdapter<,>).GetMethod("GetKeyValuePair", Globals.ScanAllMembers)!;

// ... other code

[RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
private void SetKeyValuePairAdapterFlags(
[DynamicallyAccessedMembers(DataContractPreserveMemberTypes)]
Type type)
{
if (type.IsGenericType && type.GetGenericTypeDefinition() == Globals.TypeOfKeyValuePairAdapter)
{
_isKeyValuePairAdapter = true;
_keyValuePairGenericArguments = type.GetGenericArguments();
_keyValuePairCtorInfo = type.GetConstructor(Globals.ScanAllMembers, new Type[] { Globals.TypeOfKeyValuePair.MakeGenericType(_keyValuePairGenericArguments) });
_getKeyValuePairMethodInfo = (MethodInfo)type.GetMemberWithSameMetadataDefinitionAs(s_getKeyValuePairMethod);
}
}
```

The hard reference on the method when assigning it to variable `s_getKeyValuePairMethod ` should cause the method `GetKeyValuePair` on the generic type to get rooted and it's body preserved, but after aggressively linking this code, the linker is correctly detecting the method should be preserved, but it's body is swapped to:

![image](https://user-images.githubusercontent.com/13854455/128918675-ece7a73b-198d-4958-b308-747b93377e40.png)

Adding a `[DynamicDependency]` attribute to root the method works around the issue, but there should be no difference between using the `DynamicDependency` attribute and using reflection to depend on a method.

cc: @eerhardt @vitek-karas @sbomer

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.