Skip to content

Restore #5243 AOT fix lost in #5246 merge resolution#5249

Merged
tig merged 1 commit intodevelopfrom
aot-debug-5248
May 7, 2026
Merged

Restore #5243 AOT fix lost in #5246 merge resolution#5249
tig merged 1 commit intodevelopfrom
aot-debug-5248

Conversation

@tig
Copy link
Copy Markdown
Member

@tig tig commented May 7, 2026

Summary

The fix from #5243 ("Fixes #5259. AOT: use source-generated JSON serializer for dictionary construction in DeepCloner") was reverted when commit 94dca985d merged origin/main back into release/v2.1.0-rc.1. That merge had conflicts in DeepCloner.cs and ConfigurationManager.cs and the resolution picked main's pre-#5243 versions, silently dropping the fix.

PR #5246 (rc.1 → main) and PR #5247 (rc.1 backmerge → develop) then carried the broken state forward. v2.1.0-beta.1 was tagged before #5243 merged (no fix); v2.1.0-rc.1 was tagged after, but doesn't have it either because of the conflict resolution.

This PR restores Terminal.Gui/Configuration/DeepCloner.cs and Terminal.Gui/Configuration/ConfigurationManager.cs to their state at 11d6e27d7 (the original #5243 merge commit). The two files were checked out from that commit; no other changes.

Diff content

DeepCloner.cs — adds back the 26-line SourceGenerationContext.GetTypeInfoJsonSerializer.Deserialize(\"{}\", typeInfo) fallback in CreateDictionaryInstance (between the typed paths and Activator.CreateInstance), plus the // Typed paths… comment.

ConfigurationManager.cs — removes the 54-line per-type clone helpers (CloneHardCodedPropertyValue, CloneKeyBindings, ClonePlatformKeyBinding, CloneKeyArray) and reverts the call site back to DeepCloner.DeepClone(...). Generic dictionary handling lives in DeepCloner again.

Net: +28 / -53.

Repro before the fix (current develop)

dotnet publish Examples/NativeAot -c Release -r win-x64 --self-contained
./bin/Release/net10.0/win-x64/publish/NativeAot.exe

Crashes at module init:

Unhandled exception. System.MissingMethodException: No parameterless constructor defined for type
'System.Collections.Generic.Dictionary`2[Terminal.Gui.Drawing.ColorName16,System.String]'.
   at DeepCloner.CreateDictionaryInstance(...)
   at ConfigurationManager.Initialize() ...
   at RunModuleInitializers()

Same crash a downstream AOT consumer (gui-cs/clet) hit. Tracked through #5239#5240 (partial fix) → #5242 (residual) → #5243 (the right fix) → #5248 (filed when rc.1 still crashed — explained by this PR).

Verification

Build and pack of TG with this branch checked out:

dotnet build Terminal.Gui/Terminal.Gui.csproj -c Release    # 0 errors
dotnet pack  Terminal.Gui/Terminal.Gui.csproj -c Release --no-build --output local_packages

Then in gui-cs/clet on feature/makefile-releases, pinning <PackageReference Include=\"Terminal.Gui\" Version=\"2.1.1-aot-debug-5248.1\" />:

dotnet publish src/Clet -c Release -r win-x64 --self-contained -p:PublishAot=true -o publish/win-x64
./publish/win-x64/clet.exe --version    # was crashing against rc.1; now: 1.0.0-alpha (Terminal.Gui 2.1.1-aot-debug-5248.1), exit 0
./publish/win-x64/clet.exe list         # all 17 clets enumerate, exit 0

How to make sure this stays fixed

PR #5243 added a Dictionary<ColorName16, string> test in DeepClonerTests.cs — that test was retained through the merges (verified). However, the test runs in a non-AOT context and so does not exercise the actual AOT trim path that broke. An AOT regression test (publish Examples/NativeAot in CI and run it) would have caught this conflict-resolution regression. PR #5243's commit log mentions adding such CI; if it didn't make it through the same merge, that's a separate follow-up.

Linked

cc @tig

🤖 Generated with Claude Code

The fix from #5243 ("Fixes #5259. AOT: use source-generated JSON
serializer for dictionary construction in DeepCloner") was reverted
when release/v2.1.0-rc.1 merged origin/main back at 94dca98. That
merge had conflicts in DeepCloner.cs and ConfigurationManager.cs and
the resolution picked main's pre-#5243 versions, dropping:

  - 27 lines from DeepCloner.cs (the SourceGenerationContext.GetTypeInfo
    fallback in CreateDictionaryInstance, plus its leading comment)

and re-adding 54 lines to ConfigurationManager.cs:

  - CloneHardCodedPropertyValue and the per-type clone helpers
    (CloneKeyBindings, ClonePlatformKeyBinding, CloneKeyArray) that
    #5243 had removed in favor of generic DeepCloner handling
  - the call site change from DeepClone to CloneHardCodedPropertyValue

PRs #5246 (rc.1 → main) and #5247 (rc.1 backmerge → develop) carried
the broken state forward. v2.1.0-beta.1 was tagged before the merge
(no fix); v2.1.0-rc.1 was tagged after but doesn't have it either.

Repro: `dotnet publish Examples/NativeAot -c Release -r win-x64
--self-contained -p:PublishAot=true` against current develop crashes
at module init with `MissingMethodException: No parameterless
constructor defined for type Dictionary<ColorName16, string>`. Same
crash a downstream AOT consumer (clet) hit and tracked as #5239#5240#5242#5243#5248.

This commit checks DeepCloner.cs and ConfigurationManager.cs out of
11d6e27 (the original PR #5243 merge), restoring the source-gen
fallback and removing the per-type helpers. Verified locally:

  - `dotnet build Terminal.Gui/Terminal.Gui.csproj -c Release` → 0 errors
  - clet AOT publish + `clet.exe --version` runs cleanly (was crashing
    against rc.1; now exits 0 with the local TG nupkg pinned)

Refs #5239, #5242, #5243, #5248, #5259.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@tig tig merged commit ea205f3 into develop May 7, 2026
11 checks passed
@tig tig deleted the aot-debug-5248 branch May 7, 2026 22:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant