swiftlang / swiftlang/swift

withoutActuallyEscaping incorrectly requires captured values to be Sendable or sending in a nonisolated(nonsending) context

Open
#84,591 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug triage needed
Dominant language
Swift
Stars
70.4k
Forks
10.8k
PR merge metrics
PR metrics pending

Description

Description

The compiler seems to get confused when a non-Sendable and non-sending value is captured and used by the withoutActuallyEscaping body closure in a nonisolated(nonsending) context, requiring both the captured value as well as the closure parameter to be Sendable or sending.

withoutActuallyEscaping is special cased in the compiler but should presumably act like a nonisolated(nonsending) function itself in this context. Without any captures in the body closure it works as expected and the closure parameter isn't required to be Sendable or sending in that case.

Reproduction
// Compile with `swiftc -swift-version 6`

final class NS {}

// same issue also occurs when using NonisolatedNonsendingByDefault instead of nonisolated(nonsending)
nonisolated(nonsending) func test(
    _ nonSendable: NS,
    _ operation: () async -> Void
) async {
    await withoutActuallyEscaping(operation) { escapableOp in
        print(nonSendable) // Sending 'nonSendable' risks causing data races
        await escapableOp() // Sending 'operation' risks causing data races
    }
}
Expected behavior

The snippet should compile without errors.

Environment

Tested with main-snapshot-2025-09-29:

Apple Swift version 6.3-dev (LLVM 984f3dccb13e621, Swift 2a9d858583dc912)

and Swift 6.2:

swift-driver version: 1.127.14.1 Apple Swift version 6.2.1 (swiftlang-6.2.1.1.1 clang-1700.4.1.1)
Additional information

No response

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by compiling the provided reproduction with swiftc -swift-version 6 and inspect the compiler handling for withoutActuallyEscaping and nonisolated(nonsending) closures. The work is done when the snippet compiles without errors, including the captured non-Sendable value and closure parameter.

Written by the indexing model from the issue text.

Assessment

Tech stack
swift
Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
42/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.