From 104326b07288b2d26e3a869664ba9cf5bfa60886 Mon Sep 17 00:00:00 2001 From: Stephen Celis Date: Mon, 22 Jan 2024 14:56:23 -0800 Subject: [PATCH] Make `XCTestContext` sendable (#74) With concurrency warnings dialed up, this type can cause warnings to be emitted, but as a task local should be safe to pass along. --- Package.swift | 4 +- .../Internal/GeneratePlaceholder.swift | 144 ++++-------------- Sources/XCTestDynamicOverlay/XCTFail.swift | 2 +- 3 files changed, 29 insertions(+), 121 deletions(-) diff --git a/Package.swift b/Package.swift index af999ba2..d3658fcf 100644 --- a/Package.swift +++ b/Package.swift @@ -1,4 +1,4 @@ -// swift-tools-version:5.5 +// swift-tools-version:5.7 import PackageDescription @@ -22,7 +22,7 @@ let package = Package( ] ) -#if swift(>=5.6) && !os(Windows) +#if !os(Windows) // Add the documentation compiler plugin if possible package.dependencies.append( .package(url: "https://github.com/apple/swift-docc-plugin", from: "1.0.0") diff --git a/Sources/XCTestDynamicOverlay/Internal/GeneratePlaceholder.swift b/Sources/XCTestDynamicOverlay/Internal/GeneratePlaceholder.swift index 5eb1a0ae..27bcf7c9 100644 --- a/Sources/XCTestDynamicOverlay/Internal/GeneratePlaceholder.swift +++ b/Sources/XCTestDynamicOverlay/Internal/GeneratePlaceholder.swift @@ -17,133 +17,41 @@ private func _optionalPlaceholder() throws -> Result { throw PlaceholderGenerationFailure() } -#if swift(>=5.7) - private func _placeholder() -> Result? { - switch Result.self { - case let type as _DefaultInitializable.Type: return type.placeholder as? Result - case is Void.Type: return () as? Result - case let type as any RangeReplaceableCollection.Type: return type.placeholder as? Result - case let type as any AdditiveArithmetic.Type: return type.placeholder as? Result - case let type as any ExpressibleByArrayLiteral.Type: return type.placeholder as? Result - case let type as any ExpressibleByBooleanLiteral.Type: return type.placeholder as? Result - case let type as any ExpressibleByDictionaryLiteral.Type: return type.placeholder as? Result - case let type as any ExpressibleByFloatLiteral.Type: return type.placeholder as? Result - case let type as any ExpressibleByIntegerLiteral.Type: return type.placeholder as? Result - case let type as any ExpressibleByUnicodeScalarLiteral.Type: return type.placeholder as? Result - default: return nil - } - } - - private func _rawRepresentable() -> Result? { - func posiblePlaceholder(for type: T.Type) -> T? { - (_placeholder() as T.RawValue?).flatMap(T.init(rawValue:)) - } - - return (Result.self as? any RawRepresentable.Type).flatMap { - posiblePlaceholder(for: $0) as? Result - } - } - - private func _caseIterable() -> Result? { - func firstCase(for type: T.Type) -> Result? { - T.allCases.first as? Result - } - - return (Result.self as? any CaseIterable.Type).flatMap { - firstCase(for: $0) - } - } -#else - private func _placeholder() -> Result? { - if let result = (Result.self as? _DefaultInitializable.Type)?.placeholder { - return result as? Result - } - - if Result.self == Void.self { - return () as? Result - } - - switch Witness.self { - case let type as AnyRangeReplaceableCollection.Type: return type.placeholder as? Result - case let type as AnyAdditiveArithmetic.Type: return type.placeholder as? Result - case let type as AnyExpressibleByArrayLiteral.Type: return type.placeholder as? Result - case let type as AnyExpressibleByBooleanLiteral.Type: return type.placeholder as? Result - case let type as AnyExpressibleByDictionaryLiteral.Type: return type.placeholder as? Result - case let type as AnyExpressibleByFloatLiteral.Type: return type.placeholder as? Result - case let type as AnyExpressibleByIntegerLiteral.Type: return type.placeholder as? Result - case let type as AnyExpressibleByUnicodeScalarLiteral.Type: return type.placeholder as? Result - default: return nil - } - } - - private func _rawRepresentable() -> Result? { - (Witness.self as? AnyRawRepresentable.Type).flatMap { - $0.possiblePlaceholder as? Result - } - } - - private func _caseIterable() -> Result? { - (Witness.self as? AnyCaseIterable.Type).flatMap { - $0.firstCase as? Result - } - } - - private enum Witness {} - private protocol AnyAdditiveArithmetic { static var placeholder: Any { get } } - extension Witness: AnyAdditiveArithmetic where Value: AdditiveArithmetic { - fileprivate static var placeholder: Any { Value.placeholder } - } - - private protocol AnyExpressibleByArrayLiteral { static var placeholder: Any { get } } - extension Witness: AnyExpressibleByArrayLiteral where Value: ExpressibleByArrayLiteral { - fileprivate static var placeholder: Any { Value.placeholder } - } - - private protocol AnyExpressibleByBooleanLiteral { static var placeholder: Any { get } } - extension Witness: AnyExpressibleByBooleanLiteral where Value: ExpressibleByBooleanLiteral { - fileprivate static var placeholder: Any { Value.placeholder } - } - - private protocol AnyExpressibleByDictionaryLiteral { static var placeholder: Any { get } } - extension Witness: AnyExpressibleByDictionaryLiteral where Value: ExpressibleByDictionaryLiteral { - fileprivate static var placeholder: Any { Value.placeholder } - } - - private protocol AnyExpressibleByFloatLiteral { static var placeholder: Any { get } } - extension Witness: AnyExpressibleByFloatLiteral where Value: ExpressibleByFloatLiteral { - fileprivate static var placeholder: Any { Value.placeholder } - } - - private protocol AnyExpressibleByIntegerLiteral { static var placeholder: Any { get } } - extension Witness: AnyExpressibleByIntegerLiteral where Value: ExpressibleByIntegerLiteral { - fileprivate static var placeholder: Any { Value.placeholder } +private func _placeholder() -> Result? { + switch Result.self { + case let type as _DefaultInitializable.Type: return type.placeholder as? Result + case is Void.Type: return () as? Result + case let type as any RangeReplaceableCollection.Type: return type.placeholder as? Result + case let type as any AdditiveArithmetic.Type: return type.placeholder as? Result + case let type as any ExpressibleByArrayLiteral.Type: return type.placeholder as? Result + case let type as any ExpressibleByBooleanLiteral.Type: return type.placeholder as? Result + case let type as any ExpressibleByDictionaryLiteral.Type: return type.placeholder as? Result + case let type as any ExpressibleByFloatLiteral.Type: return type.placeholder as? Result + case let type as any ExpressibleByIntegerLiteral.Type: return type.placeholder as? Result + case let type as any ExpressibleByUnicodeScalarLiteral.Type: return type.placeholder as? Result + default: return nil } +} - private protocol AnyExpressibleByUnicodeScalarLiteral { static var placeholder: Any { get } } - extension Witness: AnyExpressibleByUnicodeScalarLiteral - where Value: ExpressibleByUnicodeScalarLiteral { - fileprivate static var placeholder: Any { Value.placeholder } +private func _rawRepresentable() -> Result? { + func posiblePlaceholder(for type: T.Type) -> T? { + (_placeholder() as T.RawValue?).flatMap(T.init(rawValue:)) } - private protocol AnyRangeReplaceableCollection { static var placeholder: Any { get } } - extension Witness: AnyRangeReplaceableCollection where Value: RangeReplaceableCollection { - fileprivate static var placeholder: Any { Value.placeholder } + return (Result.self as? any RawRepresentable.Type).flatMap { + posiblePlaceholder(for: $0) as? Result } +} - private protocol AnyRawRepresentable { static var possiblePlaceholder: Any? { get } } - extension Witness: AnyRawRepresentable where Value: RawRepresentable { - fileprivate static var possiblePlaceholder: Any? { - (_placeholder() as Value.RawValue?).flatMap(Value.init(rawValue:)) - } +private func _caseIterable() -> Result? { + func firstCase(for type: T.Type) -> Result? { + T.allCases.first as? Result } - private protocol AnyCaseIterable { static var firstCase: Any? { get } } - extension Witness: AnyCaseIterable where Value: CaseIterable { - fileprivate static var firstCase: Any? { - Value.allCases.first - } + return (Result.self as? any CaseIterable.Type).flatMap { + firstCase(for: $0) } -#endif +} struct PlaceholderGenerationFailure: Error {} func _generatePlaceholder() throws -> Result { diff --git a/Sources/XCTestDynamicOverlay/XCTFail.swift b/Sources/XCTestDynamicOverlay/XCTFail.swift index f9311c23..fd60b09a 100644 --- a/Sources/XCTestDynamicOverlay/XCTFail.swift +++ b/Sources/XCTestDynamicOverlay/XCTFail.swift @@ -1,6 +1,6 @@ import Foundation -public struct XCTFailContext { +public struct XCTFailContext: Sendable { @TaskLocal public static var current: Self? public var file: StaticString