Skip to content

Commit 9300ff9

Browse files
committed
Make CheckedContinuation and UnsafeContinuation unconditionally Sendable.
The continuation types were conditionally `Sendable` based on whether the result type of the continuation was `Sendable`. However, conceptually, the return value is never leaving the current task, so it is never actually crossing concurrency boundaries. Therefore, we can make the continuation types unconditionally `Sendable`. Fixes rdar://98462858.
1 parent e422a9c commit 9300ff9

File tree

5 files changed

+5
-18
lines changed

5 files changed

+5
-18
lines changed

stdlib/public/BackDeployConcurrency/CheckedContinuation.swift

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ internal final class CheckedContinuationCanary: @unchecked Sendable {
119119
/// you can replace one with the other in most circumstances,
120120
/// without making other changes.
121121
@available(SwiftStdlib 5.1, *)
122-
public struct CheckedContinuation<T, E: Error> {
122+
public struct CheckedContinuation<T, E: Error>: Sendable {
123123
private let canary: CheckedContinuationCanary
124124

125125
/// Creates a checked continuation from an unsafe continuation.
@@ -186,9 +186,6 @@ public struct CheckedContinuation<T, E: Error> {
186186
}
187187
}
188188

189-
@available(SwiftStdlib 5.1, *)
190-
extension CheckedContinuation: Sendable where T: Sendable { }
191-
192189
@available(SwiftStdlib 5.1, *)
193190
extension CheckedContinuation {
194191
/// Resume the task awaiting the continuation by having it either

stdlib/public/BackDeployConcurrency/PartialAsyncTask.swift

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ public struct UnownedJob: Sendable {
6969
/// without making other changes.
7070
@available(SwiftStdlib 5.1, *)
7171
@frozen
72-
public struct UnsafeContinuation<T, E: Error> {
72+
public struct UnsafeContinuation<T, E: Error>: Sendable {
7373
@usableFromInline internal var context: Builtin.RawUnsafeContinuation
7474

7575
@_alwaysEmitIntoClient
@@ -144,9 +144,6 @@ public struct UnsafeContinuation<T, E: Error> {
144144
}
145145
}
146146

147-
@available(SwiftStdlib 5.1, *)
148-
extension UnsafeContinuation: Sendable where T: Sendable { }
149-
150147
@available(SwiftStdlib 5.1, *)
151148
extension UnsafeContinuation {
152149
/// Resume the task that's awaiting the continuation

stdlib/public/Concurrency/CheckedContinuation.swift

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ internal final class CheckedContinuationCanary: @unchecked Sendable {
119119
/// you can replace one with the other in most circumstances,
120120
/// without making other changes.
121121
@available(SwiftStdlib 5.1, *)
122-
public struct CheckedContinuation<T, E: Error> {
122+
public struct CheckedContinuation<T, E: Error>: Sendable {
123123
private let canary: CheckedContinuationCanary
124124

125125
/// Creates a checked continuation from an unsafe continuation.
@@ -186,9 +186,6 @@ public struct CheckedContinuation<T, E: Error> {
186186
}
187187
}
188188

189-
@available(SwiftStdlib 5.1, *)
190-
extension CheckedContinuation: Sendable where T: Sendable { }
191-
192189
@available(SwiftStdlib 5.1, *)
193190
extension CheckedContinuation {
194191
/// Resume the task awaiting the continuation by having it either

stdlib/public/Concurrency/PartialAsyncTask.swift

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ public struct UnownedJob: Sendable {
6969
/// without making other changes.
7070
@available(SwiftStdlib 5.1, *)
7171
@frozen
72-
public struct UnsafeContinuation<T, E: Error> {
72+
public struct UnsafeContinuation<T, E: Error>: Sendable {
7373
@usableFromInline internal var context: Builtin.RawUnsafeContinuation
7474

7575
@_alwaysEmitIntoClient
@@ -144,9 +144,6 @@ public struct UnsafeContinuation<T, E: Error> {
144144
}
145145
}
146146

147-
@available(SwiftStdlib 5.1, *)
148-
extension UnsafeContinuation: Sendable where T: Sendable { }
149-
150147
@available(SwiftStdlib 5.1, *)
151148
extension UnsafeContinuation {
152149
/// Resume the task that's awaiting the continuation

test/Concurrency/async_tasks.swift

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,6 @@ func test_unsafeThrowingContinuations() async throws {
8989

9090
// ==== Sendability ------------------------------------------------------------
9191
class NotSendable { }
92-
// expected-note@-1{{class 'NotSendable' does not conform to the 'Sendable' protocol}}
9392

9493
@available(SwiftStdlib 5.1, *)
9594
func test_nonsendableContinuation() async throws {
@@ -99,7 +98,7 @@ func test_nonsendableContinuation() async throws {
9998

10099
let _: NotSendable = try await withUnsafeThrowingContinuation { continuation in
101100
Task {
102-
continuation.resume(returning: NotSendable()) // expected-warning{{capture of 'continuation' with non-sendable type 'UnsafeContinuation<NotSendable, any Error>' in a `@Sendable` closure}}
101+
continuation.resume(returning: NotSendable()) // okay
103102
}
104103
}
105104
}

0 commit comments

Comments
 (0)