Skip to content

Commit 2080076

Browse files
authored
Adopt explicit existential any (#26)
Adopt explicit existential any ### Motivation As a follow-on to apple/swift-openapi-generator#99, let's also enable explicit existential any in the runtime library. ### Modifications Enabled the flag in Package.swift (for Swift 5.9 and newer) and updated all the usage sites. ### Result The codebase is closer to being ready for Swift 6. ### Test Plan Updated unit tests as well, all is passing locally. Reviewed by: simonjbeaumont Builds: ✔︎ pull request validation (5.8) - Build finished. ✔︎ pull request validation (5.9) - Build finished. ✔︎ pull request validation (docc test) - Build finished. ✔︎ pull request validation (integration test) - Build finished. ✔︎ pull request validation (nightly) - Build finished. ✔︎ pull request validation (soundness) - Build finished. ✖︎ pull request validation (api breakage) - Build finished. #26
1 parent 45b2420 commit 2080076

File tree

11 files changed

+69
-56
lines changed

11 files changed

+69
-56
lines changed

Package.swift

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,17 @@
1414
//===----------------------------------------------------------------------===//
1515
import PackageDescription
1616

17+
// General Swift-settings for all targets.
18+
var swiftSettings: [SwiftSetting] = []
19+
20+
#if swift(>=5.9)
21+
swiftSettings.append(
22+
// https://github.com/apple/swift-evolution/blob/main/proposals/0335-existential-any.md
23+
// Require `any` for existential types.
24+
.enableUpcomingFeature("ExistentialAny")
25+
)
26+
#endif
27+
1728
let package = Package(
1829
name: "swift-openapi-runtime",
1930
platforms: [
@@ -31,11 +42,13 @@ let package = Package(
3142
targets: [
3243
.target(
3344
name: "OpenAPIRuntime",
34-
dependencies: []
45+
dependencies: [],
46+
swiftSettings: swiftSettings
3547
),
3648
.testTarget(
3749
name: "OpenAPIRuntimeTests",
38-
dependencies: ["OpenAPIRuntime"]
50+
dependencies: ["OpenAPIRuntime"],
51+
swiftSettings: swiftSettings
3952
),
4053
]
4154
)

Sources/OpenAPIRuntime/Base/OpenAPIValue.swift

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,12 @@
3636
public struct OpenAPIValueContainer: Codable, Equatable, Hashable, Sendable {
3737

3838
/// The underlying dynamic value.
39-
public var value: Sendable?
39+
public var value: (any Sendable)?
4040

4141
/// Creates a new container with the given validated value.
4242
/// - Parameter value: A value of a JSON-compatible type, such as `String`,
4343
/// `[Any]`, and `[String: Any]`.
44-
init(validatedValue value: Sendable?) {
44+
init(validatedValue value: (any Sendable)?) {
4545
self.value = value
4646
}
4747

@@ -62,7 +62,7 @@ public struct OpenAPIValueContainer: Codable, Equatable, Hashable, Sendable {
6262
/// - Parameter value: An untyped value.
6363
/// - Returns: A cast value if supported.
6464
/// - Throws: When the value is not supported.
65-
static func tryCast(_ value: (any Sendable)?) throws -> Sendable? {
65+
static func tryCast(_ value: (any Sendable)?) throws -> (any Sendable)? {
6666
guard let value = value else {
6767
return nil
6868
}
@@ -98,7 +98,7 @@ public struct OpenAPIValueContainer: Codable, Equatable, Hashable, Sendable {
9898

9999
// MARK: Decodable
100100

101-
public init(from decoder: Decoder) throws {
101+
public init(from decoder: any Decoder) throws {
102102
let container = try decoder.singleValueContainer()
103103
if container.decodeNil() {
104104
self.init(validatedValue: nil)
@@ -124,7 +124,7 @@ public struct OpenAPIValueContainer: Codable, Equatable, Hashable, Sendable {
124124

125125
// MARK: Encodable
126126

127-
public func encode(to encoder: Encoder) throws {
127+
public func encode(to encoder: any Encoder) throws {
128128
var container = encoder.singleValueContainer()
129129
guard let value = value else {
130130
try container.encodeNil()
@@ -171,15 +171,15 @@ public struct OpenAPIValueContainer: Codable, Equatable, Hashable, Sendable {
171171
return lhs == rhs
172172
case let (lhs as String, rhs as String):
173173
return lhs == rhs
174-
case let (lhs as [Sendable?], rhs as [Sendable?]):
174+
case let (lhs as [(any Sendable)?], rhs as [(any Sendable)?]):
175175
guard lhs.count == rhs.count else {
176176
return false
177177
}
178178
return zip(lhs, rhs)
179179
.allSatisfy { lhs, rhs in
180180
OpenAPIValueContainer(validatedValue: lhs) == OpenAPIValueContainer(validatedValue: rhs)
181181
}
182-
case let (lhs as [String: Sendable?], rhs as [String: Sendable?]):
182+
case let (lhs as [String: (any Sendable)?], rhs as [String: (any Sendable)?]):
183183
guard lhs.count == rhs.count else {
184184
return false
185185
}
@@ -211,11 +211,11 @@ public struct OpenAPIValueContainer: Codable, Equatable, Hashable, Sendable {
211211
hasher.combine(value)
212212
case let value as String:
213213
hasher.combine(value)
214-
case let value as [Sendable]:
214+
case let value as [any Sendable]:
215215
for item in value {
216216
hasher.combine(OpenAPIValueContainer(validatedValue: item))
217217
}
218-
case let value as [String: Sendable]:
218+
case let value as [String: any Sendable]:
219219
for (key, itemValue) in value {
220220
hasher.combine(key)
221221
hasher.combine(OpenAPIValueContainer(validatedValue: itemValue))
@@ -281,11 +281,11 @@ extension OpenAPIValueContainer: ExpressibleByFloatLiteral {
281281
public struct OpenAPIObjectContainer: Codable, Equatable, Hashable, Sendable {
282282

283283
/// The underlying dynamic dictionary value.
284-
public var value: [String: Sendable?]
284+
public var value: [String: (any Sendable)?]
285285

286286
/// Creates a new container with the given validated dictionary.
287287
/// - Parameter value: A dictionary value.
288-
init(validatedValue value: [String: Sendable?]) {
288+
init(validatedValue value: [String: (any Sendable)?]) {
289289
self.value = value
290290
}
291291

@@ -311,21 +311,21 @@ public struct OpenAPIObjectContainer: Codable, Equatable, Hashable, Sendable {
311311
/// - Parameter value: A dictionary with untyped values.
312312
/// - Returns: A cast dictionary if values are supported.
313313
/// - Throws: If an unsupported value is found.
314-
static func tryCast(_ value: [String: Any?]) throws -> [String: Sendable?] {
314+
static func tryCast(_ value: [String: Any?]) throws -> [String: (any Sendable)?] {
315315
return try value.mapValues(OpenAPIValueContainer.tryCast(_:))
316316
}
317317

318318
// MARK: Decodable
319319

320-
public init(from decoder: Decoder) throws {
320+
public init(from decoder: any Decoder) throws {
321321
let container = try decoder.singleValueContainer()
322322
let item = try container.decode([String: OpenAPIValueContainer].self)
323323
self.init(validatedValue: item.mapValues(\.value))
324324
}
325325

326326
// MARK: Encodable
327327

328-
public func encode(to encoder: Encoder) throws {
328+
public func encode(to encoder: any Encoder) throws {
329329
var container = encoder.singleValueContainer()
330330
try container.encode(value.mapValues(OpenAPIValueContainer.init(validatedValue:)))
331331
}
@@ -385,11 +385,11 @@ public struct OpenAPIObjectContainer: Codable, Equatable, Hashable, Sendable {
385385
public struct OpenAPIArrayContainer: Codable, Equatable, Hashable, Sendable {
386386

387387
/// The underlying dynamic array value.
388-
public var value: [Sendable?]
388+
public var value: [(any Sendable)?]
389389

390390
/// Creates a new container with the given validated array.
391391
/// - Parameter value: An array value.
392-
init(validatedValue value: [Sendable?]) {
392+
init(validatedValue value: [(any Sendable)?]) {
393393
self.value = value
394394
}
395395

@@ -414,21 +414,21 @@ public struct OpenAPIArrayContainer: Codable, Equatable, Hashable, Sendable {
414414
/// Returns the specified value cast to an array of supported values.
415415
/// - Parameter value: An array with untyped values.
416416
/// - Returns: A cast value if values are supported, nil otherwise.
417-
static func tryCast(_ value: [Any?]) throws -> [Sendable?] {
417+
static func tryCast(_ value: [Any?]) throws -> [(any Sendable)?] {
418418
return try value.map(OpenAPIValueContainer.tryCast(_:))
419419
}
420420

421421
// MARK: Decodable
422422

423-
public init(from decoder: Decoder) throws {
423+
public init(from decoder: any Decoder) throws {
424424
let container = try decoder.singleValueContainer()
425425
let item = try container.decode([OpenAPIValueContainer].self)
426426
self.init(validatedValue: item.map(\.value))
427427
}
428428

429429
// MARK: Encodable
430430

431-
public func encode(to encoder: Encoder) throws {
431+
public func encode(to encoder: any Encoder) throws {
432432
var container = encoder.singleValueContainer()
433433
try container.encode(value.map(OpenAPIValueContainer.init(validatedValue:)))
434434
}

Sources/OpenAPIRuntime/Conversion/CodableExtensions.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ extension Decoder {
5353
guard !unknownKeys.isEmpty else {
5454
return .init()
5555
}
56-
let keyValuePairs: [(String, Sendable?)] = try unknownKeys.map { key in
56+
let keyValuePairs: [(String, (any Sendable)?)] = try unknownKeys.map { key in
5757
(
5858
key.stringValue,
5959
try container.decode(

Sources/OpenAPIRuntime/Conversion/Configuration.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ extension DateTranscoder where Self == ISO8601DateTranscoder {
5555

5656
extension JSONEncoder.DateEncodingStrategy {
5757
/// Encode the `Date` as a custom value encoded using the given ``DateTranscoder``.
58-
static func from(dateTranscoder: DateTranscoder) -> Self {
58+
static func from(dateTranscoder: any DateTranscoder) -> Self {
5959
return .custom { date, encoder in
6060
let dateAsString = try dateTranscoder.encode(date)
6161
var container = encoder.singleValueContainer()
@@ -66,7 +66,7 @@ extension JSONEncoder.DateEncodingStrategy {
6666

6767
extension JSONDecoder.DateDecodingStrategy {
6868
/// Decode the `Date` as a custom value decoded by the given ``DateTranscoder``.
69-
static func from(dateTranscoder: DateTranscoder) -> Self {
69+
static func from(dateTranscoder: any DateTranscoder) -> Self {
7070
return .custom { decoder in
7171
let container = try decoder.singleValueContainer()
7272
let dateString = try container.decode(String.self)
@@ -79,15 +79,15 @@ extension JSONDecoder.DateDecodingStrategy {
7979
public struct Configuration: Sendable {
8080

8181
/// The transcoder used when converting between date and string values.
82-
public var dateTranscoder: DateTranscoder
82+
public var dateTranscoder: any DateTranscoder
8383

8484
/// Creates a new configuration with the specified values.
8585
///
8686
/// - Parameters:
8787
/// - dateTranscoder: The transcoder to use when converting between date
8888
/// and string values.
8989
public init(
90-
dateTranscoder: DateTranscoder = .iso8601
90+
dateTranscoder: any DateTranscoder = .iso8601
9191
) {
9292
self.dateTranscoder = dateTranscoder
9393
}

Sources/OpenAPIRuntime/Deprecated/Deprecated.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ extension Converter {
197197
guard let value else {
198198
return
199199
}
200-
if let value = value as? _StringConvertible {
200+
if let value = value as? (any _StringConvertible) {
201201
headerFields.add(name: name, value: value.description)
202202
return
203203
}
@@ -223,7 +223,7 @@ extension Converter {
223223
guard let stringValue = headerFields.firstValue(name: name) else {
224224
return nil
225225
}
226-
if let myType = T.self as? _StringConvertible.Type {
226+
if let myType = T.self as? any _StringConvertible.Type {
227227
return myType.init(stringValue).map { $0 as! T }
228228
}
229229
let data = Data(stringValue.utf8)

Sources/OpenAPIRuntime/Errors/ClientError.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ public struct ClientError: Error {
4949
public var response: Response?
5050

5151
/// The underlying error that caused the operation to fail.
52-
public var underlyingError: Error
52+
public var underlyingError: any Error
5353

5454
/// Creates a new error.
5555
/// - Parameters:
@@ -65,7 +65,7 @@ public struct ClientError: Error {
6565
request: Request? = nil,
6666
baseURL: URL? = nil,
6767
response: Response? = nil,
68-
underlyingError: Error
68+
underlyingError: any Error
6969
) {
7070
self.operationID = operationID
7171
self.operationInput = operationInput
@@ -78,7 +78,7 @@ public struct ClientError: Error {
7878
// MARK: Private
7979

8080
fileprivate var underlyingErrorDescription: String {
81-
guard let prettyError = underlyingError as? PrettyStringConvertible else {
81+
guard let prettyError = underlyingError as? (any PrettyStringConvertible) else {
8282
return underlyingError.localizedDescription
8383
}
8484
return prettyError.prettyDescription

Sources/OpenAPIRuntime/Errors/RuntimeError.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@ internal enum RuntimeError: Error, CustomStringConvertible, LocalizedError, Pret
3838
case missingRequiredRequestBody
3939

4040
// Transport/Handler
41-
case transportFailed(Error)
42-
case handlerFailed(Error)
41+
case transportFailed(any Error)
42+
case handlerFailed(any Error)
4343

4444
// MARK: CustomStringConvertible
4545

Sources/OpenAPIRuntime/Errors/ServerError.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ public struct ServerError: Error {
3535
public var operationOutput: (any Sendable)?
3636

3737
/// The underlying error that caused the operation to fail.
38-
public var underlyingError: Error
38+
public var underlyingError: any Error
3939

4040
/// Creates a new error.
4141
/// - Parameters:
@@ -52,7 +52,7 @@ public struct ServerError: Error {
5252
requestMetadata: ServerRequestMetadata,
5353
operationInput: (any Sendable)? = nil,
5454
operationOutput: (any Sendable)? = nil,
55-
underlyingError: Error
55+
underlyingError: (any Error)
5656
) {
5757
self.operationID = operationID
5858
self.request = request
@@ -65,7 +65,7 @@ public struct ServerError: Error {
6565
// MARK: Private
6666

6767
fileprivate var underlyingErrorDescription: String {
68-
guard let prettyError = underlyingError as? PrettyStringConvertible else {
68+
guard let prettyError = underlyingError as? (any PrettyStringConvertible) else {
6969
return underlyingError.localizedDescription
7070
}
7171
return prettyError.prettyDescription

Sources/OpenAPIRuntime/Interface/UniversalClient.swift

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -34,17 +34,17 @@ public struct UniversalClient: Sendable {
3434
public let converter: Converter
3535

3636
/// Type capable of sending HTTP requests and receiving HTTP responses.
37-
public var transport: ClientTransport
37+
public var transport: any ClientTransport
3838

3939
/// Middlewares to be invoked before `transport`.
40-
public var middlewares: [ClientMiddleware]
40+
public var middlewares: [any ClientMiddleware]
4141

4242
/// Internal initializer that takes an initialized `Converter`.
4343
internal init(
4444
serverURL: URL,
4545
converter: Converter,
46-
transport: ClientTransport,
47-
middlewares: [ClientMiddleware]
46+
transport: any ClientTransport,
47+
middlewares: [any ClientMiddleware]
4848
) {
4949
self.serverURL = serverURL
5050
self.converter = converter
@@ -56,8 +56,8 @@ public struct UniversalClient: Sendable {
5656
public init(
5757
serverURL: URL = .defaultOpenAPIServerURL,
5858
configuration: Configuration = .init(),
59-
transport: ClientTransport,
60-
middlewares: [ClientMiddleware] = []
59+
transport: any ClientTransport,
60+
middlewares: [any ClientMiddleware] = []
6161
) {
6262
self.init(
6363
serverURL: serverURL,
@@ -93,7 +93,7 @@ public struct UniversalClient: Sendable {
9393
@Sendable
9494
func wrappingErrors<R>(
9595
work: () async throws -> R,
96-
mapError: (Error) -> Error
96+
mapError: (any Error) -> any Error
9797
) async throws -> R {
9898
do {
9999
return try await work()
@@ -106,8 +106,8 @@ public struct UniversalClient: Sendable {
106106
request: Request? = nil,
107107
baseURL: URL? = nil,
108108
response: Response? = nil,
109-
error: Error
110-
) -> Error {
109+
error: any Error
110+
) -> any Error {
111111
ClientError(
112112
operationID: operationID,
113113
operationInput: input,

0 commit comments

Comments
 (0)