Skip to content

fix(js/ts/python): settle async continuations once - #5081

Merged
dbrattli merged 1 commit into
fix/async-cleanup-generic-continuationsfrom
fix/async-cleanup-generic-continuations-2
Oct 15, 2026
Merged

dbrattli merged 1 commit into
fix/async-cleanup-generic-continuationsfrom
fix/async-cleanup-generic-continuations-2

Conversation

@MangelMaxime

Copy link
Copy Markdown
Member

@dbrattli Here is what I found while reviewing #5062

Summary

Fixes async cleanup ordering and generic unit continuations in the Python runtime, with the same
fixes mirrored in the TypeScript runtime where they applied.

Runtime fixes (Python and TypeScript)

  • TryFinally and Using install the cleanup continuation before the cancellation checkpoint, so a
    pre-cancelled token still runs compensation.
  • TryFinally claims settlement under a lock in Python; on_cancel can arrive from another thread
    while on_success runs on the loop.
  • Trampoline gains a completed flag (Python now matches TypeScript). After a terminal continuation
    runs, exceptions thrown by continuation code propagate instead of being routed back to on_error,
    which previously re-entered a succeeded try/with handler.
  • protected_bind and TryWith only guard the binder or handler evaluation, not the resulting
    computation.
  • from_continuations rejects a second completion with InvalidOperationException, matching .NET.
    from_continuations_unit is now built on top of it and shares the guard.
  • MailboxProcessor.PostAndAsyncReply delivers exactly once when the reply races with the poster's
    start, and ignores a second Reply, matching .NET AsyncReplyChannel.
  • Python Trampoline.run only looks up the event loop on the hijack path and runs inline when no loop
    is running.

Python compiler

  • Callbacks whose generic parameter is instantiated to unit are wrapped with erase_unit_callable
    so Pyright accepts the erased unit argument. This now also covers spread (ParamArray) calls,
    curried applications, and calls to local generic functions.
  • Local generic functions lose their declared signature at the call site (uncurryApplications
    emits empty signature types and the identifier type is already instantiated). The Python
    Context now records declared lambda types at Let/LetRec and uses them as a fallback.

@dbrattli
dbrattli merged commit 18ce662 into fix/async-cleanup-generic-continuations Oct 15, 2026
8 checks passed
@dbrattli
dbrattli deleted the fix/async-cleanup-generic-continuations-2 branch October 15, 2026 18:34
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.

2 participants