Skip to content

Commit d80cdb9

Browse files
committed
Extend _unsafeInheritExecutor_ to remaining @_unsafeInheritExecutor APIs
Extend the _unsafeInheritExecutor_ workaround to all remaining APIs in the Concurrency library that have adopted `#isolation` default arguments to (safely) stay in the caller's isolation domain... ... except one. Clock.measure() is currently running into problems with the type checker workaround and needs a little more thought. Fixes rdar://131760111.
1 parent 817e1c1 commit d80cdb9

File tree

4 files changed

+77
-9
lines changed

4 files changed

+77
-9
lines changed

stdlib/public/Concurrency/DiscardingTaskGroup.swift

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -90,11 +90,16 @@ public func withDiscardingTaskGroup<GroupResult>(
9090
return result
9191
}
9292

93+
// Note: hack to stage out @_unsafeInheritExecutor forms of various functions
94+
// in favor of #isolation. The _unsafeInheritExecutor_ prefix is meaningful
95+
// to the type checker.
96+
//
97+
// This function also doubles as an ABI-compatibility shim predating the
98+
// introduction of #isolation.
9399
@available(SwiftStdlib 5.9, *)
94-
@usableFromInline
95100
@_unsafeInheritExecutor // for ABI compatibility
96101
@_silgen_name("$ss23withDiscardingTaskGroup9returning4bodyxxm_xs0bcD0VzYaXEtYalF")
97-
internal func __abi_withDiscardingTaskGroup<GroupResult>(
102+
public func _unsafeInheritExecutor_withDiscardingTaskGroup<GroupResult>(
98103
returning returnType: GroupResult.Type = GroupResult.self,
99104
body: (inout DiscardingTaskGroup) async -> GroupResult
100105
) async -> GroupResult {
@@ -637,10 +642,9 @@ public func withThrowingDiscardingTaskGroup<GroupResult>(
637642
}
638643

639644
@available(SwiftStdlib 5.9, *)
640-
@usableFromInline
641645
@_unsafeInheritExecutor // for ABI compatibility
642646
@_silgen_name("$ss31withThrowingDiscardingTaskGroup9returning4bodyxxm_xs0bcdE0Vys5Error_pGzYaKXEtYaKlF")
643-
internal func __abi_withThrowingDiscardingTaskGroup<GroupResult>(
647+
public func _unsafeInheritExecutor_withThrowingDiscardingTaskGroup<GroupResult>(
644648
returning returnType: GroupResult.Type = GroupResult.self,
645649
body: (inout ThrowingDiscardingTaskGroup<Error>) async throws -> GroupResult
646650
) async throws -> GroupResult {

stdlib/public/Concurrency/Task+TaskExecutor.swift

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,11 +159,17 @@ public func withTaskExecutorPreference<T, Failure>(
159159
return try await operation()
160160
}
161161

162+
// Note: hack to stage out @_unsafeInheritExecutor forms of various functions
163+
// in favor of #isolation. The _unsafeInheritExecutor_ prefix is meaningful
164+
// to the type checker.
165+
//
166+
// This function also doubles as an ABI-compatibility shim predating the
167+
// introduction of #isolation.
162168
@_unavailableInEmbedded
163169
@available(SwiftStdlib 6.0, *)
164170
@_unsafeInheritExecutor // for ABI compatibility
165171
@_silgen_name("$ss26withTaskExecutorPreference_9operationxSch_pSg_xyYaYbKXEtYaKs8SendableRzlF")
166-
public func __abi__withTaskExecutorPreference<T: Sendable>(
172+
public func _unsafeInheritExecutor_withTaskExecutorPreference<T: Sendable>(
167173
_ taskExecutor: (any TaskExecutor)?,
168174
operation: @Sendable () async throws -> T
169175
) async rethrows -> T {

stdlib/public/Concurrency/TaskGroup.swift

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,11 +90,17 @@ public func withTaskGroup<ChildTaskResult, GroupResult>(
9090
#endif
9191
}
9292

93+
// Note: hack to stage out @_unsafeInheritExecutor forms of various functions
94+
// in favor of #isolation. The _unsafeInheritExecutor_ prefix is meaningful
95+
// to the type checker.
96+
//
97+
// This function also doubles as an ABI-compatibility shim predating the
98+
// introduction of #isolation.
9399
@available(SwiftStdlib 5.1, *)
94100
@_silgen_name("$ss13withTaskGroup2of9returning4bodyq_xm_q_mq_ScGyxGzYaXEtYar0_lF")
95101
@_unsafeInheritExecutor // for ABI compatibility
96102
@inlinable
97-
public func withTaskGroup<ChildTaskResult, GroupResult>(
103+
public func _unsafeInheritExecutor_withTaskGroup<ChildTaskResult, GroupResult>(
98104
of childTaskResultType: ChildTaskResult.Type,
99105
returning returnType: GroupResult.Type = GroupResult.self,
100106
body: (inout TaskGroup<ChildTaskResult>) async -> GroupResult
@@ -228,11 +234,16 @@ public func withThrowingTaskGroup<ChildTaskResult, GroupResult>(
228234
#endif
229235
}
230236

237+
// Note: hack to stage out @_unsafeInheritExecutor forms of various functions
238+
// in favor of #isolation. The _unsafeInheritExecutor_ prefix is meaningful
239+
// to the type checker.
240+
//
241+
// This function also doubles as an ABI-compatibility shim predating the
242+
// introduction of #isolation.
231243
@available(SwiftStdlib 5.1, *)
232244
@_silgen_name("$ss21withThrowingTaskGroup2of9returning4bodyq_xm_q_mq_Scgyxs5Error_pGzYaKXEtYaKr0_lF")
233245
@_unsafeInheritExecutor // for ABI compatibility
234-
@usableFromInline
235-
internal func withThrowingTaskGroup<ChildTaskResult, GroupResult>(
246+
public func _unsafeInheritExecutor_withThrowingTaskGroup<ChildTaskResult, GroupResult>(
236247
of childTaskResultType: ChildTaskResult.Type,
237248
returning returnType: GroupResult.Type = GroupResult.self,
238249
body: (inout ThrowingTaskGroup<ChildTaskResult, Error>) async throws -> GroupResult

test/Concurrency/unsafe_inherit_executor.swift

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,8 +88,12 @@ enum TL {
8888
static var string: String = "<undefined>"
8989
}
9090

91+
enum MyError: Error {
92+
case fail
93+
}
94+
9195
@_unsafeInheritExecutor
92-
func unsafeCallerAvoidsNewLoop() async throws {
96+
func unsafeCallerAvoidsNewLoop(clock: some Clock) async throws {
9397
// expected-warning@-1{{@_unsafeInheritExecutor attribute is deprecated; consider an 'isolated' parameter defaulted to '#isolation' instead}}
9498

9599
_ = await withUnsafeContinuation { (continuation: UnsafeContinuation<Int, Never>) in
@@ -119,4 +123,47 @@ func unsafeCallerAvoidsNewLoop() async throws {
119123

120124
func operation() async throws -> Int { 7 }
121125
try await TL.$string.withValue("hello", operation: operation)
126+
127+
// FIXME: Clock.measure does not currently support this hack.
128+
// expected-error@+1{{#isolation (introduced by a default argument) cannot be used within an '@_unsafeInheritExecutor' function}}
129+
_ = try! await clock.measure {
130+
print("so very slow")
131+
try await Task.sleep(nanoseconds: 500)
132+
}
133+
134+
_ = await withDiscardingTaskGroup(returning: Int.self) { group in
135+
group.addTask {
136+
print("hello")
137+
}
138+
139+
return 5
140+
}
141+
142+
_ = try await withThrowingDiscardingTaskGroup(returning: Int.self) { group in
143+
group.addTask {
144+
print("hello")
145+
}
146+
147+
return 5
148+
}
149+
150+
_ = await withTaskExecutorPreference(nil) {
151+
print("hello")
152+
}
153+
154+
_ = await withTaskGroup(of: Int.self, returning: Int.self) { group in
155+
group.addTask {
156+
return 5
157+
}
158+
159+
return 5
160+
}
161+
162+
_ = try await withThrowingTaskGroup(of: Int.self, returning: Int.self) { group in
163+
group.addTask {
164+
throw MyError.fail
165+
}
166+
167+
throw MyError.fail
168+
}
122169
}

0 commit comments

Comments
 (0)