Aot annotation on System.Text.Json#67582
Conversation
|
Note regarding the This serves as a reminder for when your PR is modifying a ref *.cs file and adding/modifying public APIs, to please make sure the API implementation in the src *.cs file is documented with triple slash comments, so the PR reviewers can sign off that change. |
|
Tagging subscribers to this area: @dotnet/area-system-text-json, @gregsdennis Issue DetailsThe annotation falls into two categories
This PR takes a dependency on a pending API request and hence is in a draft form.
|
| /// The object to be added to the end of the <see cref="JsonArray"/>. | ||
| /// </param> | ||
| [RequiresUnreferencedCode(JsonValue.CreateUnreferencedCodeMessage)] | ||
| [RequiresDynamicCode(JsonValue.CreateUnreferencedCodeMessage)] |
There was a problem hiding this comment.
I believe you need to update the ref code as well for all public changes.
|
|
||
| [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", | ||
| Justification = "Workaround for https://github.com/mono/linker/issues/1416. All usages are marked as unsafe.")] | ||
| [UnconditionalSuppressMessage("AOT", "IL3050:Calling members annotated with 'RequiresDynamicCodeAttribute' may break functionality when AOT compiling.", Justification = "<Pending>")] |
There was a problem hiding this comment.
- The strings in the second string,
IL3050are really long. Can they just be simplified to `IL3050:RequiresDynamicCodeAttribute". - All justification should be filled out.
- Is the justification the same as the existing suppress message - working around Linker warns about generic type flown into lambda method linker#1416? That doesn't seem right. Maybe this method should just have
[RequiresDynamicCode]on it.
| /// for <typeparamref name="TValue"/> or its serializable members. | ||
| /// </exception> | ||
| [RequiresUnreferencedCode(SerializationUnreferencedCodeMessage)] | ||
| [RequiresDynamicCode(SerializationUnreferencedCodeMessage)] |
There was a problem hiding this comment.
I'm not sure the existing SerializationUnreferencedCodeMessage is the right message for RequiresDynamicCode. It says:
"JSON serialization and deserialization might require types that cannot be statically analyzed. Use the overload that takes a JsonTypeInfo or JsonSerializerContext, or make sure all of the required types are preserved."
I'm not sure that advice works correctly for requiring dynamic code.
|
|
||
| [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", | ||
| Justification = "The ctor is marked with RequiresUnreferencedCode.")] | ||
| [UnconditionalSuppressMessage("AOT", "IL3050:Calling members annotated with 'RequiresDynamicCodeAttribute' may break functionality when AOT compiling.", Justification = "<Pending>")] |
There was a problem hiding this comment.
could they re-use same attributes rather than doubling them?
| { | ||
| public override bool CanConvert(Type typeToConvert) => GetAsyncEnumerableInterface(typeToConvert) is not null; | ||
|
|
||
| [UnconditionalSuppressMessage("AOT", "IL3050:Calling members annotated with 'RequiresDynamicCodeAttribute' may break functionality when AOT compiling.", Justification = "<Pending>")] |
There was a problem hiding this comment.
Unless we have guarantees that the typeToConvert and elementType are always reference type, or the code got compiled through other means, this is not safe to suppress.
| return converter; | ||
| } | ||
|
|
||
| [UnconditionalSuppressMessage("AOT", "IL3050:Calling members annotated with 'RequiresDynamicCodeAttribute' may break functionality when AOT compiling.", Justification = "<Pending>")] |
There was a problem hiding this comment.
Unless the key type and value type are reference types or code for that instantiation is available through other means, this is not safe to suppress.
| [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2055:MakeGenericType", | ||
| Justification = "'EnumConverter<T> where T : struct' implies 'T : new()', so the trimmer is warning calling MakeGenericType here because enumType's constructors are not annotated. " + | ||
| "But EnumConverter doesn't call new T(), so this is safe.")] | ||
| [UnconditionalSuppressMessage("AOT", "IL3050:Calling members annotated with 'RequiresDynamicCodeAttribute' may break functionality when AOT compiling.", Justification = "<Pending>")] |
There was a problem hiding this comment.
Enum types are valuetypes, the MakeGenericType will likely throw 100% of time.
There was a problem hiding this comment.
You might consider suppressing the warning here and add an annotation in the converter factory constructor, as is done here:
The factory constructors are only invoked in the context of reflection serialization code paths, with the notable exception of JsonStringEnumConverter which is a public class. It would likely require an annotation on its constructors.
| [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2055:MakeGenericType", | ||
| Justification = "'NullableConverter<T> where T : struct' implies 'T : new()', so the trimmer is warning calling MakeGenericType here because valueTypeToConvert's constructors are not annotated. " + | ||
| "But NullableConverter doesn't call new T(), so this is safe.")] | ||
| [UnconditionalSuppressMessage("AOT", "IL3050:Calling members annotated with 'RequiresDynamicCodeAttribute' may break functionality when AOT compiling.", Justification = "<Pending>")] |
There was a problem hiding this comment.
Same as for the EnumConverter above.
| #endif | ||
| } | ||
|
|
||
| [UnconditionalSuppressMessage("AOT", "IL3050:Calling members annotated with 'RequiresDynamicCodeAttribute' may break functionality when AOT compiling.", Justification = "<Pending>")] |
There was a problem hiding this comment.
Same concern as the other MakeGenericType comments
| { | ||
| #if NETCOREAPP | ||
| [RequiresDynamicCode("Runtime code generation is not available for Aot form factor")] | ||
| [UnconditionalSuppressMessage("AotAnalysis", "IL3051:RequiresDynamicCode", |
There was a problem hiding this comment.
It doesn't look right that we need this suppression if the type is RDC.
| { | ||
| #if NETCOREAPP | ||
| [RequiresDynamicCode("Runtime code generation is not available for Aot form factor")] | ||
| [UnconditionalSuppressMessage("AotAnalysis", "IL3051:RequiresDynamicCode", |
There was a problem hiding this comment.
Same - we shouldn't need this. If this type is RDC, we can't construct an instance of it without a warning. It should be okay to have mismatched virtual override annotations after that because we'd be warned at the time the instance is constructed.
|
I'm guessing we should we close this in favor of #68464? |
The annotation falls into two categories
DynamicMethodcalls: AllDynamicMethodcalls are behind the runtime feature switch and propagated up to the switch method and suppressedMakeGenericXXXin the trimmer but by usingRequiresDynamicCode(same message as trimmer)This PR takes a dependency on a pending API request and hence is in a draft form.