Skip to content

Commit a3bf1fc

Browse files
authored
Merge pull request swiftlang#75248 from DougGregor/unsafe-inherit-executor-the-rest
Extend _unsafeInheritExecutor_ to remaining @_unsafeInheritExecutor APIs
2 parents cc55495 + a47483c commit a3bf1fc

File tree

8 files changed

+107
-17
lines changed

8 files changed

+107
-17
lines changed

lib/Sema/TypeCheckAttr.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7275,7 +7275,10 @@ void AttributeChecker::visitUnsafeInheritExecutorAttr(
72757275
auto fn = cast<FuncDecl>(D);
72767276
if (!fn->isAsyncContext()) {
72777277
diagnose(attr->getLocation(), diag::inherits_executor_without_async);
7278-
} else {
7278+
} else if (fn->getBaseName().isSpecial() ||
7279+
!fn->getParentModule()->getName().str().equals("_Concurrency") ||
7280+
!fn->getBaseIdentifier().str()
7281+
.startswith("_unsafeInheritExecutor_")) {
72797282
bool inConcurrencyModule = D->getDeclContext()->getParentModule()->getName()
72807283
.str().equals("_Concurrency");
72817284
auto diag = fn->diagnose(diag::unsafe_inherits_executor_deprecated);

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2105,7 +2105,8 @@ void swift::introduceUnsafeInheritExecutorReplacements(
21052105

21062106
auto isReplaceable = [&](ValueDecl *decl) {
21072107
return isa<FuncDecl>(decl) && inConcurrencyModule(decl->getDeclContext()) &&
2108-
decl->getDeclContext()->isModuleScopeContext();
2108+
decl->getDeclContext()->isModuleScopeContext() &&
2109+
cast<FuncDecl>(decl)->hasAsync();
21092110
};
21102111

21112112
// Make sure at least some of the entries are functions in the _Concurrency
@@ -2160,7 +2161,8 @@ void swift::introduceUnsafeInheritExecutorReplacements(
21602161
return;
21612162

21622163
auto isReplaceable = [&](ValueDecl *decl) {
2163-
return isa<FuncDecl>(decl) && inConcurrencyModule(decl->getDeclContext());
2164+
return isa<FuncDecl>(decl) && inConcurrencyModule(decl->getDeclContext()) &&
2165+
cast<FuncDecl>(decl)->hasAsync();
21642166
};
21652167

21662168
// Make sure at least some of the entries are functions in the _Concurrency

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

stdlib/public/Concurrency/TaskLocal.swift

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -265,14 +265,16 @@ public final class TaskLocal<Value: Sendable>: Sendable, CustomStringConvertible
265265
return try await operation()
266266
}
267267

268+
@_silgen_name("$ss9TaskLocalC13withValueImpl_9operation4file4lineqd__xn_qd__yYaKXESSSutYaKlF")
268269
@inlinable
269270
@discardableResult
270271
@_unsafeInheritExecutor // internal for backwards compatibility; though may be able to be removed safely?
271272
@available(SwiftStdlib 5.1, *)
272-
@backDeployed(before: SwiftStdlib 5.9)
273-
internal func withValueImpl<R>(_ valueDuringOperation: __owned Value,
274-
operation: () async throws -> R,
275-
file: String = #fileID, line: UInt = #line) async rethrows -> R {
273+
internal func _unsafeInheritExecutor_withValueImpl<R>(
274+
_ valueDuringOperation: __owned Value,
275+
operation: () async throws -> R,
276+
file: String = #fileID, line: UInt = #line
277+
) async rethrows -> R {
276278
_taskLocalValuePush(key: key, value: consume valueDuringOperation)
277279
defer { _taskLocalValuePop() }
278280

test/Concurrency/unsafe_inherit_executor.swift

Lines changed: 58 additions & 2 deletions
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
@@ -113,10 +117,62 @@ func unsafeCallerAvoidsNewLoop() async throws {
113117
} onCancel: {
114118
}
115119

116-
await TL.$string.withValue("hello") {
120+
TL.$string.withValue("hello") {
121+
print(TL.string)
122+
}
123+
124+
try await TL.$string.withValue("hello") {
125+
try await Task.sleep(nanoseconds: 500)
117126
print(TL.string)
118127
}
119128

120129
func operation() async throws -> Int { 7 }
121130
try await TL.$string.withValue("hello", operation: operation)
131+
132+
// FIXME: Clock.measure does not currently support this hack.
133+
// expected-error@+1{{#isolation (introduced by a default argument) cannot be used within an '@_unsafeInheritExecutor' function}}
134+
_ = try! await clock.measure {
135+
print("so very slow")
136+
try await Task.sleep(nanoseconds: 500)
137+
}
138+
139+
_ = await withDiscardingTaskGroup(returning: Int.self) { group in
140+
group.addTask {
141+
print("hello")
142+
}
143+
144+
return 5
145+
}
146+
147+
_ = try await withThrowingDiscardingTaskGroup(returning: Int.self) { group in
148+
group.addTask {
149+
print("hello")
150+
}
151+
152+
return 5
153+
}
154+
155+
_ = await withTaskExecutorPreference(nil) {
156+
print("hello")
157+
}
158+
159+
_ = await withTaskGroup(of: Int.self, returning: Int.self) { group in
160+
group.addTask {
161+
return 5
162+
}
163+
164+
return 5
165+
}
166+
167+
_ = try await withThrowingTaskGroup(of: Int.self, returning: Int.self) { group in
168+
group.addTask {
169+
throw MyError.fail
170+
}
171+
172+
throw MyError.fail
173+
}
122174
}
175+
176+
@_unsafeInheritExecutor
177+
func _unsafeInheritExecutor_hacky() async { }
178+
// expected-warning@-1{{@_unsafeInheritExecutor attribute is deprecated; consider an 'isolated' parameter defaulted to '#isolation' instead}}

test/api-digester/stability-concurrency-abi.test

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,12 @@ Func TaskLocal.withValue(_:operation:file:line:) has parameter 1 type change fro
118118
Func TaskLocal.withValue(_:operation:file:line:) has parameter 1 type change from () throws -> τ_1_0 to () async throws -> τ_1_0
119119
Func TaskLocal.withValue(_:operation:file:line:) has parameter 2 type change from Swift.String to (any _Concurrency.Actor)?
120120
Func TaskLocal.withValue(_:operation:file:line:) has parameter 3 type change from Swift.UInt to Swift.String
121+
Func withTaskGroup(of:returning:body:) has parameter 2 type change from (inout _Concurrency.TaskGroup<τ_0_0>) async -> τ_0_1 to (any _Concurrency.Actor)?
122+
Func withThrowingTaskGroup(of:returning:body:) has been renamed to Func withThrowingTaskGroup(of:returning:isolation:body:)
123+
Func withThrowingTaskGroup(of:returning:body:) has mangled name changing from '_Concurrency.withThrowingTaskGroup<A, B where A: Swift.Sendable>(of: A.Type, returning: B.Type, body: (inout Swift.ThrowingTaskGroup<A, Swift.Error>) async throws -> B) async throws -> B' to '_Concurrency.withThrowingTaskGroup<A, B where A: Swift.Sendable>(of: A.Type, returning: B.Type, isolation: isolated Swift.Optional<Swift.Actor>, body: (inout Swift.ThrowingTaskGroup<A, Swift.Error>) async throws -> B) async throws -> B'
124+
Func withThrowingTaskGroup(of:returning:body:) has parameter 2 type change from (inout _Concurrency.ThrowingTaskGroup<τ_0_0, any Swift.Error>) async throws -> τ_0_1 to (any _Concurrency.Actor)?
125+
Func withTaskGroup(of:returning:body:) has been renamed to Func withTaskGroup(of:returning:isolation:body:)
126+
Func withTaskGroup(of:returning:body:) has mangled name changing from '_Concurrency.withTaskGroup<A, B where A: Swift.Sendable>(of: A.Type, returning: B.Type, body: (inout Swift.TaskGroup<A>) async -> B) async -> B' to '_Concurrency.withTaskGroup<A, B where A: Swift.Sendable>(of: A.Type, returning: B.Type, isolation: isolated Swift.Optional<Swift.Actor>, body: (inout Swift.TaskGroup<A>) async -> B) async -> B'
121127

122128
// *** DO NOT DISABLE OR XFAIL THIS TEST. *** (See comment above.)
123129

0 commit comments

Comments
 (0)