diff --git a/Package.swift b/Package.swift index 3cff98089..840a20d59 100644 --- a/Package.swift +++ b/Package.swift @@ -1,4 +1,4 @@ -// swift-tools-version:5.10 +// swift-tools-version:6.0 //===----------------------------------------------------------------------===// // // This source file is part of the AsyncHTTPClient open source project @@ -19,10 +19,6 @@ let strictConcurrencyDevelopment = false let strictConcurrencySettings: [SwiftSetting] = { var initialSettings: [SwiftSetting] = [] - initialSettings.append(contentsOf: [ - .enableUpcomingFeature("StrictConcurrency"), - .enableUpcomingFeature("InferSendableFromCaptures"), - ]) if strictConcurrencyDevelopment { // -warnings-as-errors here is a workaround so that IDE-based development can diff --git a/README.md b/README.md index a4f49c8c8..b557e58fa 100644 --- a/README.md +++ b/README.md @@ -306,7 +306,7 @@ Please have a look at [SECURITY.md](SECURITY.md) for AsyncHTTPClient's security ## Supported Versions -The most recent versions of AsyncHTTPClient support Swift 5.10 and newer. The minimum Swift version supported by AsyncHTTPClient releases are detailed below: +The most recent versions of AsyncHTTPClient support Swift 6.0 and newer. The minimum Swift version supported by AsyncHTTPClient releases are detailed below: AsyncHTTPClient | Minimum Swift Version --------------------|---------------------- @@ -318,4 +318,5 @@ AsyncHTTPClient | Minimum Swift Version `1.20.0 ..< 1.21.0` | 5.7 `1.21.0 ..< 1.26.0` | 5.8 `1.26.0 ..< 1.27.0` | 5.9 -`1.27.0 ...` | 5.10 +`1.27.0 ..< 1.30.0` | 5.10 +`1.30.0 ...` | 6.0 diff --git a/Sources/AsyncHTTPClient/DeconstructedURL.swift b/Sources/AsyncHTTPClient/DeconstructedURL.swift index 52042bce3..f7d0b1977 100644 --- a/Sources/AsyncHTTPClient/DeconstructedURL.swift +++ b/Sources/AsyncHTTPClient/DeconstructedURL.swift @@ -48,7 +48,7 @@ extension DeconstructedURL { switch scheme { case .http, .https: - #if !canImport(Darwin) && compiler(>=6.0) + #if !canImport(Darwin) guard let urlHost = url.host, !urlHost.isEmpty else { throw HTTPClientError.emptyHost } @@ -89,7 +89,7 @@ extension DeconstructedURL { } } -#if !canImport(Darwin) && compiler(>=6.0) +#if !canImport(Darwin) extension String { @inlinable internal func trimIPv6Brackets() -> String { var utf8View = self.utf8[...] diff --git a/Sources/AsyncHTTPClient/HTTPClient+StructuredConcurrency.swift b/Sources/AsyncHTTPClient/HTTPClient+StructuredConcurrency.swift index f7d471f10..98c6555da 100644 --- a/Sources/AsyncHTTPClient/HTTPClient+StructuredConcurrency.swift +++ b/Sources/AsyncHTTPClient/HTTPClient+StructuredConcurrency.swift @@ -17,7 +17,6 @@ import NIO @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) extension HTTPClient { - #if compiler(>=6.0) /// Start & automatically shut down a new ``HTTPClient``. /// /// This method allows to start & automatically dispose of a ``HTTPClient`` following the principle of Structured Concurrency. @@ -43,30 +42,4 @@ extension HTTPClient { try await httpClient.shutdown() } } - #else - /// Start & automatically shut down a new ``HTTPClient``. - /// - /// This method allows to start & automatically dispose of a ``HTTPClient`` following the principle of Structured Concurrency. - /// The ``HTTPClient`` is guaranteed to be shut down upon return, whether `body` throws or not. - /// - /// This may be particularly useful if you cannot use the shared singleton (``HTTPClient/shared``). - public static func withHTTPClient( - eventLoopGroup: any EventLoopGroup = HTTPClient.defaultEventLoopGroup, - configuration: Configuration = Configuration(), - backgroundActivityLogger: Logger? = nil, - _ body: (HTTPClient) async throws -> Return - ) async throws -> Return { - let logger = (backgroundActivityLogger ?? HTTPClient.loggingDisabled) - let httpClient = HTTPClient( - eventLoopGroup: eventLoopGroup, - configuration: configuration, - backgroundActivityLogger: logger - ) - return try await asyncDo { - try await body(httpClient) - } finally: { _ in - try await httpClient.shutdown() - } - } - #endif } diff --git a/Sources/AsyncHTTPClient/HTTPHandler.swift b/Sources/AsyncHTTPClient/HTTPHandler.swift index f9b337565..20df597ca 100644 --- a/Sources/AsyncHTTPClient/HTTPHandler.swift +++ b/Sources/AsyncHTTPClient/HTTPHandler.swift @@ -13,6 +13,7 @@ //===----------------------------------------------------------------------===// import Algorithms +import Foundation import Logging import NIOConcurrencyHelpers import NIOCore @@ -21,12 +22,6 @@ import NIOPosix import NIOSSL import Tracing -#if compiler(>=6.0) -import Foundation -#else -@preconcurrency import Foundation -#endif - extension HTTPClient { /// A request body. public struct Body: Sendable { diff --git a/Sources/AsyncHTTPClient/StructuredConcurrencyHelpers.swift b/Sources/AsyncHTTPClient/StructuredConcurrencyHelpers.swift index 25f1225e0..071e93d36 100644 --- a/Sources/AsyncHTTPClient/StructuredConcurrencyHelpers.swift +++ b/Sources/AsyncHTTPClient/StructuredConcurrencyHelpers.swift @@ -15,14 +15,13 @@ // 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( 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 { + _ 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() @@ -48,36 +47,3 @@ internal func asyncDo( }.value return result } -#else -@inlinable -@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) -internal func asyncDo( - _ 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 diff --git a/Tests/AsyncHTTPClientTests/HTTPClientTests.swift b/Tests/AsyncHTTPClientTests/HTTPClientTests.swift index 50c3ecb9d..bc8feb853 100644 --- a/Tests/AsyncHTTPClientTests/HTTPClientTests.swift +++ b/Tests/AsyncHTTPClientTests/HTTPClientTests.swift @@ -46,7 +46,7 @@ final class HTTPClientTests: XCTestCaseHTTPClientTestsBaseClass { let request3 = try Request(url: "unix:///tmp/file") XCTAssertEqual(request3.host, "") - #if os(Linux) && compiler(>=6.0) && compiler(<6.1) + #if os(Linux) && compiler(<6.1) XCTAssertEqual(request3.url.host, "") #else XCTAssertNil(request3.url.host) diff --git a/Tests/AsyncHTTPClientTests/TransactionTests.swift b/Tests/AsyncHTTPClientTests/TransactionTests.swift index 3316de370..8e6464a5b 100644 --- a/Tests/AsyncHTTPClientTests/TransactionTests.swift +++ b/Tests/AsyncHTTPClientTests/TransactionTests.swift @@ -657,7 +657,6 @@ private actor Promise { @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) extension Transaction { - #if compiler(>=6.0) fileprivate static func makeWithResultTask( request: sending PreparedRequest, requestOptions: RequestOptions = .forTests(), @@ -685,40 +684,4 @@ extension Transaction { return (await transactionPromise.value, task) } - #else - fileprivate static func makeWithResultTask( - request: PreparedRequest, - requestOptions: RequestOptions = .forTests(), - logger: Logger = Logger(label: "test"), - connectionDeadline: NIODeadline = .distantFuture, - preferredEventLoop: EventLoop - ) async -> (Transaction, _Concurrency.Task) { - // It isn't sendable ... but on 6.0 and later we use 'sending'. - struct UnsafePrepareRequest: @unchecked Sendable { - var value: PreparedRequest - } - - let transactionPromise = Promise() - let unsafe = UnsafePrepareRequest(value: request) - let task = Task { - try await withCheckedThrowingContinuation { - (continuation: CheckedContinuation) in - let request = unsafe.value - let transaction = Transaction( - request: request, - requestOptions: requestOptions, - logger: logger, - connectionDeadline: connectionDeadline, - preferredEventLoop: preferredEventLoop, - responseContinuation: continuation - ) - Task { - await transactionPromise.fulfil(transaction) - } - } - } - - return (await transactionPromise.value, task) - } - #endif }