Skip to content

net11.0: Patch<T>'s JSON converter as an open generic, without the registry, if Native AOT holds #262

Open

Description

@CaffeinatedCoder

Problem

Patch<T> reaches its converter through PatchJsonConverterFactory. Each closed Patch<T>'s static constructor registers its converter, and the factory runs that constructor with RuntimeHelpers.RunClassConstructor under an [UnconditionalSuppressMessage] (IL2059). The workaround exists because the source generator refused an open generic [JsonConverter] (SYSLIB1220), and MakeGenericType has no code under Native AOT (design/patch.md, "The converter, and Native AOT"; spikes/MergePatch).

.NET 11 lifts that refusal. [JsonConverter(typeof(Converter<>))] on a generic type is closed over the type's arguments, by the reflection provider and by the source generator (What's new in .NET 11 libraries, dotnet/runtime#123209). Native AOT isn't documented.

Change

On net11.0 only (#208), Patch<T> carries [JsonConverter(typeof(PatchJsonConverter<>))], with no static constructor and no registry. net10.0 keeps the factory. PatchJsonConverterFactory stays public on both targets, since removing it would be breaking.

Measure first:

  • Native AOT. The smoke test's aot consumer on net11.0 reads and writes a patch of a primitive, of a value object and of a type listed in the context, under a source-generated context and under reflection.
  • Visibility. Check whether the generator creates the converter from the consumer's code. If it does, PatchJsonConverter<T> (internal today) becomes public with EditorBrowsable(Never) on net11.0: a new public type that needs a claim or a waiver.
  • Parity. The three states and the bytes must be the same on both targets, and a source-generated context must need the same types listed on both (decision 120: a shared member behaves the same). With the open converter, the generator may produce metadata for T itself, which would change that.

If Native AOT or parity fails, close the issue with the measurement and keep the factory.

Done when

  • The Patch tests run on both targets.
  • The Native AOT smoke test covers a patch on net11.0.
  • The net11.0 build has no IL2059 suppression for Patch.
  • design/patch.md says which target uses which converter.

Blocked by #208.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area/aotNative AOT and trimmingarea/jsonSystem.Text.Json wire forms, values and dictionary keyschoreBuild, CI, tooling, packaging, refactoring with no behaviour changepackage/coreAffects CodoMetis.TypeKit

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions