Skip to content

Commit e2c9541

Browse files
rlziiiktoso
andauthored
Allow TaskGroup's ChildTaskResult Type To Be Inferred (swiftlang#74517)
Co-authored-by: Konrad `ktoso` Malawski <[email protected]>
1 parent dcee673 commit e2c9541

File tree

2 files changed

+141
-2
lines changed

2 files changed

+141
-2
lines changed

stdlib/public/Concurrency/TaskGroup.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ import Swift
6767
@backDeployed(before: SwiftStdlib 6.0)
6868
@inlinable
6969
public func withTaskGroup<ChildTaskResult, GroupResult>(
70-
of childTaskResultType: ChildTaskResult.Type,
70+
of childTaskResultType: ChildTaskResult.Type = ChildTaskResult.self,
7171
returning returnType: GroupResult.Type = GroupResult.self,
7272
isolation: isolated (any Actor)? = #isolation,
7373
body: (inout TaskGroup<ChildTaskResult>) async -> GroupResult
@@ -202,7 +202,7 @@ public func _unsafeInheritExecutor_withTaskGroup<ChildTaskResult, GroupResult>(
202202
@backDeployed(before: SwiftStdlib 6.0)
203203
@inlinable
204204
public func withThrowingTaskGroup<ChildTaskResult, GroupResult>(
205-
of childTaskResultType: ChildTaskResult.Type,
205+
of childTaskResultType: ChildTaskResult.Type = ChildTaskResult.self,
206206
returning returnType: GroupResult.Type = GroupResult.self,
207207
isolation: isolated (any Actor)? = #isolation,
208208
body: (inout ThrowingTaskGroup<ChildTaskResult, Error>) async throws -> GroupResult
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
// RUN: %target-swift-frontend -disable-availability-checking %s -emit-sil -o /dev/null -verify -strict-concurrency=complete
2+
3+
// REQUIRES: concurrency
4+
// REQUIRES: asserts
5+
6+
// === OK cases
7+
8+
let _ = await withTaskGroup { group in
9+
group.addTask { }
10+
group.addTask { }
11+
}
12+
let _ = await withThrowingTaskGroup { group in
13+
group.addTask { }
14+
group.addTask { }
15+
}
16+
17+
let _ = await withTaskGroup { group in
18+
group.addTask { 1 }
19+
group.addTask { 2 }
20+
return "result"
21+
}
22+
let _ = await withThrowingTaskGroup { group in
23+
group.addTask { 1 }
24+
group.addTask { 2 }
25+
return "result"
26+
}
27+
28+
let _ = await withTaskGroup { group in
29+
group.addTask {
30+
if Bool.random() {
31+
return 1
32+
} else {
33+
return 0
34+
}
35+
}
36+
group.addTask {
37+
if Bool.random() {
38+
return 1
39+
} else {
40+
return 0
41+
}
42+
}
43+
return "result"
44+
}
45+
let _ = await withThrowingTaskGroup { group in
46+
group.addTask {
47+
if Bool.random() {
48+
return 1
49+
} else {
50+
return 0
51+
}
52+
}
53+
group.addTask {
54+
if Bool.random() {
55+
return 1
56+
} else {
57+
return 0
58+
}
59+
}
60+
return "result"
61+
}
62+
63+
// === Cases where inference fails
64+
65+
let _: Int = await withTaskGroup { group in
66+
// expected-error@-1{{generic parameter 'ChildTaskResult' could not be inferred}}
67+
return 1
68+
}
69+
let _: Int = await withThrowingTaskGroup { group in
70+
// expected-error@-1{{generic parameter 'ChildTaskResult' could not be inferred}}
71+
return 1
72+
}
73+
74+
// we infer the ChildTaskResult from a addTask, so if some other method
75+
// precedes it, inference will fail.
76+
77+
let _: Int = await withTaskGroup { group in
78+
// expected-error@-1{{generic parameter 'ChildTaskResult' could not be inferred}}
79+
await group.next()
80+
return 1
81+
}
82+
let _: Int = await withThrowingTaskGroup { group in
83+
// expected-error@-1{{generic parameter 'ChildTaskResult' could not be inferred}}
84+
try await group.next()
85+
return 1
86+
}
87+
88+
let _: Int = await withTaskGroup { group in
89+
// expected-error@-1{{generic parameter 'ChildTaskResult' could not be inferred}}
90+
await group.next()
91+
group.addTask { 1 }
92+
93+
return 1
94+
}
95+
let _: Int = await withThrowingTaskGroup { group in
96+
// expected-error@-1{{generic parameter 'ChildTaskResult' could not be inferred}}
97+
try await group.next()
98+
group.addTask { 1 }
99+
100+
return 1
101+
}
102+
103+
let _ = await withTaskGroup { group in
104+
// expected-error@-1{{generic parameter 'ChildTaskResult' could not be inferred}}
105+
}
106+
let _ = await withThrowingTaskGroup { group in
107+
// expected-error@-1{{generic parameter 'ChildTaskResult' could not be inferred}}
108+
}
109+
110+
// Notable exception, defer does not cause inference to break:
111+
112+
let _: Int = await withTaskGroup { group in
113+
defer { group.cancelAll() }
114+
group.addTask { 1 }
115+
116+
return 1
117+
}
118+
let _: Int = await withThrowingTaskGroup { group in
119+
defer { group.cancelAll() }
120+
group.addTask { 1 }
121+
122+
return 1
123+
}
124+
125+
// Check conflicting types inside addTask {}
126+
127+
let _ = await withTaskGroup { group in
128+
group.addTask { 1 }
129+
group.addTask { "x" } // expected-error{{cannot convert value of type 'String' to closure result type 'Int'}}
130+
131+
return 1
132+
}
133+
let _ = await withThrowingTaskGroup { group in
134+
group.addTask { 1 }
135+
group.addTask { "x" } // expected-error{{cannot convert value of type 'String' to closure result type 'Int'}}
136+
137+
return 1
138+
}
139+

0 commit comments

Comments
 (0)