Uh oh!
There was an error while loading. Please reload this page.
Avoid stripping IL of non-async Task-returning methods - #129884
Conversation
The IL of these may be needed at runtime to compile async versions.
There was a problem hiding this comment.
Pull request overview
This change updates ReadyToRun IL body stripping so the compiler retains real IL for methods whose IL may be needed at runtime (notably synchronous Task/ValueTask-returning methods that can have async variants), instead of replacing their bodies with the minimal throwing stub when --strip-il-bodies is enabled.
Changes:
- Replaces the previous “non-generic only” strip condition with a helper (
MayNeedILAtRuntime) that centralizes the decision. - Preserves IL for generic methods/types (existing behavior) and additionally for non-async
Task/ValueTask-returning methods.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
jakobbotsch
commented
Jun 26, 2026
Once the crossgen2 support makes it in we could also consider being a bit more precise -- we can strip the IL body if we have compiled both the async and non-async variants. |
jakobbotsch
commented
Jun 29, 2026
/backport to release/11.0-preview6 |
Started backporting to |
…g methods (#129975) Backport of #129884 to release/11.0-preview6 /cc @jakobbotsch ## Customer Impact - [X] Customer reported - [ ] Found internally Crossgen2 may strip IL of Task-returning methods that will be needed at runtime if runtime async is enabled. This results in `NullReferenceException` at runtime. Reported in #129813. ## Regression - [X] Yes - [ ] No Introduced in #128384 that started depending on user IL when compiling async variants of non-async Task/ValueTask-returning methods. ## Testing Verified that customer's test case progresses further when IL stripping is disabled. ## Risk Low. Disable stripping of IL for non-async Task-returning methods. Co-authored-by: Jakob Botsch Nielsen <jakob.botsch.nielsen@gmail.com>
Adds an ILCompiler.ReadyToRun.Tests case that crossgen2-composites a small runtime-async assembly with --strip-il-bodies and inspects the emitted component MSIL to assert every branch of the strip decision, covering the regression from dotnet#129813 fixed by dotnet#129884. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Adds an ILCompiler.ReadyToRun.Tests case that crossgen2-composites a small runtime-async assembly with --strip-il-bodies and inspects the emitted component MSIL to assert every branch of the strip decision, covering the regression from dotnet#129813 fixed by dotnet#129884. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
## Description The `--strip-il-bodies` optimization in crossgen2 is applied when building the composite ReadyToRun images that ship in the Apple mobile runtime packs, and in #129813 it regressed by stripping the IL of non-async `Task`/`ValueTask`-returning methods. That IL is still needed, because with runtime-async enabled the runtime compiles a runtime-async variant of such a method from its IL, so replacing it with a `ldnull` throw stub threw `NullReferenceException` on the mobile packs until #129884 narrowed the pass via `MayNeedILAtRuntime`. This PR adds a deterministic `ILCompiler.ReadyToRun.Tests` tests that inspect the emitted component MSIL to assert every branch of the strip logic. Non-async `Task<T>`/`ValueTask<T>`/`Task`/`ValueTask`-returning methods, a generic method, and a method on a generic type keep their IL, while plain methods and async `Task<T>`/`ValueTask` methods are still stripped. TODO: This PR should be aligned with #130025 --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The IL of these may be needed at runtime to compile async versions.
## Description The `--strip-il-bodies` optimization in crossgen2 is applied when building the composite ReadyToRun images that ship in the Apple mobile runtime packs, and in #129813 it regressed by stripping the IL of non-async `Task`/`ValueTask`-returning methods. That IL is still needed, because with runtime-async enabled the runtime compiles a runtime-async variant of such a method from its IL, so replacing it with a `ldnull` throw stub threw `NullReferenceException` on the mobile packs until #129884 narrowed the pass via `MayNeedILAtRuntime`. This PR adds a deterministic `ILCompiler.ReadyToRun.Tests` tests that inspect the emitted component MSIL to assert every branch of the strip logic. Non-async `Task<T>`/`ValueTask<T>`/`Task`/`ValueTask`-returning methods, a generic method, and a method on a generic type keep their IL, while plain methods and async `Task<T>`/`ValueTask` methods are still stripped. TODO: This PR should be aligned with #130025 --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The IL of these may be needed at runtime to compile async versions.
Fix#129813