Align Async.Await with fslang-suggestions #840 (raise TaskCanceledException on cancel) - #677
Open
T-Gro wants to merge 1 commit into
Open
Align Async.Await with fslang-suggestions #840 (raise TaskCanceledException on cancel)#677T-Gro wants to merge 1 commit into
T-Gro wants to merge 1 commit into
Conversation
A cancelled Task is now surfaced through the exception continuation as a TaskCanceledException (ec) instead of the cancellation continuation (cc), so it can be caught by an ordinary try/with around the Await, matching C# await and Async.AwaitTask. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
T-Gro
force-pushed
the
tgro-align-await
branch
from
August 10, 2026 08:59
e4c56af to
747e3f1
Compare
6 tasks
gusty
self-requested a review
August 10, 2026 09:30
There was a problem hiding this comment.
Pull request overview
Aligns Async.Await’s cancellation semantics with fslang-suggestions #840 by surfacing a canceled Task as a catchable TaskCanceledException via the exception continuation (rather than treating it as async cancellation), and updates tests accordingly.
Changes:
- Updated
Async.Await(forTask<'T>andTask) to routeIsCanceledthrough the exception continuation (ec) withTaskCanceledException. - Updated async zip tests to use a truly canceled
Async(via cancellation continuation) rather than relying on awaiting a canceledTask. - Added tests asserting a canceled
Task/Task<'T>awaited viaAsync.Awaitraises aTaskCanceledExceptioncatchable bytry/with.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
src/FSharpPlus/Extensions/Extensions.fs |
Changes Async.Await cancellation path to raise TaskCanceledException via exception continuation. |
tests/FSharpPlus.Tests/Asyncs.fs |
Adjusts zip test inputs to produce genuine async cancellation independent of Async.Await behavior. |
tests/FSharpPlus.Tests/Task.fs |
Adds coverage to ensure awaiting canceled tasks raises TaskCanceledException catchable by try/with. |
Suppressed comments (1)
src/FSharpPlus/Extensions/Extensions.fs:200
- Same as the generic overload: prefer
TaskCanceledException(task)overTaskCanceledException()so the thrown exception is associated with the awaited task (matching typicalawaitsemantics) and preserves the Task reference for diagnostics.
if task.IsFaulted then
let e = Unchecked.nonNull task.Exception
if e.InnerExceptions.Count = 1 then ec e.InnerExceptions[0]
else ec e
elif task.IsCanceled then ec (TaskCanceledException ())
else sc ())
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Comment on lines
168
to
173
| if task.IsFaulted then | ||
| let e = Unchecked.nonNull task.Exception | ||
| if e.InnerExceptions.Count = 1 then ec e.InnerExceptions[0] | ||
| else ec e | ||
| elif task.IsCanceled then cc (TaskCanceledException ()) | ||
| elif task.IsCanceled then ec (TaskCanceledException ()) | ||
| else sc task.Result) |
wallymathieu
approved these changes
Aug 10, 2026
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.
Aligns
Async.Awaitwith fslang-suggestions #840, as requested in dotnet/fsharp#19785 (comment) and tracked by #676.What
On cancellation, both
Awaitoverloads (Task<'T>andTask) now call the exception continuation with aTaskCanceledException(ec) instead of the cancellation continuation (cc):Why
With
cc, a cancelledTaskpropagated as an async cancellation, so atry ... with :? TaskCanceledException ->placed around theAwaitwould not catch it. Withecit is surfaced as an ordinary exception, catchable locally — matching C#awaitand everyAwaitTaskCorrect-derived implementation. The doc comment already described this behaviour.Note:
Async.map2/map3/zipbuild onAwait, so a purely-cancelled input now surfaces as aTaskCanceledExceptionrather than a cancellation. Where cancellation is combined with a fault, the fault still wins (cancellation dropped inTask.map*before reachingAwait).Tests
Asyncs.fszip tests build their cancellation input directly (they previously relied onAwaitof a cancelledTaskyielding a cancellation).Task.fscoverage asserting a cancelledTask/Task<'T>await raises aTaskCanceledExceptioncatchable bytry/with.