From bfe063c845329f21e452b84dcaccf834d516eccd Mon Sep 17 00:00:00 2001
From: Nick Stanton <nickstanton@microsoft.com>
Date: Tue, 13 Dec 2022 11:28:59 -0700
Subject: [PATCH 1/4] Add warnings and annotations

---
 .../Components/src/Reflection/PropertySetter.cs          | 4 ++++
 src/Http/Routing/src/Matching/ILEmitTrieFactory.cs       | 3 +++
 src/Http/Routing/src/Matching/ILEmitTrieJumpTable.cs     | 3 +++
 src/Http/Routing/src/Matching/JumpTableBuilder.cs        | 2 ++
 .../src/Infrastructure/DotNetDispatcher.cs               | 3 +++
 .../DotNetObjectReferenceJsonConverterFactory.cs         | 1 +
 .../src/Infrastructure/TaskGenericsUtil.cs               | 7 +++++++
 src/Shared/PropertyHelper/PropertyHelper.cs              | 9 +++++++++
 8 files changed, 32 insertions(+)

diff --git a/src/Components/Components/src/Reflection/PropertySetter.cs b/src/Components/Components/src/Reflection/PropertySetter.cs
index a79c71ccbaf0..c65bea3231db 100644
--- a/src/Components/Components/src/Reflection/PropertySetter.cs
+++ b/src/Components/Components/src/Reflection/PropertySetter.cs
@@ -17,6 +17,10 @@ internal sealed class PropertySetter
         "ReflectionAnalysis",
         "IL2060:MakeGenericMethod",
         Justification = "The referenced methods don't have any DynamicallyAccessedMembers annotations. See https://github.com/mono/linker/issues/1727")]
+    [SuppressMessage(
+        "AOT",
+        "IL3050:Calling members annotated with 'RequiresDynamicCodeAttribute' may break functionality when AOT compiling.",
+        Justification = "The referenced methods are AOT safe with reference types.")]
     public PropertySetter(Type targetType, PropertyInfo property)
     {
         if (property.SetMethod == null)
diff --git a/src/Http/Routing/src/Matching/ILEmitTrieFactory.cs b/src/Http/Routing/src/Matching/ILEmitTrieFactory.cs
index 52af625d63c8..01f40f130c79 100644
--- a/src/Http/Routing/src/Matching/ILEmitTrieFactory.cs
+++ b/src/Http/Routing/src/Matching/ILEmitTrieFactory.cs
@@ -4,6 +4,7 @@
 #nullable disable
 
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 using System.Linq;
 using System.Reflection;
 using System.Reflection.Emit;
@@ -12,6 +13,7 @@
 
 namespace Microsoft.AspNetCore.Routing.Matching;
 
+[RequiresDynamicCode("ILEmitTrieFactory uses runtime IL generation.")]
 internal static class ILEmitTrieFactory
 {
     // The algorthm we use only works for ASCII text. If we find non-ASCII text in the input
@@ -477,6 +479,7 @@ private sealed class Labels
         public Label ReturnNotAscii { get; set; }
     }
 
+    [RequiresDynamicCode("ILEmitTrieFactory uses runtime IL generation.")]
     private sealed class Methods
     {
         // Caching because the methods won't change, if we're being called once we're likely to
diff --git a/src/Http/Routing/src/Matching/ILEmitTrieJumpTable.cs b/src/Http/Routing/src/Matching/ILEmitTrieJumpTable.cs
index f382c2d562b7..b0e975d7fdc1 100644
--- a/src/Http/Routing/src/Matching/ILEmitTrieJumpTable.cs
+++ b/src/Http/Routing/src/Matching/ILEmitTrieJumpTable.cs
@@ -3,12 +3,15 @@
 
 #nullable disable
 
+using System.Diagnostics.CodeAnalysis;
+
 namespace Microsoft.AspNetCore.Routing.Matching;
 
 // Uses generated IL to implement the JumpTable contract. This approach requires
 // a fallback jump table for two reasons:
 // 1. We compute the IL lazily to avoid taking up significant time when processing a request
 // 2. The generated IL only supports ASCII in the URL path
+[RequiresDynamicCode("ILEmitTrieJumpTable uses runtime IL generation.")]
 internal sealed class ILEmitTrieJumpTable : JumpTable
 {
     private readonly int _defaultDestination;
diff --git a/src/Http/Routing/src/Matching/JumpTableBuilder.cs b/src/Http/Routing/src/Matching/JumpTableBuilder.cs
index 4ead4b3bb889..0c48d3b261c2 100644
--- a/src/Http/Routing/src/Matching/JumpTableBuilder.cs
+++ b/src/Http/Routing/src/Matching/JumpTableBuilder.cs
@@ -87,7 +87,9 @@ public static JumpTable Build(int defaultDestination, int exitDestination, (stri
         // Use the ILEmitTrieJumpTable if the IL is going to be compiled (not interpreted)
         if (RuntimeFeature.IsDynamicCodeCompiled)
         {
+#pragma warning disable IL3050 // See https://github.com/dotnet/linker/issues/2715.
             return new ILEmitTrieJumpTable(defaultDestination, exitDestination, pathEntries, vectorize: null, fallback);
+#pragma warning restore IL3050 
         }
 
         return fallback;
diff --git a/src/JSInterop/Microsoft.JSInterop/src/Infrastructure/DotNetDispatcher.cs b/src/JSInterop/Microsoft.JSInterop/src/Infrastructure/DotNetDispatcher.cs
index 5640fce75a5f..f24a1afb1578 100644
--- a/src/JSInterop/Microsoft.JSInterop/src/Infrastructure/DotNetDispatcher.cs
+++ b/src/JSInterop/Microsoft.JSInterop/src/Infrastructure/DotNetDispatcher.cs
@@ -375,6 +375,9 @@ private static (MethodInfo, Type[]) GetCachedMethodInfo(AssemblyKey assemblyKey,
         "ReflectionAnalysis",
         "IL2060:MakeGenericMethod",
         Justification = "https://github.com/mono/linker/issues/1727")]
+    [SuppressMessage("AOT",
+        "IL3050:Calling members annotated with 'RequiresDynamicCodeAttribute' may break functionality when AOT compiling.",
+        Justification = "Methods being referenced do not have DynamicallyAccessedMembers.")]
     private static Task GetTaskByType(Type type, object obj)
     {
         var converterDelegate = _cachedConvertToTaskByType.GetOrAdd(type, (Type t, MethodInfo taskConverterMethodInfo) =>
diff --git a/src/JSInterop/Microsoft.JSInterop/src/Infrastructure/DotNetObjectReferenceJsonConverterFactory.cs b/src/JSInterop/Microsoft.JSInterop/src/Infrastructure/DotNetObjectReferenceJsonConverterFactory.cs
index b769b949d974..c7808a0fa145 100644
--- a/src/JSInterop/Microsoft.JSInterop/src/Infrastructure/DotNetObjectReferenceJsonConverterFactory.cs
+++ b/src/JSInterop/Microsoft.JSInterop/src/Infrastructure/DotNetObjectReferenceJsonConverterFactory.cs
@@ -22,6 +22,7 @@ public override bool CanConvert(Type typeToConvert)
     }
 
     [UnconditionalSuppressMessage("Trimming", "IL2055", Justification = "We expect that types used with DotNetObjectReference are retained.")]
+    [SuppressMessage("AOT", "IL3050:Calling members annotated with 'RequiresDynamicCodeAttribute' may break functionality when AOT compiling.", Justification = "MakeGenericType is AOT safe for reference types.")]
     public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions jsonSerializerOptions)
     {
         // System.Text.Json handles caching the converters per type on our behalf. No caching is required here.
diff --git a/src/JSInterop/Microsoft.JSInterop/src/Infrastructure/TaskGenericsUtil.cs b/src/JSInterop/Microsoft.JSInterop/src/Infrastructure/TaskGenericsUtil.cs
index a03d87536db1..fc09ebf314c4 100644
--- a/src/JSInterop/Microsoft.JSInterop/src/Infrastructure/TaskGenericsUtil.cs
+++ b/src/JSInterop/Microsoft.JSInterop/src/Infrastructure/TaskGenericsUtil.cs
@@ -2,6 +2,7 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 
 using System.Collections.Concurrent;
+using System.Diagnostics.CodeAnalysis;
 using System.Globalization;
 
 namespace Microsoft.JSInterop.Infrastructure;
@@ -23,6 +24,9 @@ public static void SetTaskCompletionSourceException(object taskCompletionSource,
     public static Type GetTaskCompletionSourceResultType(object taskCompletionSource)
         => CreateResultSetter(taskCompletionSource).ResultType;
 
+    [SuppressMessage("AOT",
+        "IL3050:Calling members annotated with 'RequiresDynamicCodeAttribute' may break functionality when AOT compiling.",
+        Justification = "MakeGenericType is AOT safe for reference types.")]
     public static object? GetTaskResult(Task task)
     {
         var getter = _cachedResultGetters.GetOrAdd(task.GetType(), taskInstanceType =>
@@ -101,6 +105,9 @@ public void SetException(object tcs, Exception exception)
         }
     }
 
+    [SuppressMessage("AOT",
+        "IL3050:Calling members annotated with 'RequiresDynamicCodeAttribute' may break functionality when AOT compiling.",
+        Justification = "MakeGenericType is AOT safe for reference types.")]
     private static ITcsResultSetter CreateResultSetter(object taskCompletionSource)
     {
         return _cachedResultSetters.GetOrAdd(taskCompletionSource.GetType(), tcsType =>
diff --git a/src/Shared/PropertyHelper/PropertyHelper.cs b/src/Shared/PropertyHelper/PropertyHelper.cs
index f0301fe7fcc0..44e23a3149a3 100644
--- a/src/Shared/PropertyHelper/PropertyHelper.cs
+++ b/src/Shared/PropertyHelper/PropertyHelper.cs
@@ -151,6 +151,7 @@ public static PropertyHelper[] GetProperties(
     /// A cached array of all public properties of the specified type.
     /// </returns>
     [RequiresUnreferencedCode("This API is not trim safe.")]
+    [RequiresDynamicCode("This API is not trim safe.")]
     public static PropertyHelper[] GetVisibleProperties(
         [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.NonPublicProperties)] Type type)
     {
@@ -167,6 +168,7 @@ public static PropertyHelper[] GetVisibleProperties(
     /// same speed.
     /// </remarks>
     [RequiresUnreferencedCode("This API is not trimmer safe.")]
+    [RequiresDynamicCode("This API is not trim safe.")]
     public static Func<object, object?> MakeFastPropertyGetter(PropertyInfo propertyInfo)
     {
         Debug.Assert(propertyInfo != null);
@@ -187,6 +189,7 @@ public static PropertyHelper[] GetVisibleProperties(
     /// same speed.
     /// </remarks>
     [RequiresUnreferencedCode("This API is not trimmer safe.")]
+    [RequiresDynamicCode("This API is not trim safe.")]
     public static Func<object, object?> MakeNullSafeFastPropertyGetter(PropertyInfo propertyInfo)
     {
         Debug.Assert(propertyInfo != null);
@@ -198,6 +201,7 @@ public static PropertyHelper[] GetVisibleProperties(
     }
 
     [RequiresUnreferencedCode("This API is not trimmer safe.")]
+    [RequiresDynamicCode("This API is not trim safe.")]
     private static Func<object, object?> MakeFastPropertyGetter(
         PropertyInfo propertyInfo,
         MethodInfo propertyGetterWrapperMethod,
@@ -242,6 +246,7 @@ public static PropertyHelper[] GetVisibleProperties(
     }
 
     [RequiresUnreferencedCode("This API is not trimmer safe.")]
+    [RequiresDynamicCode("This API is not trim safe.")]
     private static Func<object, object?> MakeFastPropertyGetter(
         Type openGenericDelegateType,
         MethodInfo propertyGetMethod,
@@ -271,6 +276,7 @@ public static PropertyHelper[] GetVisibleProperties(
     /// same speed. This only works for reference types.
     /// </remarks>
     [RequiresUnreferencedCode("This API is not trimmer safe.")]
+    [RequiresDynamicCode("This API is not trim safe.")]
     public static Action<object, object?> MakeFastPropertySetter(PropertyInfo propertyInfo)
     {
         Debug.Assert(propertyInfo != null);
@@ -313,6 +319,7 @@ public static PropertyHelper[] GetVisibleProperties(
     /// faster when the same type is used multiple times with ObjectToDictionary.
     /// </remarks>
     [RequiresUnreferencedCode("Method uses reflection to generate the dictionary.")]
+    [RequiresDynamicCode("This API is not trim safe.")]
     public static IDictionary<string, object?> ObjectToDictionary(object? value)
     {
         if (value is IDictionary<string, object?> dictionary)
@@ -402,6 +409,7 @@ private static void CallPropertySetter<TDeclaringType, TValue>(
     /// A cached array of all public properties of the specified type.
     /// </returns>
     [RequiresUnreferencedCode("This API is not trim safe.")]
+    [RequiresDynamicCode("This API is not trim safe.")]
     public static PropertyHelper[] GetVisibleProperties(
         Type type,
         ConcurrentDictionary<Type, PropertyHelper[]>? allPropertiesCache,
@@ -483,6 +491,7 @@ public static PropertyHelper[] GetVisibleProperties(
     /// </returns>
     // There isn't a way to represent trimmability requirements since for type since we unwrap nullable types.
     [RequiresUnreferencedCode("This API is not trim safe.")]
+    [RequiresDynamicCode("This API is not trim safe.")]
     public static PropertyHelper[] GetProperties(
         Type type,
         ConcurrentDictionary<Type, PropertyHelper[]>? cache)

From af375813bcae777994a8a9acf7bf3f09a933472b Mon Sep 17 00:00:00 2001
From: Nick Stanton <nickstanton@microsoft.com>
Date: Tue, 20 Dec 2022 14:24:27 -0700
Subject: [PATCH 2/4] revert PropertyHelper changes

---
 src/Shared/PropertyHelper/PropertyHelper.cs | 9 ---------
 1 file changed, 9 deletions(-)

diff --git a/src/Shared/PropertyHelper/PropertyHelper.cs b/src/Shared/PropertyHelper/PropertyHelper.cs
index 44e23a3149a3..f0301fe7fcc0 100644
--- a/src/Shared/PropertyHelper/PropertyHelper.cs
+++ b/src/Shared/PropertyHelper/PropertyHelper.cs
@@ -151,7 +151,6 @@ public static PropertyHelper[] GetProperties(
     /// A cached array of all public properties of the specified type.
     /// </returns>
     [RequiresUnreferencedCode("This API is not trim safe.")]
-    [RequiresDynamicCode("This API is not trim safe.")]
     public static PropertyHelper[] GetVisibleProperties(
         [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.NonPublicProperties)] Type type)
     {
@@ -168,7 +167,6 @@ public static PropertyHelper[] GetVisibleProperties(
     /// same speed.
     /// </remarks>
     [RequiresUnreferencedCode("This API is not trimmer safe.")]
-    [RequiresDynamicCode("This API is not trim safe.")]
     public static Func<object, object?> MakeFastPropertyGetter(PropertyInfo propertyInfo)
     {
         Debug.Assert(propertyInfo != null);
@@ -189,7 +187,6 @@ public static PropertyHelper[] GetVisibleProperties(
     /// same speed.
     /// </remarks>
     [RequiresUnreferencedCode("This API is not trimmer safe.")]
-    [RequiresDynamicCode("This API is not trim safe.")]
     public static Func<object, object?> MakeNullSafeFastPropertyGetter(PropertyInfo propertyInfo)
     {
         Debug.Assert(propertyInfo != null);
@@ -201,7 +198,6 @@ public static PropertyHelper[] GetVisibleProperties(
     }
 
     [RequiresUnreferencedCode("This API is not trimmer safe.")]
-    [RequiresDynamicCode("This API is not trim safe.")]
     private static Func<object, object?> MakeFastPropertyGetter(
         PropertyInfo propertyInfo,
         MethodInfo propertyGetterWrapperMethod,
@@ -246,7 +242,6 @@ public static PropertyHelper[] GetVisibleProperties(
     }
 
     [RequiresUnreferencedCode("This API is not trimmer safe.")]
-    [RequiresDynamicCode("This API is not trim safe.")]
     private static Func<object, object?> MakeFastPropertyGetter(
         Type openGenericDelegateType,
         MethodInfo propertyGetMethod,
@@ -276,7 +271,6 @@ public static PropertyHelper[] GetVisibleProperties(
     /// same speed. This only works for reference types.
     /// </remarks>
     [RequiresUnreferencedCode("This API is not trimmer safe.")]
-    [RequiresDynamicCode("This API is not trim safe.")]
     public static Action<object, object?> MakeFastPropertySetter(PropertyInfo propertyInfo)
     {
         Debug.Assert(propertyInfo != null);
@@ -319,7 +313,6 @@ public static PropertyHelper[] GetVisibleProperties(
     /// faster when the same type is used multiple times with ObjectToDictionary.
     /// </remarks>
     [RequiresUnreferencedCode("Method uses reflection to generate the dictionary.")]
-    [RequiresDynamicCode("This API is not trim safe.")]
     public static IDictionary<string, object?> ObjectToDictionary(object? value)
     {
         if (value is IDictionary<string, object?> dictionary)
@@ -409,7 +402,6 @@ private static void CallPropertySetter<TDeclaringType, TValue>(
     /// A cached array of all public properties of the specified type.
     /// </returns>
     [RequiresUnreferencedCode("This API is not trim safe.")]
-    [RequiresDynamicCode("This API is not trim safe.")]
     public static PropertyHelper[] GetVisibleProperties(
         Type type,
         ConcurrentDictionary<Type, PropertyHelper[]>? allPropertiesCache,
@@ -491,7 +483,6 @@ public static PropertyHelper[] GetVisibleProperties(
     /// </returns>
     // There isn't a way to represent trimmability requirements since for type since we unwrap nullable types.
     [RequiresUnreferencedCode("This API is not trim safe.")]
-    [RequiresDynamicCode("This API is not trim safe.")]
     public static PropertyHelper[] GetProperties(
         Type type,
         ConcurrentDictionary<Type, PropertyHelper[]>? cache)

From 8b265e7e008f3431a1a5ea4bc1486435e3cb094f Mon Sep 17 00:00:00 2001
From: Nick Stanton <nickstanton@microsoft.com>
Date: Wed, 21 Dec 2022 14:09:17 -0700
Subject: [PATCH 3/4] Revert JSInterop changes

---
 .../src/Infrastructure/DotNetDispatcher.cs                 | 3 ---
 .../DotNetObjectReferenceJsonConverterFactory.cs           | 1 -
 .../src/Infrastructure/TaskGenericsUtil.cs                 | 7 -------
 3 files changed, 11 deletions(-)

diff --git a/src/JSInterop/Microsoft.JSInterop/src/Infrastructure/DotNetDispatcher.cs b/src/JSInterop/Microsoft.JSInterop/src/Infrastructure/DotNetDispatcher.cs
index f24a1afb1578..5640fce75a5f 100644
--- a/src/JSInterop/Microsoft.JSInterop/src/Infrastructure/DotNetDispatcher.cs
+++ b/src/JSInterop/Microsoft.JSInterop/src/Infrastructure/DotNetDispatcher.cs
@@ -375,9 +375,6 @@ private static (MethodInfo, Type[]) GetCachedMethodInfo(AssemblyKey assemblyKey,
         "ReflectionAnalysis",
         "IL2060:MakeGenericMethod",
         Justification = "https://github.com/mono/linker/issues/1727")]
-    [SuppressMessage("AOT",
-        "IL3050:Calling members annotated with 'RequiresDynamicCodeAttribute' may break functionality when AOT compiling.",
-        Justification = "Methods being referenced do not have DynamicallyAccessedMembers.")]
     private static Task GetTaskByType(Type type, object obj)
     {
         var converterDelegate = _cachedConvertToTaskByType.GetOrAdd(type, (Type t, MethodInfo taskConverterMethodInfo) =>
diff --git a/src/JSInterop/Microsoft.JSInterop/src/Infrastructure/DotNetObjectReferenceJsonConverterFactory.cs b/src/JSInterop/Microsoft.JSInterop/src/Infrastructure/DotNetObjectReferenceJsonConverterFactory.cs
index c7808a0fa145..b769b949d974 100644
--- a/src/JSInterop/Microsoft.JSInterop/src/Infrastructure/DotNetObjectReferenceJsonConverterFactory.cs
+++ b/src/JSInterop/Microsoft.JSInterop/src/Infrastructure/DotNetObjectReferenceJsonConverterFactory.cs
@@ -22,7 +22,6 @@ public override bool CanConvert(Type typeToConvert)
     }
 
     [UnconditionalSuppressMessage("Trimming", "IL2055", Justification = "We expect that types used with DotNetObjectReference are retained.")]
-    [SuppressMessage("AOT", "IL3050:Calling members annotated with 'RequiresDynamicCodeAttribute' may break functionality when AOT compiling.", Justification = "MakeGenericType is AOT safe for reference types.")]
     public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions jsonSerializerOptions)
     {
         // System.Text.Json handles caching the converters per type on our behalf. No caching is required here.
diff --git a/src/JSInterop/Microsoft.JSInterop/src/Infrastructure/TaskGenericsUtil.cs b/src/JSInterop/Microsoft.JSInterop/src/Infrastructure/TaskGenericsUtil.cs
index fc09ebf314c4..a03d87536db1 100644
--- a/src/JSInterop/Microsoft.JSInterop/src/Infrastructure/TaskGenericsUtil.cs
+++ b/src/JSInterop/Microsoft.JSInterop/src/Infrastructure/TaskGenericsUtil.cs
@@ -2,7 +2,6 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 
 using System.Collections.Concurrent;
-using System.Diagnostics.CodeAnalysis;
 using System.Globalization;
 
 namespace Microsoft.JSInterop.Infrastructure;
@@ -24,9 +23,6 @@ public static void SetTaskCompletionSourceException(object taskCompletionSource,
     public static Type GetTaskCompletionSourceResultType(object taskCompletionSource)
         => CreateResultSetter(taskCompletionSource).ResultType;
 
-    [SuppressMessage("AOT",
-        "IL3050:Calling members annotated with 'RequiresDynamicCodeAttribute' may break functionality when AOT compiling.",
-        Justification = "MakeGenericType is AOT safe for reference types.")]
     public static object? GetTaskResult(Task task)
     {
         var getter = _cachedResultGetters.GetOrAdd(task.GetType(), taskInstanceType =>
@@ -105,9 +101,6 @@ public void SetException(object tcs, Exception exception)
         }
     }
 
-    [SuppressMessage("AOT",
-        "IL3050:Calling members annotated with 'RequiresDynamicCodeAttribute' may break functionality when AOT compiling.",
-        Justification = "MakeGenericType is AOT safe for reference types.")]
     private static ITcsResultSetter CreateResultSetter(object taskCompletionSource)
     {
         return _cachedResultSetters.GetOrAdd(taskCompletionSource.GetType(), tcsType =>

From 757c43caa4c7838bc6f47721b5426d0d9fc6225d Mon Sep 17 00:00:00 2001
From: Nick Stanton <nickstanton@microsoft.com>
Date: Wed, 28 Dec 2022 12:44:19 -0700
Subject: [PATCH 4/4] revert PropertySetter changes

---
 src/Components/Components/src/Reflection/PropertySetter.cs | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/src/Components/Components/src/Reflection/PropertySetter.cs b/src/Components/Components/src/Reflection/PropertySetter.cs
index c65bea3231db..a79c71ccbaf0 100644
--- a/src/Components/Components/src/Reflection/PropertySetter.cs
+++ b/src/Components/Components/src/Reflection/PropertySetter.cs
@@ -17,10 +17,6 @@ internal sealed class PropertySetter
         "ReflectionAnalysis",
         "IL2060:MakeGenericMethod",
         Justification = "The referenced methods don't have any DynamicallyAccessedMembers annotations. See https://github.com/mono/linker/issues/1727")]
-    [SuppressMessage(
-        "AOT",
-        "IL3050:Calling members annotated with 'RequiresDynamicCodeAttribute' may break functionality when AOT compiling.",
-        Justification = "The referenced methods are AOT safe with reference types.")]
     public PropertySetter(Type targetType, PropertyInfo property)
     {
         if (property.SetMethod == null)