Skip to content

Commit 16119e5

Browse files
committed
[Concurrency] Lower availability for task names + addTask
1 parent ad2735c commit 16119e5

File tree

4 files changed

+189
-50
lines changed

4 files changed

+189
-50
lines changed

stdlib/public/Concurrency/Task+init.swift.gyb

Lines changed: 73 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ import Swift
1515
// ==== Task.init ------------------------------------------------
1616

1717
% for (METHOD_VARIANTS, ALL_AVAILABILITY, PARAMS) in [
18-
% (
19-
% [ # METHOD_VARIANT
18+
% # ==== Without task executor, but available ever since 5.1
19+
% ([ # METHOD_VARIANT
2020
% '',
2121
% 'THROWING',
2222
% ],
@@ -29,9 +29,7 @@ import Swift
2929
% 'priority: TaskPriority? = nil',
3030
% '@_inheritActorContext @_implicitSelfCapture operation: sending @escaping @isolated(any) () async throws -> Success',
3131
% ]),
32-
% # ====
33-
% (
34-
% [ # METHOD_VARIANT
32+
% ([ # METHOD_VARIANT
3533
% 'DETACHED',
3634
% 'DETACHED THROWING',
3735
% ],
@@ -44,46 +42,83 @@ import Swift
4442
% 'priority: TaskPriority? = nil',
4543
% 'operation: sending @escaping @isolated(any) () async throws -> Success',
4644
% ]),
45+
% # ==== With task executor, but available only since 6.0
46+
% ([ # METHOD_VARIANT
47+
% '',
48+
% 'THROWING',
49+
% ],
50+
% [ # ALL_AVAILABILITY
51+
% '@_alwaysEmitIntoClient',
52+
% '@available(SwiftStdlib 6.0, *)',
53+
% ],
54+
% [ # PARAMS
55+
% 'name: String?',
56+
% 'executorPreference taskExecutor: (any TaskExecutor)? = nil',
57+
% 'priority: TaskPriority? = nil',
58+
% '@_inheritActorContext @_implicitSelfCapture operation: sending @escaping @isolated(any) () async throws -> Success',
59+
% ]),
60+
% ([ # METHOD_VARIANT
61+
% 'DETACHED',
62+
% 'DETACHED THROWING',
63+
% ],
64+
% [
65+
% '@_alwaysEmitIntoClient',
66+
% '@available(SwiftStdlib 6.0, *)',
67+
% ],
68+
% [ # PARAMS
69+
% 'name: String?',
70+
% 'executorPreference taskExecutor: (any TaskExecutor)? = nil',
71+
% 'priority: TaskPriority? = nil',
72+
% 'operation: sending @escaping @isolated(any) () async throws -> Success',
73+
% ]),
4774
% ]:
4875
% for METHOD_VARIANT in METHOD_VARIANTS:
4976

5077
% IS_DETACHED = 'DETACHED' in METHOD_VARIANT
5178
% IS_THROWING = 'THROWING' in METHOD_VARIANT
79+
% HAS_TASK_PRIORITY = any('priority:' in param for param in PARAMS)
80+
% HAS_TASK_NAME = any('name:' in param for param in PARAMS)
81+
% HAS_TASK_EXECUTOR = any('taskExecutor:' in param for param in PARAMS)
82+
%
5283
% if IS_THROWING:
5384
% FAILURE_TYPE = 'Error'
5485
% else:
5586
% FAILURE_TYPE = 'Never'
5687
% end
5788

58-
%
59-
% def adjust_params_for_kind(params):
60-
% res = []
61-
% for p in params:
62-
% np = p
63-
% if not IS_THROWING:
64-
% np = np.replace("throws", "")
65-
% res.append(np)
66-
% return res
67-
%
68-
%
69-
% HAS_TASK_PRIORITY = any('priority:' in param for param in PARAMS)
70-
% HAS_TASK_NAME = any('name:' in param for param in PARAMS)
71-
% HAS_TASK_EXECUTOR = any('taskExecutor:' in param for param in PARAMS)
89+
%{
7290

73-
% if IS_DETACHED:
74-
% ARROW_RETURN_TYPE = f'-> Task<Success, {FAILURE_TYPE}>'
75-
% else:
76-
% ARROW_RETURN_TYPE = '' # init does not spell out return type
77-
% end
91+
def adjust_params_for_kind(params):
92+
res = []
93+
for p in params:
94+
np = p
95+
if not IS_THROWING:
96+
np = np.replace("throws", "")
97+
res.append(np)
98+
return res
7899

79-
% if IS_DETACHED:
80-
% THE_FUNC = 'public static func detached'
81-
% else:
82-
% THE_FUNC = 'public init'
83-
% end
100+
def adjust_availability(avails):
101+
res = []
102+
for av in avails:
103+
adjusted = av
104+
if HAS_TASK_EXECUTOR:
105+
adjusted = adjusted.replace("SwiftStdlib 5.1", "SwiftStdlib 6.0")
106+
res.append(adjusted)
107+
return res
108+
109+
if IS_DETACHED:
110+
ARROW_RETURN_TYPE = f'-> Task<Success, {FAILURE_TYPE}>'
111+
else:
112+
ARROW_RETURN_TYPE = '' # init does not spell out return type
113+
114+
if IS_DETACHED:
115+
THE_FUNC = 'public static func detached'
116+
else:
117+
THE_FUNC = 'public init'
118+
119+
}%
84120

85121
% # ====================================================================================================================
86-
@available(SwiftStdlib 5.1, *)
87122
extension Task where Failure == ${FAILURE_TYPE} {
88123

89124
% # --------------------------------------------------------------------------------------------------------------------
@@ -101,7 +136,7 @@ extension Task where Failure == ${FAILURE_TYPE} {
101136
#elseif $Embedded
102137
@discardableResult
103138
@_alwaysEmitIntoClient
104-
@available(SwiftStdlib 5.1, *)
139+
${" \n".join(adjust_availability(['@available(SwiftStdlib 5.1, *)']))}
105140
${THE_FUNC}(
106141
${",\n ".join(adjust_params_for_kind(PARAMS))}
107142
) ${ARROW_RETURN_TYPE}{
@@ -159,16 +194,18 @@ extension Task where Failure == ${FAILURE_TYPE} {
159194
% if HAS_TASK_NAME:
160195
/// - name: Human readable name of the task.
161196
% end
162-
% if HAS_TASK_NAME:
163-
/// - taskExecutor: the preferred task executor for this task,
164-
/// and any child tasks created by it. Explicitly passing `nil` is
165-
/// interpreted as "no preference".
197+
% if HAS_TASK_EXECUTOR:
198+
/// - taskExecutor:
199+
/// - taskExecutor: The task executor that the child task should be started on and keep using.
200+
/// Explicitly passing `nil` as the executor preference is equivalent to no preference,
201+
/// and effectively means to inherit the outer context's executor preference.
202+
/// You can also pass the ``globalConcurrentExecutor`` global executor explicitly.
166203
% end
167204
/// - priority: The priority of the task.
168205
/// - operation: The operation to perform.
169206
///
170207
/// - Returns: A reference to the task.
171-
${"\n ".join(ALL_AVAILABILITY)}
208+
${"\n ".join(adjust_availability(ALL_AVAILABILITY))}
172209
@discardableResult
173210
${THE_FUNC}(
174211
${",\n ".join(adjust_params_for_kind(PARAMS))}

stdlib/public/Concurrency/TaskGroup+addTask.swift.gyb

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ import Swift
3131
% 'ThrowingDiscardingTaskGroup'
3232
% ],
3333
% [
34-
% '@available(SwiftStdlib 6.2, *)',
34+
% '@available(SwiftStdlib 6.0, *)', # because task executor
3535
% '@_unavailableInEmbedded', # since TaskExecutor is not available on embedded
3636
% ],
3737
% ['addTask', 'addTaskUnlessCancelled'],
@@ -43,6 +43,42 @@ import Swift
4343
% 'operation: sending @escaping @isolated(any) () async throws -> ChildTaskResult'
4444
% ],
4545
% ),
46+
% (
47+
% '', # no #if condition
48+
% [
49+
% 'TaskGroup',
50+
% 'ThrowingTaskGroup',
51+
% ],
52+
% [
53+
% '@available(SwiftStdlib 5.1, *)',
54+
% ],
55+
% ['addTask', 'addTaskUnlessCancelled'],
56+
% [
57+
% 'name: String?',
58+
% # without task executor
59+
% 'priority: TaskPriority? = nil',
60+
% # throws and ChildTaskResult will be adjusted per task group type
61+
% 'operation: sending @escaping @isolated(any) () async throws -> ChildTaskResult'
62+
% ],
63+
% ),
64+
% (
65+
% '', # no #if condition
66+
% [
67+
% 'DiscardingTaskGroup',
68+
% 'ThrowingDiscardingTaskGroup'
69+
% ],
70+
% [
71+
% '@available(SwiftStdlib 5.9, *)', # because Discarding task groups
72+
% ],
73+
% ['addTask', 'addTaskUnlessCancelled'],
74+
% [
75+
% 'name: String?',
76+
% # without task executor
77+
% 'priority: TaskPriority? = nil',
78+
% # throws and ChildTaskResult will be adjusted per task group type
79+
% 'operation: sending @escaping @isolated(any) () async throws -> ChildTaskResult'
80+
% ],
81+
% ),
4682
% # -----------------------------------------------------------------------
4783
% # === Added TaskExecutor
4884
% (
@@ -170,7 +206,9 @@ import Swift
170206
#if ${IFDEF}
171207
% end
172208

173-
% if IS_DISCARDING:
209+
% if HAS_TASK_EXECUTOR:
210+
@available(SwiftStdlib 6.0, *)
211+
% elif IS_DISCARDING:
174212
@available(SwiftStdlib 5.9, *)
175213
% else:
176214
@available(SwiftStdlib 5.1, *)
@@ -267,7 +305,9 @@ extension ${TYPE} {
267305
flags: flags,
268306
initialSerialExecutor: builtinSerialExecutor,
269307
taskGroup: _group,
308+
% if HAS_TASK_EXECUTOR:
270309
initialTaskExecutorConsuming: taskExecutor,
310+
% end
271311
taskName: nameBytes.baseAddress!._rawValue,
272312
operation: operation).0
273313
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
// RUN: %target-swift-frontend -emit-sil -verify -o /dev/null -verify %s
2+
3+
struct Boom: Error {}
4+
5+
@available(SwiftStdlib 6.2, *)
6+
func testName() {
7+
_ = Task.name
8+
}
9+
10+
@available(SwiftStdlib 6.0, *)
11+
func taskExecutor() async {
12+
Task(name: "name", executorPreference: nil) { }
13+
Task(name: "name", executorPreference: nil) { throw Boom() }
14+
15+
Task.detached(name: "name", executorPreference: nil) { throw Boom() }
16+
17+
await withTaskGroup(of: Void.self) { group in
18+
group.addTask(name: "name", executorPreference: nil) {
19+
()
20+
}
21+
}
22+
await withThrowingTaskGroup(of: Void.self) { group in
23+
group.addTask(name: "name", executorPreference: nil) {
24+
()
25+
}
26+
}
27+
28+
await withDiscardingTaskGroup { group in
29+
group.addTask(name: "name", executorPreference: nil) {
30+
()
31+
}
32+
}
33+
try! await withThrowingDiscardingTaskGroup { group in
34+
group.addTask(name: "name", executorPreference: nil) {
35+
()
36+
}
37+
}
38+
}
39+
40+
@available(SwiftStdlib 5.1, *)
41+
func backDeployedNames() async {
42+
Task(name: "name") { }
43+
Task(name: "name") { throw Boom() }
44+
45+
Task.detached(name: "name") { }
46+
Task.detached(name: "name") { throw Boom() }
47+
48+
await withTaskGroup(of: Void.self) { group in
49+
group.addTask(name: "name") {
50+
()
51+
}
52+
}
53+
await withThrowingTaskGroup(of: Void.self) { group in
54+
group.addTask(name: "name") {
55+
()
56+
}
57+
}
58+
}
59+
60+
@available(SwiftStdlib 5.9, *)
61+
func backDeployedDiscarding() async {
62+
await withDiscardingTaskGroup { group in
63+
group.addTask(name: "name") {
64+
()
65+
}
66+
}
67+
try! await withThrowingDiscardingTaskGroup { group in
68+
group.addTask(name: "name") {
69+
()
70+
}
71+
}
72+
}
73+

test/diagnostics/pretty-printed-diagnostics.swift

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: not %target-swift-frontend -diagnostic-style=swift -typecheck %/s 2>&1 | %FileCheck %s --dump-input=always
1+
// RUN: not %target-swift-frontend -diagnostic-style=swift -typecheck %/s 2>&1 | %FileCheck %s
22

33
// REQUIRES: swift_swift_parser
44

@@ -70,11 +70,6 @@ foo(b:
7070
func test(a: Int) {}
7171
func test(a: Int) {}
7272

73-
struct DuplicateInits {
74-
init(a: Int) {}
75-
init(a: Int) {}
76-
}
77-
7873
// Test fallback for non-ASCII characters.
7974
// CHECK: SOURCE_DIR{{[/\]+}}test{{[/\]+}}diagnostics{{[/\]+}}pretty-printed-diagnostics.swift:[[#LINE:]]:11
8075
// CHECK: [[#LINE-2]] |
@@ -99,9 +94,3 @@ struct DuplicateInits {
9994
// CHECK: | `- note: 'test(a:)' previously declared here
10095
// CHECK: [[#LINE]] | func test(a: Int) {}
10196
// CHECL: [[#LINE+1]] | `- error: invalid redeclaration of 'test(a:)'
102-
103-
// CHECK: SOURCE_DIR{{[/\]+}}test{{[/\]+}}diagnostics{{[/\]+}}pretty-printed-diagnostics.swift:[[#LINE:]]:3
104-
// CHECK: [[#LINE-1]] | init(a: Int) {}
105-
// CHECK: | `- note: 'init(a:)' previously declared here
106-
// CHECK: [[#LINE]] | init(a: Int) {}
107-
// CHECL: [[#LINE+1]] | `- error: invalid redeclaration of 'init(a:)'

0 commit comments

Comments
 (0)