Skip to content

Commit e44a4f1

Browse files
authored
Merge pull request #38772 from DougGregor/task-group-non-throwing-next-result-5.5
Make `ThrowingTaskGroup.nextResult()` non-throwing.
2 parents 97176fc + 5bf9d9e commit e44a4f1

File tree

2 files changed

+28
-16
lines changed

2 files changed

+28
-16
lines changed

stdlib/public/Concurrency/TaskGroup.swift

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -599,6 +599,20 @@ public struct ThrowingTaskGroup<ChildTaskResult, Failure: Error> {
599599
return try await _taskGroupWaitNext(group: _group)
600600
}
601601

602+
@_silgen_name("$sScg10nextResults0B0Oyxq_GSgyYaKF")
603+
@usableFromInline
604+
mutating func nextResultForABI() async throws -> Result<ChildTaskResult, Failure>? {
605+
do {
606+
guard let success: ChildTaskResult = try await _taskGroupWaitNext(group: _group) else {
607+
return nil
608+
}
609+
610+
return .success(success)
611+
} catch {
612+
return .failure(error as! Failure) // as!-safe, because we are only allowed to throw Failure (Error)
613+
}
614+
}
615+
602616
/// Wait for the next child task to complete,
603617
/// and return a result containing either
604618
/// the value that the child task returned or the error that it threw.
@@ -632,16 +646,9 @@ public struct ThrowingTaskGroup<ChildTaskResult, Failure: Error> {
632646
/// containing the error that the child task threw.
633647
///
634648
/// - SeeAlso: `next()`
635-
public mutating func nextResult() async throws -> Result<ChildTaskResult, Failure>? {
636-
do {
637-
guard let success: ChildTaskResult = try await _taskGroupWaitNext(group: _group) else {
638-
return nil
639-
}
640-
641-
return .success(success)
642-
} catch {
643-
return .failure(error as! Failure) // as!-safe, because we are only allowed to throw Failure (Error)
644-
}
649+
@_alwaysEmitIntoClient
650+
public mutating func nextResult() async -> Result<ChildTaskResult, Failure>? {
651+
return try! await nextResultForABI()
645652
}
646653

647654
/// A Boolean value that indicates whether the group has any remaining tasks.

test/Concurrency/Runtime/async_taskgroup_throw_recover.swift

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ func boom() async throws -> Int {
2323
@available(SwiftStdlib 5.5, *)
2424
func test_taskGroup_throws() async {
2525
let got: Int = try await withThrowingTaskGroup(of: Int.self) { group in
26-
group.spawn { try await boom() }
26+
group.addTask { try await boom() }
2727

2828
do {
2929
while let r = try await group.next() {
@@ -35,19 +35,24 @@ func test_taskGroup_throws() async {
3535
let gc = group.isCancelled
3636
print("group cancelled: \(gc)")
3737

38-
group.spawn { () async -> Int in
38+
group.addTask { () async -> Int in
3939
let c = Task.isCancelled
4040
print("task 3 (cancelled: \(c))")
4141
return 3
4242
}
4343

44-
guard let third = try! await group.next() else {
44+
switch await group.nextResult() {
45+
case .success(let third):
46+
print("task group returning normally: \(third)")
47+
return third
48+
49+
case .failure(let error):
50+
fatalError("got an erroneous third result")
51+
52+
case .none:
4553
print("task group failed to get 3")
4654
return 0
4755
}
48-
49-
print("task group returning normally: \(third)")
50-
return third
5156
}
5257

5358
fatalError("Should have thrown and handled inside the catch block")

0 commit comments

Comments
 (0)