Summary
TuiConfigurationBuilder.ConvertValue(string, Type) calls TypeDescriptor.GetConverter(Type) — which is annotated [RequiresUnreferencedCode]/[RequiresDynamicCode] — without any trim/AOT annotation or suppression. As a result, any NativeAOT (or trimmed) application that consumes TuiConfigurationBuilder fails to publish with IL2026 (and would hit IL3050). This is a regression introduced by #5411 (the CM→MEC migration): the sibling binding methods in the same file were annotated, but ConvertValue was missed.
Terminal.Gui advertises AOT/trim compatibility, so a published API on the primary configuration entry point breaking AOT consumers is a correctness gap.
Affected version
2.4.15 (stable) and the release/v2.4.14-beta.1 line — i.e. everything containing #5411. TuiConfigurationBuilder did not exist before #5411, so this ships in the first release that has it.
Repro
Any project with true that calls new TuiConfigurationBuilder(...) and binds settings, then:
dotnet publish .csproj -r osx-arm64 -c Release # or linux-x64 / win-x64
Concretely, tui-cs/Editor's examples/ted (NativeAOT) fails on all three RIDs. Real CI evidence:
Error (identical across osx-arm64 / linux-x64 / win-x64)
ILC : Trim analysis error IL2026: Terminal.Gui.Configuration.TuiConfigurationBuilder.ConvertValue(String,Type):
Using member 'System.ComponentModel.TypeDescriptor.GetConverter(Type)' which has 'RequiresUnreferencedCodeAttribute'
can break functionality when trimming application code. Generic TypeConverters may require the generic types to be
annotated. For example, NullableConverter requires the underlying type to be DynamicallyAccessedMembers All.
.../Terminal.Gui/2.4.15/lib/net10.0/Terminal.Gui.dll : error IL2104: Assembly 'Terminal.Gui' produced trim warnings.
ILC : ... exited with return value 0, but errors were detected during execution.
Root cause
In Terminal.Gui/Configuration/Settings/TuiConfigurationBuilder.cs (as of v2.4.15):
ConvertValue (~line 250) has a fast path for string/bool/int/Rune/enum, then falls back to TypeDescriptor.GetConverter(targetType) (~line 277) for any other type.
ConvertValue carries no [UnconditionalSuppressMessage] / [RequiresUnreferencedCode] / [RequiresDynamicCode] attribute.
- By contrast, the sibling methods in the same file (~lines 158, 169, 211 — e.g.
BindFlatDottedKeys, which is the caller) are annotated:
[UnconditionalSuppressMessage ("Trimming", "IL2026", Justification = "Settings POCOs are simple types preserved by DynamicDependency in ConfigPropertyHostTypes.")]
[UnconditionalSuppressMessage ("AOT", "IL3050", Justification = "Settings POCOs are simple types; no generic instantiation needed at runtime.")]
The caller's suppression does not silence the warning originating inside ConvertValue, so ILC reports it at the ConvertValue → GetConverter call site.
Suggested fix
Either:
- Annotate
ConvertValue consistently with the same [UnconditionalSuppressMessage("Trimming","IL2026")] + [UnconditionalSuppressMessage("AOT","IL3050")] (and matching justification) used on the sibling methods — if the "settings POCOs are simple types preserved by DynamicDependency" guarantee genuinely holds for the TypeConverter fallback path; or
- Make the fallback trim-safe — e.g. drop the
TypeDescriptor.GetConverter fallback (the scalar fast path already covers the common cases) and require non-scalar settings types to be handled explicitly, so the public binding path has no RequiresUnreferencedCode dependency at all.
Option 2 is the stronger guarantee for a public, AOT-advertised API; option 1 restores parity with the rest of the file as a minimal fix.
Impact
Blocks NativeAOT/trimmed downstream consumers (e.g. the tui-cs/Editor ted app and its release pipeline) from publishing against any #5411-containing Terminal.Gui.
Summary
TuiConfigurationBuilder.ConvertValue(string, Type)callsTypeDescriptor.GetConverter(Type)— which is annotated[RequiresUnreferencedCode]/[RequiresDynamicCode]— without any trim/AOT annotation or suppression. As a result, any NativeAOT (or trimmed) application that consumesTuiConfigurationBuilderfails to publish withIL2026(and would hitIL3050). This is a regression introduced by #5411 (the CM→MEC migration): the sibling binding methods in the same file were annotated, butConvertValuewas missed.Terminal.Gui advertises AOT/trim compatibility, so a published API on the primary configuration entry point breaking AOT consumers is a correctness gap.
Affected version
2.4.15(stable) and therelease/v2.4.14-beta.1line — i.e. everything containing #5411.TuiConfigurationBuilderdid not exist before #5411, so this ships in the first release that has it.Repro
Any project with
true that callsnew TuiConfigurationBuilder(...)and binds settings, then:Concretely,
tui-cs/Editor'sexamples/ted(NativeAOT) fails on all three RIDs. Real CI evidence:Error (identical across osx-arm64 / linux-x64 / win-x64)
Root cause
In
Terminal.Gui/Configuration/Settings/TuiConfigurationBuilder.cs(as ofv2.4.15):ConvertValue(~line 250) has a fast path forstring/bool/int/Rune/enum, then falls back toTypeDescriptor.GetConverter(targetType)(~line 277) for any other type.ConvertValuecarries no[UnconditionalSuppressMessage]/[RequiresUnreferencedCode]/[RequiresDynamicCode]attribute.BindFlatDottedKeys, which is the caller) are annotated:ConvertValue, so ILC reports it at theConvertValue→GetConvertercall site.Suggested fix
Either:
ConvertValueconsistently with the same[UnconditionalSuppressMessage("Trimming","IL2026")]+[UnconditionalSuppressMessage("AOT","IL3050")](and matching justification) used on the sibling methods — if the "settings POCOs are simple types preserved by DynamicDependency" guarantee genuinely holds for theTypeConverterfallback path; orTypeDescriptor.GetConverterfallback (the scalar fast path already covers the common cases) and require non-scalar settings types to be handled explicitly, so the public binding path has noRequiresUnreferencedCodedependency at all.Option 2 is the stronger guarantee for a public, AOT-advertised API; option 1 restores parity with the rest of the file as a minimal fix.
Impact
Blocks NativeAOT/trimmed downstream consumers (e.g. the
tui-cs/Editortedapp and its release pipeline) from publishing against any #5411-containing Terminal.Gui.