Skip to content

Fix #3777: decompile runtime async without a separate C# 15 setting#3791

Merged
siegfriedpammer merged 1 commit into
masterfrom
fix-3777-drop-runtime-async-setting
Jun 17, 2026
Merged

Fix #3777: decompile runtime async without a separate C# 15 setting#3791
siegfriedpammer merged 1 commit into
masterfrom
fix-3777-drop-runtime-async-setting

Conversation

@siegfriedpammer

Copy link
Copy Markdown
Member

Fixes #3777.

Runtime async is a compiler feature, not a language feature: there is no dotnet/csharplang spec for it, and Roslyn emits it even in older language versions when enabled. ILSpy decompiles runtime-async methods back into ordinary async/await, which is a C# 5 construct. Gating that reconstruction on C# 15 needlessly produced worse output whenever a lower language version was selected.

Rather than just re-gate the toggle to C# 5, this removes the standalone RuntimeAsync setting entirely and folds its behavior into the existing AsyncAwait ("Decompile async methods") setting. The separate toggle was redundant: AsyncAwaitDecompiler.Run already early-returns when AsyncAwait is disabled, so the runtime-async transforms were always nested inside that gate. Runtime async now follows the single async/await toggle, exactly like state-machine async.

Changes

  • Remove the RuntimeAsync property from DecompilerSettings (plus its C# 15 version-gating in SetLanguageVersion/GetMinimumRequiredVersion) and its resource string.
  • Route the three consumers (DecompilerTypeSystem.GetOptions, AsyncAwaitDecompiler, EarlyExpressionTransforms) through AsyncAwait.

Notes

  • Settings persistence is reflection-based, so a stale RuntimeAsync attribute in saved settings is silently ignored on load; no migration needed.
  • The orphaned "C# 15.0" options group disappears automatically since the UI reflects properties.

Testing

  • Built the desktop solution filter cleanly (0 warnings/errors).
  • Ran the RuntimeAsync* pretty tests locally (RuntimeAsync, RuntimeAsyncForeach, RuntimeAsyncMain, RuntimeAsyncStreams, RuntimeAsyncUsing, RuntimeAsyncCustomTaskType): all 12 cases pass.

Runtime async is a compiler feature that emits ordinary async/await (a
C# 5 construct), so reconstructing it should not require selecting C# 15.
The dedicated RuntimeAsync setting was also redundant: AsyncAwaitDecompiler
already runs the runtime-async transforms only when AsyncAwait is enabled.
Fold the behavior into the AsyncAwait setting and drop the separate toggle.

Assisted-by: Claude:claude-opus-4-8:Claude Code
@siegfriedpammer
siegfriedpammer merged commit f2e17b6 into master Jun 17, 2026
11 checks passed
@christophwille
christophwille deleted the fix-3777-drop-runtime-async-setting branch June 23, 2026 10:35
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.

Decompiling runtime async should not be gated on C# 15.

1 participant