I am very, very supportive of the goals of this pitch. Any attempt to mitigate the effects of SE-0335 as passed is welcome in my book.
Iāve edited the project manually as if these rules were applied and it builds until there is a crash later in code generation which may or may not be relevant.
Suggested tempering of elision to `some`
diff --git a/Source/AFError.swift b/Source/AFError.swift
index 8cd60c7..37c568c 100644
--- a/Source/AFError.swift
+++ b/Source/AFError.swift
@@ -363,7 +363,7 @@ extension AFError {
extension AFError {
/// The `URLConvertible` associated with the error.
- public var urlConvertible: URLConvertible? {
+ public var urlConvertible: (any URLConvertible)? {
guard case let .invalidURL(url) = self else { return nil }
return url
}
@@ -377,7 +377,7 @@ extension AFError {
/// The underlying `Error` responsible for generating the failure associated with `.sessionInvalidated`,
/// `.parameterEncodingFailed`, `.parameterEncoderFailed`, `.multipartEncodingFailed`, `.requestAdaptationFailed`,
/// `.responseSerializationFailed`, `.requestRetryFailed` errors.
- public var underlyingError: Error? {
+ public var underlyingError: (any Error)? {
switch self {
case let .multipartEncodingFailed(reason):
return reason.underlyingError
@@ -460,7 +460,7 @@ extension AFError {
}
extension AFError.ParameterEncodingFailureReason {
- var underlyingError: Error? {
+ var underlyingError: (any Error)? {
switch self {
case let .jsonEncodingFailed(error),
let .customEncodingFailed(error):
@@ -472,7 +472,7 @@ extension AFError.ParameterEncodingFailureReason {
}
extension AFError.ParameterEncoderFailureReason {
- var underlyingError: Error? {
+ var underlyingError: (any Error)? {
switch self {
case let .encoderFailed(error):
return error
@@ -503,7 +503,7 @@ extension AFError.MultipartEncodingFailureReason {
}
}
- var underlyingError: Error? {
+ var underlyingError: (any Error)? {
switch self {
case let .bodyPartFileNotReachableWithError(_, error),
let .bodyPartFileSizeQueryFailedWithError(_, error),
@@ -564,7 +564,7 @@ extension AFError.ResponseValidationFailureReason {
}
}
- var underlyingError: Error? {
+ var underlyingError: (any Error)? {
switch self {
case let .customValidationFailed(error):
return error
@@ -594,7 +594,7 @@ extension AFError.ResponseSerializationFailureReason {
}
}
- var underlyingError: Error? {
+ var underlyingError: (any Error)? {
switch self {
case let .jsonSerializationFailed(error),
let .decodingFailed(error),
@@ -632,7 +632,7 @@ extension AFError.ServerTrustFailureReason {
}
}
- var underlyingError: Error? {
+ var underlyingError: (any Error)? {
switch self {
case let .customEvaluationFailed(error):
return error
diff --git a/Source/AuthenticationInterceptor.swift b/Source/AuthenticationInterceptor.swift
index c3a3f31..625cec1 100644
--- a/Source/AuthenticationInterceptor.swift
+++ b/Source/AuthenticationInterceptor.swift
@@ -81,7 +81,7 @@ public protocol Authenticator: AnyObject {
/// - credential: The `Credential` to refresh.
/// - session: The `Session` requiring the refresh.
/// - completion: The closure to be executed once the refresh is complete.
- func refresh(_ credential: Credential, for session: Session, completion: @escaping (Result<Credential, Error>) -> Void)
+ func refresh(_ credential: Credential, for session: Session, completion: @escaping (Result<Credential, any Error>) -> Void)
/// Determines whether the `URLRequest` failed due to an authentication error based on the `HTTPURLResponse`.
///
@@ -193,7 +193,7 @@ public class AuthenticationInterceptor<AuthenticatorType>: RequestInterceptor wh
private struct AdaptOperation {
let urlRequest: URLRequest
let session: Session
- let completion: (Result<URLRequest, Error>) -> Void
+ let completion: (Result<URLRequest, any Error>) -> Void
}
private enum AdaptResult {
@@ -247,7 +247,7 @@ public class AuthenticationInterceptor<AuthenticatorType>: RequestInterceptor wh
// MARK: Adapt
- public func adapt(_ urlRequest: URLRequest, for session: Session, completion: @escaping (Result<URLRequest, Error>) -> Void) {
+ public func adapt(_ urlRequest: URLRequest, for session: Session, completion: @escaping (Result<URLRequest, any Error>) -> Void) {
let adaptResult: AdaptResult = $mutableState.write { mutableState in
// Queue the adapt operation if a refresh is already in place.
guard !mutableState.isRefreshing else {
diff --git a/Source/EventMonitor.swift b/Source/EventMonitor.swift
index 3b09671..4333f0c 100644
--- a/Source/EventMonitor.swift
+++ b/Source/EventMonitor.swift
@@ -312,13 +312,13 @@ extension EventMonitor {
public final class CompositeEventMonitor: EventMonitor {
public let queue = DispatchQueue(label: "org.alamofire.compositeEventMonitor", qos: .utility)
- let monitors: [EventMonitor]
+ let monitors: [any EventMonitor]
- init(monitors: [EventMonitor]) {
+ init(monitors: [any EventMonitor]) {
self.monitors = monitors
}
- func performEvent(_ event: @escaping (EventMonitor) -> Void) {
+ func performEvent(_ event: @escaping (any EventMonitor) -> Void) {
queue.async {
for monitor in self.monitors {
monitor.queue.async { event(monitor) }
@@ -571,7 +571,7 @@ public final class CompositeEventMonitor: EventMonitor {
/// `EventMonitor` that allows optional closures to be set to receive events.
open class ClosureEventMonitor: EventMonitor {
/// Closure called on the `urlSession(_:didBecomeInvalidWithError:)` event.
- open var sessionDidBecomeInvalidWithError: ((URLSession, Error?) -> Void)?
+ open var sessionDidBecomeInvalidWithError: ((URLSession, (any Error)?) -> Void)?
/// Closure called on the `urlSession(_:task:didReceive:completionHandler:)`.
open var taskDidReceiveChallenge: ((URLSession, URLSessionTask, URLAuthenticationChallenge) -> Void)?
@@ -589,7 +589,7 @@ open class ClosureEventMonitor: EventMonitor {
open var taskDidFinishCollectingMetrics: ((URLSession, URLSessionTask, URLSessionTaskMetrics) -> Void)?
/// Closure called on the `urlSession(_:task:didCompleteWithError:)` event.
- open var taskDidComplete: ((URLSession, URLSessionTask, Error?) -> Void)?
+ open var taskDidComplete: ((URLSession, URLSessionTask, (any Error)?) -> Void)?
/// Closure called on the `urlSession(_:taskIsWaitingForConnectivity:)` event.
open var taskIsWaitingForConnectivity: ((URLSession, URLSessionTask) -> Void)?
diff --git a/Source/MultipartUpload.swift b/Source/MultipartUpload.swift
index ceda21f..04df61a 100644
--- a/Source/MultipartUpload.swift
+++ b/Source/MultipartUpload.swift
@@ -31,7 +31,7 @@ final class MultipartUpload {
@Protected
private(set) var multipartFormData: MultipartFormData
let encodingMemoryThreshold: UInt64
- let request: URLRequestConvertible
+ let request: any URLRequestConvertible
let fileManager: FileManager
init(encodingMemoryThreshold: UInt64,
diff --git a/Source/Request.swift b/Source/Request.swift
index 3d64743..148e98b 100644
--- a/Source/Request.swift
+++ b/Source/Request.swift
@@ -72,11 +72,11 @@ public class Request {
/// The queue used for all serialization actions. By default it's a serial queue that targets `underlyingQueue`.
public let serializationQueue: DispatchQueue
/// `EventMonitor` used for event callbacks.
- public let eventMonitor: EventMonitor?
+ public let eventMonitor: (any EventMonitor)?
/// The `Request`'s interceptor.
- public let interceptor: RequestInterceptor?
+ public let interceptor: (any RequestInterceptor)?
/// The `Request`'s delegate.
- public private(set) weak var delegate: RequestDelegate?
+ public private(set) weak var delegate: (any RequestDelegate)?
// MARK: - Mutable State
@@ -89,9 +89,9 @@ public class Request {
/// `ProgressHandler` and `DispatchQueue` provided for download progress callbacks.
var downloadProgressHandler: (handler: ProgressHandler, queue: DispatchQueue)?
/// `RedirectHandler` provided for to handle request redirection.
- var redirectHandler: RedirectHandler?
+ var redirectHandler: (any RedirectHandler)?
/// `CachedResponseHandler` provided to handle response caching.
- var cachedResponseHandler: CachedResponseHandler?
+ var cachedResponseHandler: (any CachedResponseHandler)?
/// Queue and closure called when the `Request` is able to create a cURL description of itself.
var cURLHandler: (queue: DispatchQueue, handler: (String) -> Void)?
/// Queue and closure called when the `Request` creates a `URLRequest`.
@@ -165,7 +165,7 @@ public class Request {
// MARK: Redirect Handling
/// `RedirectHandler` set on the instance.
- public private(set) var redirectHandler: RedirectHandler? {
+ public private(set) var redirectHandler: (any RedirectHandler)? {
get { $mutableState.redirectHandler }
set { $mutableState.redirectHandler = newValue }
}
@@ -173,7 +173,7 @@ public class Request {
// MARK: Cached Response Handling
/// `CachedResponseHandler` set on the instance.
- public private(set) var cachedResponseHandler: CachedResponseHandler? {
+ public private(set) var cachedResponseHandler: (any CachedResponseHandler)? {
get { $mutableState.cachedResponseHandler }
set { $mutableState.cachedResponseHandler = newValue }
}
@@ -1083,7 +1083,7 @@ public protocol RequestDelegate: AnyObject {
/// `Request` subclass which handles in-memory `Data` download using `URLSessionDataTask`.
public class DataRequest: Request {
/// `URLRequestConvertible` value used to create `URLRequest`s for this instance.
- public let convertible: URLRequestConvertible
+ public let convertible: any URLRequestConvertible
/// `Data` read from the server so far.
public var data: Data? { mutableData }
@@ -1244,7 +1244,7 @@ public final class DataStreamRequest: Request {
}
/// `URLRequestConvertible` value used to create `URLRequest`s for this instance.
- public let convertible: URLRequestConvertible
+ public let convertible: any URLRequestConvertible
/// Whether or not the instance will be cancelled if stream parsing encounters an error.
public let automaticallyCancelOnStreamError: Bool
@@ -1778,7 +1778,7 @@ public class UploadRequest: DataRequest {
// MARK: Initial State
/// The `UploadableConvertible` value used to produce the `Uploadable` value for this instance.
- public let upload: UploadableConvertible
+ public let upload: any UploadableConvertible
/// `FileManager` used to perform cleanup tasks, including the removal of multipart form encoded payloads written
/// to disk.
diff --git a/Source/RequestInterceptor.swift b/Source/RequestInterceptor.swift
index 7ed39a5..f591ee7 100644
--- a/Source/RequestInterceptor.swift
+++ b/Source/RequestInterceptor.swift
@@ -43,7 +43,7 @@ public protocol RequestAdapter {
/// - urlRequest: The `URLRequest` to adapt.
/// - session: The `Session` that will execute the `URLRequest`.
/// - completion: The completion handler that must be called when adaptation is complete.
- func adapt(_ urlRequest: URLRequest, for session: Session, completion: @escaping (Result<URLRequest, Error>) -> Void)
+ func adapt(_ urlRequest: URLRequest, for session: Session, completion: @escaping (Result<URLRequest, any Error>) -> Void)
/// Inspects and adapts the specified `URLRequest` in some manner and calls the completion handler with the Result.
///
@@ -51,11 +51,11 @@ public protocol RequestAdapter {
/// - urlRequest: The `URLRequest` to adapt.
/// - state: The `RequestAdapterState` associated with the `URLRequest`.
/// - completion: The completion handler that must be called when adaptation is complete.
- func adapt(_ urlRequest: URLRequest, using state: RequestAdapterState, completion: @escaping (Result<URLRequest, Error>) -> Void)
+ func adapt(_ urlRequest: URLRequest, using state: RequestAdapterState, completion: @escaping (Result<URLRequest, any Error>) -> Void)
}
extension RequestAdapter {
- public func adapt(_ urlRequest: URLRequest, using state: RequestAdapterState, completion: @escaping (Result<URLRequest, Error>) -> Void) {
+ public func adapt(_ urlRequest: URLRequest, using state: RequestAdapterState, completion: @escaping (Result<URLRequest, any Error>) -> Void) {
adapt(urlRequest, for: state.session, completion: completion)
}
}
@@ -89,7 +89,7 @@ extension RetryResult {
}
}
- var error: Error? {
+ var error: (any Error)? {
guard case let .doNotRetryWithError(error) = self else { return nil }
return error
}
@@ -118,7 +118,7 @@ public protocol RequestRetrier {
public protocol RequestInterceptor: RequestAdapter, RequestRetrier {}
extension RequestInterceptor {
- public func adapt(_ urlRequest: URLRequest, for session: Session, completion: @escaping (Result<URLRequest, Error>) -> Void) {
+ public func adapt(_ urlRequest: URLRequest, for session: Session, completion: @escaping (Result<URLRequest, any Error>) -> Void) {
completion(.success(urlRequest))
}
@@ -148,11 +148,11 @@ open class Adapter: RequestInterceptor {
self.adaptHandler = adaptHandler
}
- open func adapt(_ urlRequest: URLRequest, for session: Session, completion: @escaping (Result<URLRequest, Error>) -> Void) {
+ open func adapt(_ urlRequest: URLRequest, for session: Session, completion: @escaping (Result<URLRequest, any Error>) -> Void) {
adaptHandler(urlRequest, session, completion)
}
- open func adapt(_ urlRequest: URLRequest, using state: RequestAdapterState, completion: @escaping (Result<URLRequest, Error>) -> Void) {
+ open func adapt(_ urlRequest: URLRequest, using state: RequestAdapterState, completion: @escaping (Result<URLRequest, any Error>) -> Void) {
adaptHandler(urlRequest, state.session, completion)
}
}
@@ -207,9 +207,9 @@ extension RequestRetrier where Self == Retrier {
/// `RequestInterceptor` which can use multiple `RequestAdapter` and `RequestRetrier` values.
open class Interceptor: RequestInterceptor {
/// All `RequestAdapter`s associated with the instance. These adapters will be run until one fails.
- public let adapters: [RequestAdapter]
+ public let adapters: [any RequestAdapter]
/// All `RequestRetrier`s associated with the instance. These retriers will be run one at a time until one triggers retry.
- public let retriers: [RequestRetrier]
+ public let retriers: [any RequestRetrier]
/// Creates an instance from `AdaptHandler` and `RetryHandler` closures.
///
@@ -242,14 +242,14 @@ open class Interceptor: RequestInterceptor {
self.retriers = retriers + interceptors
}
- open func adapt(_ urlRequest: URLRequest, for session: Session, completion: @escaping (Result<URLRequest, Error>) -> Void) {
+ open func adapt(_ urlRequest: URLRequest, for session: Session, completion: @escaping (Result<URLRequest, any Error>) -> Void) {
adapt(urlRequest, for: session, using: adapters, completion: completion)
}
private func adapt(_ urlRequest: URLRequest,
for session: Session,
- using adapters: [RequestAdapter],
- completion: @escaping (Result<URLRequest, Error>) -> Void) {
+ using adapters: [any RequestAdapter],
+ completion: @escaping (Result<URLRequest, any Error>) -> Void) {
var pendingAdapters = adapters
guard !pendingAdapters.isEmpty else { completion(.success(urlRequest)); return }
@@ -266,14 +266,14 @@ open class Interceptor: RequestInterceptor {
}
}
- open func adapt(_ urlRequest: URLRequest, using state: RequestAdapterState, completion: @escaping (Result<URLRequest, Error>) -> Void) {
+ open func adapt(_ urlRequest: URLRequest, using state: RequestAdapterState, completion: @escaping (Result<URLRequest, any Error>) -> Void) {
adapt(urlRequest, using: state, adapters: adapters, completion: completion)
}
private func adapt(_ urlRequest: URLRequest,
using state: RequestAdapterState,
- adapters: [RequestAdapter],
- completion: @escaping (Result<URLRequest, Error>) -> Void) {
+ adapters: [any RequestAdapter],
+ completion: @escaping (Result<URLRequest, any Error>) -> Void) {
var pendingAdapters = adapters
guard !pendingAdapters.isEmpty else { completion(.success(urlRequest)); return }
@@ -300,7 +300,7 @@ open class Interceptor: RequestInterceptor {
private func retry(_ request: Request,
for session: Session,
dueTo error: Error,
- using retriers: [RequestRetrier],
+ using retriers: [any RequestRetrier],
completion: @escaping (RetryResult) -> Void) {
var pendingRetriers = retriers
diff --git a/Source/ResponseSerialization.swift b/Source/ResponseSerialization.swift
index 3097364..03130ef 100644
--- a/Source/ResponseSerialization.swift
+++ b/Source/ResponseSerialization.swift
@@ -65,7 +65,7 @@ public protocol DownloadResponseSerializerProtocol {
/// A serializer that can handle both data and download responses.
public protocol ResponseSerializer: DataResponseSerializerProtocol & DownloadResponseSerializerProtocol {
/// `DataPreprocessor` used to prepare incoming `Data` for serialization.
- var dataPreprocessor: DataPreprocessor { get }
+ var dataPreprocessor: any DataPreprocessor { get }
/// `HTTPMethod`s for which empty response bodies are considered appropriate.
var emptyRequestMethods: Set<HTTPMethod> { get }
/// HTTP response codes for which empty response bodies are considered appropriate.
diff --git a/Source/Result+Alamofire.swift b/Source/Result+Alamofire.swift
index 39ac286..6fe83ab 100644
--- a/Source/Result+Alamofire.swift
+++ b/Source/Result+Alamofire.swift
@@ -79,7 +79,7 @@ extension Result {
///
/// - returns: A `Result` containing the result of the given closure. If this instance is a failure, returns the
/// same failure.
- func tryMap<NewSuccess>(_ transform: (Success) throws -> NewSuccess) -> Result<NewSuccess, Error> {
+ func tryMap<NewSuccess>(_ transform: (Success) throws -> NewSuccess) -> Result<NewSuccess, any Error> {
switch self {
case let .success(value):
do {
@@ -105,7 +105,7 @@ extension Result {
///
/// - Returns: A `Result` instance containing the result of the transform. If this instance is a success, returns
/// the same success.
- func tryMapError<NewFailure: Error>(_ transform: (Failure) throws -> NewFailure) -> Result<Success, Error> {
+ func tryMapError<NewFailure: Error>(_ transform: (Failure) throws -> NewFailure) -> Result<Success, any Error> {
switch self {
case let .failure(error):
do {
diff --git a/Source/Session.swift b/Source/Session.swift
index 4232f85..3be3c97 100644
--- a/Source/Session.swift
+++ b/Source/Session.swift
@@ -54,17 +54,17 @@ open class Session {
public let serializationQueue: DispatchQueue
/// `RequestInterceptor` used for all `Request` created by the instance. `RequestInterceptor`s can also be set on a
/// per-`Request` basis, in which case the `Request`'s interceptor takes precedence over this value.
- public let interceptor: RequestInterceptor?
+ public let interceptor: (any RequestInterceptor)?
/// `ServerTrustManager` instance used to evaluate all trust challenges and provide certificate and key pinning.
public let serverTrustManager: ServerTrustManager?
/// `RedirectHandler` instance used to provide customization for request redirection.
- public let redirectHandler: RedirectHandler?
+ public let redirectHandler: (any RedirectHandler)?
/// `CachedResponseHandler` instance used to provide customization of cached response handling.
- public let cachedResponseHandler: CachedResponseHandler?
+ public let cachedResponseHandler: (any CachedResponseHandler)?
/// `CompositeEventMonitor` used to compose Alamofire's `defaultEventMonitors` and any passed `EventMonitor`s.
public let eventMonitor: CompositeEventMonitor
/// `EventMonitor`s included in all instances. `[AlamofireNotifications()]` by default.
- public let defaultEventMonitors: [EventMonitor] = [AlamofireNotifications()]
+ public let defaultEventMonitors: [any EventMonitor] = [AlamofireNotifications()]
/// Internal map between `Request`s and any `URLSessionTasks` that may be in flight for them.
var requestTaskMap = RequestTaskMap()
Iām sure this sounds "not serious" and a bit arbitrary, being neither eliding to one or the other in a seemingly non-deterministic way but the rules aren't that complicated and essentially amount to continuing to use an existential when the value is contained in another type so as not to leak itās genericisity to the containing type.
In this way the net effect of this aspect of Swift 6 would be reaping the benefits of a partial migration directly to some
without trying to apply it where it wouldn't have been appropriate anyway which seems to be reasonably easy to determine.
Alamofire is great starting point. It is a popular, rich codebase which makes extensive use of protocols. If it can be made to build without modification that would bode well for the existing Swift codebase.