dotnet / runtime

.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.
https://docs.microsoft.com/dotnet/core/
MIT License
15.43k stars 4.76k forks source link

[net9.0-preview3]: NativeAOT System.Text.Json throws "System.NotSupportedException: 'System.Text.Json.Serialization.JsonDerivedTypeAttribute[]' is missing native code or metadata." #101205

Closed lambdageek closed 7 months ago

lambdageek commented 7 months ago

When compiling an app that uses System.Text.Json using NativeAOT, using .NET 9 Preview 3, the app throws an exception:

Unhandled exception. System.NotSupportedException: 'System.Text.Json.Serialization.JsonDerivedTypeAttribute[]' is missing native code or metadata. This can happen for code that is not compatible with trimming or AOT. Inspect and fix trimming and AOT related warnings that were generated when the app was published. For more information see https://aka.ms/nativeaot-compatibility
   at System.Reflection.Runtime.General.TypeUnifier.WithVerifiedTypeHandle(RuntimeArrayTypeInfo, RuntimeTypeInfo) + 0x78
   at System.Array.InternalCreate(RuntimeType, Int32, Int32*, Int32*) + 0xdc
   at System.Array.CreateInstance(Type, Int32) + 0x4c
   at System.Attribute.Instantiate(IEnumerable`1, Type) + 0xd8
   at System.Reflection.CustomAttributeExtensions.GetCustomAttributes[T](MemberInfo, Boolean) + 0x48
   at System.Text.Json.Serialization.Metadata.JsonPolymorphismOptions.CreateFromAttributeDeclarations(Type) + 0x9c
   at System.Text.Json.Serialization.Metadata.JsonTypeInfo.PopulatePolymorphismMetadata() + 0x18
   at System.Text.Json.Serialization.Metadata.JsonMetadataServices.CreateCore[T](JsonSerializerOptions, JsonObjectInfoValues`1) + 0xdc
   at ContractDescriptorParser.ContractDescriptorContext.Create_ContractDescriptor(JsonSerializerOptions) + 0xec
   at System.Text.Json.JsonSerializerOptions.GetTypeInfoNoCaching(Type) + 0x4c
   at System.Text.Json.JsonSerializerOptions.CachingContext.CreateCacheEntry(Type, JsonSerializerOptions.CachingContext) + 0x20
--- End of stack trace from previous location ---
   at System.Text.Json.JsonSerializerOptions.CachingContext.CacheEntry.GetResult() + 0x24
   at System.Text.Json.JsonSerializerOptions.GetTypeInfoInternal(Type, Boolean, Nullable`1, Boolean, Boolean) + 0x54
   at System.Text.Json.JsonSerializerOptions.GetTypeInfo(Type) + 0x4c
   at ContractDescriptorParser.ContractDescriptorContext.get_ContractDescriptor() + 0x30
   at ContractDescriptorParser.ParseCompact(ReadOnlySpan`1) + 0x3c
   at Program.<Main>$(String[] args) + 0x104
zsh: abort      ./bin/Release/net9.0/osx-arm64/native/roundtrip-json ./foo.jsonc

This is a regression from .NET 8.

Repro: https://github.com/lambdageek/roundtrip-json

dotnet-policy-service[bot] commented 7 months ago

Tagging subscribers to this area: @dotnet/area-system-text-json, @gregsdennis See info in area-owners.md if you want to be subscribed.

lambdageek commented 7 months ago

As a workaround I can add:


public class Root
{
        public static System.Text.Json.Serialization.JsonDerivedTypeAttribute[] r1 = new System.Text.Json.Serialization.JsonDerivedTypeAttribute[] {null};
}

roots.xml:

<linker>
  <assembly fullname="roundtrip-json">
    <type fullname="Root" preserve="all" />
  </assembly>
</linker>

and then add that as a root descriptor in my .csproj:

  <ItemGroup>
    <TrimmerRootDescriptor Include="roots.xml" />
  </ItemGroup>
jkotas commented 7 months ago

cc @MichalStrehovsky

MichalStrehovsky commented 7 months ago

This is what I fixed in #100626 (and #101048). Custom attribute activation has a suppression that assumes we can always create arrays of reference types but this is only possible if there's a __Canon[] template.

We have not been running a ton of tests since the test merging happened. This would have been caught there. I'm in the process of fixing the regressions in #100331.