Files
async-http-client/Sources/AsyncHTTPClient/StructuredConcurrencyHelpers.swift
T
Johannes Weiss b645ad4082 fix 5.10 compile on Ubuntu 24.04 (Noble) for Intel (x86_64) (#810)
Specifically Swift 5.10 _on Intel on Ubuntu Noble (24.04)_ has a crazy
bug which leads to compilation failures in a `#if compiler(>=6.0)`
block: https://github.com/swiftlang/swift/issues/79285 .

This workaround fixes the compilation by _changing the whitespace_.

Thanks @gwynne for finding this workaround!

---------

Co-authored-by: Johannes Weiss <johannes@jweiss.io>
2025-02-11 12:25:31 +00:00

84 lines
3.0 KiB
Swift

//===----------------------------------------------------------------------===//
//
// This source file is part of the AsyncHTTPClient open source project
//
// Copyright (c) 2025 Apple Inc. and the AsyncHTTPClient project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
// See CONTRIBUTORS.txt for the list of AsyncHTTPClient project authors
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//
// swift-format-ignore
// Note: Whitespace changes are used to workaround compiler bug
// https://github.com/swiftlang/swift/issues/79285
#if compiler(>=6.0)
@inlinable
@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
internal func asyncDo<R>(
isolation: isolated (any Actor)? = #isolation,
// DO NOT FIX THE WHITESPACE IN THE NEXT LINE UNTIL 5.10 IS UNSUPPORTED
// https://github.com/swiftlang/swift/issues/79285
_ body: () async throws -> sending R, finally: sending @escaping ((any Error)?) async throws -> Void) async throws -> sending R {
let result: R
do {
result = try await body()
} catch {
// `body` failed, we need to invoke `finally` with the `error`.
// This _looks_ unstructured but isn't really because we unconditionally always await the return.
// We need to have an uncancelled task here to assure this is actually running in case we hit a
// cancellation error.
try await Task {
try await finally(error)
}.value
throw error
}
// `body` succeeded, we need to invoke `finally` with `nil` (no error).
// This _looks_ unstructured but isn't really because we unconditionally always await the return.
// We need to have an uncancelled task here to assure this is actually running in case we hit a
// cancellation error.
try await Task {
try await finally(nil)
}.value
return result
}
#else
@inlinable
@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
internal func asyncDo<R: Sendable>(
_ body: () async throws -> R,
finally: @escaping @Sendable ((any Error)?) async throws -> Void
) async throws -> R {
let result: R
do {
result = try await body()
} catch {
// `body` failed, we need to invoke `finally` with the `error`.
// This _looks_ unstructured but isn't really because we unconditionally always await the return.
// We need to have an uncancelled task here to assure this is actually running in case we hit a
// cancellation error.
try await Task {
try await finally(error)
}.value
throw error
}
// `body` succeeded, we need to invoke `finally` with `nil` (no error).
// This _looks_ unstructured but isn't really because we unconditionally always await the return.
// We need to have an uncancelled task here to assure this is actually running in case we hit a
// cancellation error.
try await Task {
try await finally(nil)
}.value
return result
}
#endif