Skip to content

Commit a512438

Browse files
Document intrinsic APIs marked RequiresUnreferencedCode (dotnet#42725)
1 parent 6471416 commit a512438

File tree

2 files changed

+54
-0
lines changed

2 files changed

+54
-0
lines changed
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
---
2+
title: Intrinsic APIs marked RequiresUnreferencedCode
3+
description: Learn how the tooling recognizes certain patterns in calls to APIs annotated with RequiresUnreferencedCode.
4+
author: MichalStrehovsky
5+
ms.author: michals
6+
ms.date: 09/13/2024
7+
---
8+
9+
# Intrinsic APIs marked RequiresUnreferencedCode
10+
11+
Under normal circumstances, calling APIs annotated with <xref:System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute> in an app published with trimming triggers warning [IL2026 (Members attributed with RequiresUnreferencedCode may break when trimming)](trim-warnings/il2026.md). APIs that trigger the warning might not behave correctly in a trimmed deployment.
12+
13+
Some APIs annotated `[RequiresUnreferencedCode]` can still be used without triggering the warning if they're called in a specific pattern. When used as part of a pattern, the call to the API can be statically analyzed by the compiler, does not generate a warning, and behaves as expected at run time.
14+
15+
## MethodInfo.MakeGenericMethod(Type[]) method
16+
17+
Calls to this API don't trigger a warning if the generic method definition is statically visible within the calling method body and none of the generic method's generic parameters have the `new()` constraint or `DynamicallyAccessedMembers` attribute. For example, `typeof(SomeType).GetMethod("GenericMethod").MakeGenericMethod(someType)` doesn't generate a warning provided there are no `new()` constraints or `DynamicallyAccessedMembers` annotations on the generic parameters.
18+
19+
If the generic method has parameters with the `new()` constraint or `DynamicallyAccessedMembers` attribute, the generic arguments used with `MakeGenericMethod` need to also be statically visible within the calling method body. Otherwise the warning is issued.
20+
21+
## MethodInfo.MakeGenericType(Type[]) method
22+
23+
Calls to this API don't trigger a warning if the generic type definition is statically visible within the calling method body and none of the generic type's generic parameters have the `new()` constraint or `DynamicallyAccessedMembers` attribute. For example, `typeof(SomeType<>).MakeGenericType(someType)` doesn't generate a warning provided there are no `new()` constraints or `DynamicallyAccessedMembers` annotations on the generic parameters.
24+
25+
If the generic type has parameters with the `new()` constraint or `DynamicallyAccessedMembers` attribute, the generic arguments used with `MakeGenericType` need to also be statically visible within the calling method body. Otherwise the warning is issued.
26+
27+
## RuntimeHelpers.RunClassConstructor(Type) method
28+
29+
Calls to this API don't trigger a warning if the concrete type is statically visible in the calling method body. For example, `RuntimeHelpers.RunClassConstructor(typeof(string).TypeHandle)` does not trigger a warning, but `RuntimeHelpers.RunClassConstructor(typeof(T).TypeHandle)` and `RuntimeHelpers.RunClassConstructor(someTypeHandle)` do.
30+
31+
Additionally, starting with .NET 9, the warning isn't issued when the type handle was loaded from `Type` stored in a location annotated as `DynamicallyAccessedMemberTypes.NonPublicConstructors`. That's because non-public constructors include the static constructor:
32+
33+
```csharp
34+
static void M<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.NonPublicConstructors)] T>
35+
([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type t)
36+
{
37+
RuntimeHelpers.RunClassConstructor(typeof(T).TypeHandle); // No IL2026 warning
38+
RuntimeHelpers.RunClassConstructor(t.TypeHandle); // No IL2026 warning
39+
}
40+
41+
```
42+
43+
## Type.GetType overloads
44+
45+
Calls to this API don't trigger a warning if the string parameter is passed as a string literal and case-insensitive search isn't requested. The API also doesn't trigger a warning if a non-literal string is used, but the string was loaded from a location annotated with `[DynamicallyAccessedMembers]`.
46+
47+
```csharp
48+
static void GetTheType([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.NonPublicConstructors)] string s)
49+
{
50+
Type.GetType(s); // No IL2026 warning
51+
}
52+
```

docs/navigate/devops-testing/toc.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,8 @@ items:
253253
href: ../../core/deploying/trimming/trimming-options.md
254254
- name: Trimming libraries
255255
href: ../../core/deploying/trimming/prepare-libraries-for-trimming.md
256+
- name: Intrinsic APIs marked RequiresUnreferencedCode
257+
href: ../../core/deploying/trimming/intrinsic-requiresunreferencedcode-apis.md
256258
- name: Trim warnings
257259
items:
258260
- name: IL2001

0 commit comments

Comments
 (0)