Add runtime async tests for catching non-Exception throws#131112
Merged
VSadov merged 2 commits intoJul 21, 2026
Merged
Conversation
|
Azure Pipelines: 16 pipeline(s) were filtered out due to trigger conditions. There may be pipelines that require an authorized user to comment /azp run to run. |
Co-authored-by: VSadov <8218165+VSadov@users.noreply.github.com>
Copilot
AI
changed the title
[WIP] Add runtime async tests for catching non-Exception throws
Add runtime async tests for catching non-Exception throws
Jul 20, 2026
VSadov
marked this pull request as ready for review
July 21, 2026 19:25
|
Azure Pipelines: Successfully started running 1 pipeline(s). 15 pipeline(s) were filtered out due to trigger conditions. There may be pipelines that require an authorized user to comment /azp run to run. |
VSadov
merged commit Jul 21, 2026
457430a
into
copilot/runtime-async-tests-for-non-exceptions
71 of 74 checks passed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Runtime async (async2) is meant to match compiler state-machine async (async1). No coverage existed for catching objects that don't derive from
System.Exception(only throwable via IL), whereRuntimeCompatibilityAttribute(WrapNonExceptionThrows)governs whether the object surfaces as aRuntimeWrappedException. These tests close that hole and pin down where the two forms agree and diverge.Description
New tests under
src/tests/async/runtime-wrapped-exception/:NonExceptionThrower.il— IL helper that throws a non-Exceptionobject (a string), since C# can't express this.NoWrapThrowers.cs— helper assembly marked[assembly: RuntimeCompatibility(WrapNonExceptionThrows = false)]with async1/async2 throwers. The attribute is assembly-scoped, so an opt-out variant requires its own assembly.runtime-wrapped-exception.cs— awaits each thrower (async1 via[RuntimeAsyncMethodGeneration(false)], async2 by default) and asserts the caller observes aRuntimeWrappedExceptionwrapping the thrown object, for throws both before and after a suspension point, under bothWrapNonExceptionThrowssettings.Observed behavior:
WrapNonExceptionThrows = true(C#/CoreLib default): async1 and async2 match — caller seesRuntimeWrappedExceptionin all cases.WrapNonExceptionThrows = false: they match for a synchronous (pre-yield) throw and for async2 after a yield. They diverge for a non-Exception thrown after a suspension point — async2 faults theTaskwith aRuntimeWrappedException, while async1 lets the raw object escape onto the thread pool and crash the process.The divergent (crashing) case,
CatchAfterYield_NoWrap_Async1, is not exercised as a test: this reflects the older async1 behavior that is terminal to the process and is not something we plan to change, so it is left blocked with an explanatory comment rather than an[ActiveIssue]link. The remaining tests run.On NativeAOT a non-Exception thrown after a suspension point is not surfaced as a
RuntimeWrappedExceptionand terminates the process instead of faulting theTask, so the test project is blocked on NativeAOT (DisableProjectBuildwhenTestBuildMode == nativeaot), pending the follow-up #131111.