From 90b06a7937e6cbf6431a84b6f099a2fb3b929ffb Mon Sep 17 00:00:00 2001 From: Jeremy Schonfeld Date: Tue, 16 Jul 2024 17:00:59 -0700 Subject: [PATCH 1/2] (131556645) Restore sendable annotations --- .../AttributedString/AttributeScope.swift | 2 +- ...ibutedString+AttributeTransformation.swift | 76 ++++- ...ttributedString+Runs+AttributeSlices.swift | 66 +++- .../PredicateCodableConfiguration.swift | 49 +-- .../PredicateExpressionConstruction.swift | 2 +- .../Predicate/PredicateExpression.swift | 31 +- .../FoundationEssentials/SortComparator.swift | 35 +- .../String/KeyPathComparator.swift | 79 +++-- .../String/SortDescriptor.swift | 317 +++++++++++++++--- .../PredicateCodableTests.swift | 4 +- 10 files changed, 525 insertions(+), 136 deletions(-) diff --git a/Sources/FoundationEssentials/AttributedString/AttributeScope.swift b/Sources/FoundationEssentials/AttributedString/AttributeScope.swift index a9e5a4e28..43ae67bef 100644 --- a/Sources/FoundationEssentials/AttributedString/AttributeScope.swift +++ b/Sources/FoundationEssentials/AttributedString/AttributeScope.swift @@ -31,7 +31,7 @@ public enum AttributeScopes { } import Darwin internal import MachO.dyld -@preconcurrency internal import ReflectionInternal +internal import ReflectionInternal fileprivate struct ScopeDescription : Sendable { var attributes: [String : any AttributedStringKey.Type] = [:] diff --git a/Sources/FoundationEssentials/AttributedString/AttributedString+AttributeTransformation.swift b/Sources/FoundationEssentials/AttributedString/AttributedString+AttributeTransformation.swift index 72b506cbe..acf2a878d 100644 --- a/Sources/FoundationEssentials/AttributedString/AttributedString+AttributeTransformation.swift +++ b/Sources/FoundationEssentials/AttributedString/AttributedString+AttributeTransformation.swift @@ -52,7 +52,9 @@ extension AttributedString { andChanged changed: AttributedString.SingleAttributeTransformer, to attrStr: inout AttributedString, key: K.Type - ) { + ) + where + K.Value : Sendable { if orig.range != changed.range || orig.attrName != changed.attrName { attrStr._guts.removeAttributeValue(forKey: K.self, in: orig.range._bstringRange) // If the range changed, we need to remove from the old range first. } @@ -63,7 +65,7 @@ extension AttributedString { andChanged changed: AttributedString.SingleAttributeTransformer, to attrStr: inout AttributedString, key: K.Type - ) { + ) where K.Value : Sendable { if orig.range != changed.range || orig.attrName != changed.attrName || orig.attr != changed.attr { if let newVal = changed.attr { // Then if there's a new value, we add it in. // Unfortunately, we can't use the attrStr[range].set() provided by the AttributedStringProtocol, because we *don't know* the new type statically! @@ -78,10 +80,13 @@ extension AttributedString { @available(macOS 12, iOS 15, tvOS 15, watchOS 8, *) extension AttributedString { + @preconcurrency public func transformingAttributes( _ k: K.Type, _ c: (inout AttributedString.SingleAttributeTransformer) -> Void - ) -> AttributedString { + ) -> AttributedString + where + K.Value : Sendable { let orig = AttributedString(_guts) var copy = orig copy.ensureUniqueReference() // ???: Is this best practice? We're going behind the back of the AttributedString mutation API surface, so it doesn't happen anywhere else. It's also aggressively speculative. @@ -95,12 +100,16 @@ extension AttributedString { return copy } + @preconcurrency public func transformingAttributes( _ k: K1.Type, _ k2: K2.Type, _ c: (inout AttributedString.SingleAttributeTransformer, inout AttributedString.SingleAttributeTransformer) -> Void - ) -> AttributedString { + ) -> AttributedString + where + K1.Value : Sendable, + K2.Value : Sendable { let orig = AttributedString(_guts) var copy = orig copy.ensureUniqueReference() // ???: Is this best practice? We're going behind the back of the AttributedString mutation API surface, so it doesn't happen anywhere else. It's also aggressively speculative. @@ -118,6 +127,7 @@ extension AttributedString { return copy } + @preconcurrency public func transformingAttributes( _ k: K1.Type, _ k2: K2.Type, @@ -125,7 +135,11 @@ extension AttributedString { _ c: (inout AttributedString.SingleAttributeTransformer, inout AttributedString.SingleAttributeTransformer, inout AttributedString.SingleAttributeTransformer) -> Void - ) -> AttributedString { + ) -> AttributedString + where + K1.Value : Sendable, + K2.Value : Sendable, + K3.Value : Sendable { let orig = AttributedString(_guts) var copy = orig copy.ensureUniqueReference() // ???: Is this best practice? We're going behind the back of the AttributedString mutation API surface, so it doesn't happen anywhere else. It's also aggressively speculative. @@ -147,6 +161,7 @@ extension AttributedString { return copy } + @preconcurrency public func transformingAttributes( _ k: K1.Type, _ k2: K2.Type, @@ -156,7 +171,12 @@ extension AttributedString { inout AttributedString.SingleAttributeTransformer, inout AttributedString.SingleAttributeTransformer, inout AttributedString.SingleAttributeTransformer) -> Void - ) -> AttributedString { + ) -> AttributedString + where + K1.Value : Sendable, + K2.Value : Sendable, + K3.Value : Sendable, + K4.Value : Sendable { let orig = AttributedString(_guts) var copy = orig copy.ensureUniqueReference() // ???: Is this best practice? We're going behind the back of the AttributedString mutation API surface, so it doesn't happen anywhere else. It's also aggressively speculative. @@ -182,6 +202,7 @@ extension AttributedString { return copy } + @preconcurrency public func transformingAttributes( _ k: K1.Type, _ k2: K2.Type, @@ -193,7 +214,13 @@ extension AttributedString { inout AttributedString.SingleAttributeTransformer, inout AttributedString.SingleAttributeTransformer, inout AttributedString.SingleAttributeTransformer) -> Void - ) -> AttributedString { + ) -> AttributedString + where + K1.Value : Sendable, + K2.Value : Sendable, + K3.Value : Sendable, + K4.Value : Sendable, + K5.Value : Sendable { let orig = AttributedString(_guts) var copy = orig copy.ensureUniqueReference() // ???: Is this best practice? We're going behind the back of the AttributedString mutation API surface, so it doesn't happen anywhere else. It's also aggressively speculative. @@ -226,22 +253,30 @@ extension AttributedString { @available(macOS 12, iOS 15, tvOS 15, watchOS 8, *) extension AttributedString { + @preconcurrency public func transformingAttributes( _ k: KeyPath, _ c: (inout AttributedString.SingleAttributeTransformer) -> Void - ) -> AttributedString { + ) -> AttributedString + where + K.Value : Sendable { self.transformingAttributes(K.self, c) } + @preconcurrency public func transformingAttributes( _ k: KeyPath, _ k2: KeyPath, _ c: (inout AttributedString.SingleAttributeTransformer, inout AttributedString.SingleAttributeTransformer) -> Void - ) -> AttributedString { + ) -> AttributedString + where + K1.Value : Sendable, + K2.Value : Sendable { self.transformingAttributes(K1.self, K2.self, c) } + @preconcurrency public func transformingAttributes( _ k: KeyPath, _ k2: KeyPath, @@ -249,10 +284,15 @@ extension AttributedString { _ c: (inout AttributedString.SingleAttributeTransformer, inout AttributedString.SingleAttributeTransformer, inout AttributedString.SingleAttributeTransformer) -> Void - ) -> AttributedString { + ) -> AttributedString + where + K1.Value : Sendable, + K2.Value : Sendable, + K3.Value : Sendable { self.transformingAttributes(K1.self, K2.self, K3.self, c) } + @preconcurrency public func transformingAttributes( _ k: KeyPath, _ k2: KeyPath, @@ -262,10 +302,16 @@ extension AttributedString { inout AttributedString.SingleAttributeTransformer, inout AttributedString.SingleAttributeTransformer, inout AttributedString.SingleAttributeTransformer) -> Void - ) -> AttributedString { + ) -> AttributedString + where + K1.Value : Sendable, + K2.Value : Sendable, + K3.Value : Sendable, + K4.Value : Sendable { self.transformingAttributes(K1.self, K2.self, K3.self, K4.self, c) } + @preconcurrency public func transformingAttributes( _ k: KeyPath, _ k2: KeyPath, @@ -277,7 +323,13 @@ extension AttributedString { inout AttributedString.SingleAttributeTransformer, inout AttributedString.SingleAttributeTransformer, inout AttributedString.SingleAttributeTransformer) -> Void - ) -> AttributedString { + ) -> AttributedString + where + K1.Value : Sendable, + K2.Value : Sendable, + K3.Value : Sendable, + K4.Value : Sendable, + K5.Value : Sendable { self.transformingAttributes(K1.self, K2.self, K3.self, K4.self, K5.self, c) } } diff --git a/Sources/FoundationEssentials/AttributedString/AttributedString+Runs+AttributeSlices.swift b/Sources/FoundationEssentials/AttributedString/AttributedString+Runs+AttributeSlices.swift index 0a01046a6..1cd2760fc 100644 --- a/Sources/FoundationEssentials/AttributedString/AttributedString+Runs+AttributeSlices.swift +++ b/Sources/FoundationEssentials/AttributedString/AttributedString+Runs+AttributeSlices.swift @@ -100,11 +100,13 @@ extension AttributedString.Runs { // down to the nearest valid indices. } - public subscript(_ keyPath: KeyPath) -> AttributesSlice1 { + @preconcurrency + public subscript(_ keyPath: KeyPath) -> AttributesSlice1 where T.Value : Sendable { return AttributesSlice1(runs: self) } - public subscript(_ t: T.Type) -> AttributesSlice1 { + @preconcurrency + public subscript(_ t: T.Type) -> AttributesSlice1 where T.Value : Sendable { return AttributesSlice1(runs: self) } } @@ -205,23 +207,31 @@ extension AttributedString.Runs { // down to the nearest valid indices. } + @preconcurrency public subscript < T : AttributedStringKey, U : AttributedStringKey > ( _ t: KeyPath, _ u: KeyPath - ) -> AttributesSlice2 { + ) -> AttributesSlice2 + where + T.Value : Sendable, + U.Value : Sendable { return AttributesSlice2(runs: self) } + @preconcurrency public subscript < T : AttributedStringKey, U : AttributedStringKey > ( _ t: T.Type, _ u: U.Type - ) -> AttributesSlice2 { + ) -> AttributesSlice2 + where + T.Value : Sendable, + U.Value : Sendable { return AttributesSlice2(runs: self) } } @@ -328,6 +338,7 @@ extension AttributedString.Runs { // down to the nearest valid indices. } + @preconcurrency public subscript < T : AttributedStringKey, U : AttributedStringKey, @@ -336,10 +347,15 @@ extension AttributedString.Runs { _ t: KeyPath, _ u: KeyPath, _ v: KeyPath - ) -> AttributesSlice3 { + ) -> AttributesSlice3 + where + T.Value : Sendable, + U.Value : Sendable, + V.Value : Sendable { return AttributesSlice3(runs: self) } + @preconcurrency public subscript < T : AttributedStringKey, U : AttributedStringKey, @@ -348,7 +364,11 @@ extension AttributedString.Runs { _ t: T.Type, _ u: U.Type, _ v: V.Type - ) -> AttributesSlice3 { + ) -> AttributesSlice3 + where + T.Value : Sendable, + U.Value : Sendable, + V.Value : Sendable { return AttributesSlice3(runs: self) } } @@ -464,6 +484,7 @@ extension AttributedString.Runs { // down to the nearest valid indices. } + @preconcurrency public subscript < T : AttributedStringKey, U : AttributedStringKey, @@ -474,10 +495,16 @@ extension AttributedString.Runs { _ u: KeyPath, _ v: KeyPath, _ w: KeyPath - ) -> AttributesSlice4 { + ) -> AttributesSlice4 + where + T.Value : Sendable, + U.Value : Sendable, + V.Value : Sendable, + W.Value : Sendable { return AttributesSlice4(runs: self) } + @preconcurrency public subscript < T : AttributedStringKey, U : AttributedStringKey, @@ -488,7 +515,12 @@ extension AttributedString.Runs { _ u: U.Type, _ v: V.Type, _ w: W.Type - ) -> AttributesSlice4 { + ) -> AttributesSlice4 + where + T.Value : Sendable, + U.Value : Sendable, + V.Value : Sendable, + W.Value : Sendable { return AttributesSlice4(runs: self) } } @@ -610,6 +642,7 @@ extension AttributedString.Runs { // down to the nearest valid indices. } + @preconcurrency public subscript < T : AttributedStringKey, U : AttributedStringKey, @@ -622,10 +655,17 @@ extension AttributedString.Runs { _ v: KeyPath, _ w: KeyPath, _ x: KeyPath - ) -> AttributesSlice5 { + ) -> AttributesSlice5 + where + T.Value : Sendable, + U.Value : Sendable, + V.Value : Sendable, + W.Value : Sendable, + X.Value : Sendable { return AttributesSlice5(runs: self) } + @preconcurrency public subscript < T : AttributedStringKey, U : AttributedStringKey, @@ -638,7 +678,13 @@ extension AttributedString.Runs { _ v: V.Type, _ w: W.Type, _ x: X.Type - ) -> AttributesSlice5 { + ) -> AttributesSlice5 + where + T.Value : Sendable, + U.Value : Sendable, + V.Value : Sendable, + W.Value : Sendable, + X.Value : Sendable { return AttributesSlice5(runs: self) } } diff --git a/Sources/FoundationEssentials/Predicate/Archiving/PredicateCodableConfiguration.swift b/Sources/FoundationEssentials/Predicate/Archiving/PredicateCodableConfiguration.swift index 935912e04..3bd02eef7 100644 --- a/Sources/FoundationEssentials/Predicate/Archiving/PredicateCodableConfiguration.swift +++ b/Sources/FoundationEssentials/Predicate/Archiving/PredicateCodableConfiguration.swift @@ -13,11 +13,12 @@ #if FOUNDATION_FRAMEWORK #if canImport(ReflectionInternal) -@preconcurrency internal import ReflectionInternal +internal import ReflectionInternal @available(FoundationPredicate 0.1, *) public protocol PredicateCodableKeyPathProviding { - static var predicateCodableKeyPaths : [String : PartialKeyPath] { get } + @preconcurrency + static var predicateCodableKeyPaths : [String : PartialKeyPath & Sendable] { get } } @available(FoundationPredicate 0.1, *) @@ -48,7 +49,7 @@ public struct PredicateCodableConfiguration: Sendable, CustomDebugStringConverti } enum AllowListKeyPath : Equatable, Sendable { - typealias Constructor = @Sendable (GenericArguments) -> AnyKeyPath? + typealias Constructor = @Sendable (GenericArguments) -> (AnyKeyPath & Sendable)? case concrete(AnyKeyPath & Sendable) case partial(PartialType, Constructor, String) @@ -168,7 +169,17 @@ public struct PredicateCodableConfiguration: Sendable, CustomDebugStringConverti } } - public mutating func allowKeyPath(_ keyPath: AnyKeyPath, identifier: String) { + @_alwaysEmitIntoClient + public mutating func allowKeyPath(_ keyPath: AnyKeyPath & Sendable, identifier: String) { + self.allowKeyPath(keyPath as AnyKeyPath, identifier: identifier) + } + + @_alwaysEmitIntoClient + public mutating func disallowKeyPath(_ keyPath: AnyKeyPath & Sendable) { + self.disallowKeyPath(keyPath as AnyKeyPath) + } + + /*public*/ @usableFromInline mutating func allowKeyPath(_ keyPath: AnyKeyPath, identifier: String) { keyPath._validateForPredicateUsage() for (id, existingKeyPath) in allowedKeyPaths { if id == identifier { @@ -186,15 +197,15 @@ public struct PredicateCodableConfiguration: Sendable, CustomDebugStringConverti allowedKeyPaths[id] = nil } } - allowedKeyPaths[identifier] = .concrete(keyPath) + allowedKeyPaths[identifier] = .concrete(keyPath._unsafeAssumeSendableAnyKeyPath) _allowType(type(of: keyPath).rootType, preferNewIdentifier: false) _allowType(type(of: keyPath).valueType, preferNewIdentifier: false) } - public mutating func disallowKeyPath(_ keyPath: AnyKeyPath) { + /*public*/ @usableFromInline mutating func disallowKeyPath(_ keyPath: AnyKeyPath) { keyPath._validateForPredicateUsage() allowedKeyPaths = allowedKeyPaths.filter { - $0.value != .concrete(keyPath) + $0.value != .concrete(keyPath._unsafeAssumeSendableAnyKeyPath) } } @@ -259,7 +270,7 @@ public struct PredicateCodableConfiguration: Sendable, CustomDebugStringConverti @available(FoundationPredicate 0.1, *) extension PredicateCodableConfiguration { - func _identifier(for keyPath: AnyKeyPath) -> String? { + func _identifier(for keyPath: AnyKeyPath & Sendable) -> String? { let concreteIdentifier = allowedKeyPaths.first { $0.value == .concrete(keyPath) }?.key @@ -286,7 +297,7 @@ extension PredicateCodableConfiguration { return nil } - func _keyPath(for identifier: String, rootType: Any.Type) -> AnyKeyPath? { + func _keyPath(for identifier: String, rootType: Any.Type) -> (AnyKeyPath & Sendable)? { guard let value = allowedKeyPaths[identifier] else { return nil } @@ -418,7 +429,7 @@ extension PredicateCodableConfiguration { return nil } - func project(_: E.Type) -> AnyKeyPath { + func project(_: E.Type) -> AnyKeyPath & Sendable { \Array.count } return _openExistential(elementType.swiftType, do: project) @@ -428,7 +439,7 @@ extension PredicateCodableConfiguration { return nil } - func project(_: E.Type) -> AnyKeyPath { + func project(_: E.Type) -> AnyKeyPath & Sendable { \Array.isEmpty } return _openExistential(elementType.swiftType, do: project) @@ -438,7 +449,7 @@ extension PredicateCodableConfiguration { return nil } - func project(_: E.Type) -> AnyKeyPath { + func project(_: E.Type) -> AnyKeyPath & Sendable { \Array.first } return _openExistential(elementType.swiftType, do: project) @@ -448,7 +459,7 @@ extension PredicateCodableConfiguration { return nil } - func project(_: E.Type) -> AnyKeyPath { + func project(_: E.Type) -> AnyKeyPath & Sendable { \Array.last } return _openExistential(elementType.swiftType, do: project) @@ -460,7 +471,7 @@ extension PredicateCodableConfiguration { return nil } - func project(_: E.Type) -> AnyKeyPath { + func project(_: E.Type) -> AnyKeyPath & Sendable { \Set.count } return project(elementType) @@ -470,7 +481,7 @@ extension PredicateCodableConfiguration { return nil } - func project(_: E.Type) -> AnyKeyPath { + func project(_: E.Type) -> AnyKeyPath & Sendable { \Set.isEmpty } return project(elementType) @@ -482,8 +493,8 @@ extension PredicateCodableConfiguration { return nil } - func project(_: K.Type) -> AnyKeyPath { - func project2(_: V.Type) -> AnyKeyPath { + func project(_: K.Type) -> AnyKeyPath & Sendable { + func project2(_: V.Type) -> AnyKeyPath & Sendable { \Dictionary.count } return _openExistential(genericArgs[1].swiftType, do: project2) @@ -495,8 +506,8 @@ extension PredicateCodableConfiguration { return nil } - func project(_: K.Type) -> AnyKeyPath { - func project2(_: V.Type) -> AnyKeyPath { + func project(_: K.Type) -> AnyKeyPath & Sendable { + func project2(_: V.Type) -> AnyKeyPath & Sendable { \Dictionary.isEmpty } return _openExistential(genericArgs[1].swiftType, do: project2) diff --git a/Sources/FoundationEssentials/Predicate/Archiving/PredicateExpressionConstruction.swift b/Sources/FoundationEssentials/Predicate/Archiving/PredicateExpressionConstruction.swift index 89fc3d6c4..c400b5173 100644 --- a/Sources/FoundationEssentials/Predicate/Archiving/PredicateExpressionConstruction.swift +++ b/Sources/FoundationEssentials/Predicate/Archiving/PredicateExpressionConstruction.swift @@ -12,7 +12,7 @@ #if FOUNDATION_FRAMEWORK -@preconcurrency internal import ReflectionInternal +internal import ReflectionInternal @available(FoundationPredicate 0.1, *) enum PredicateCodableError : Error, CustomStringConvertible { diff --git a/Sources/FoundationEssentials/Predicate/PredicateExpression.swift b/Sources/FoundationEssentials/Predicate/PredicateExpression.swift index d4859abb6..3e8520ea8 100644 --- a/Sources/FoundationEssentials/Predicate/PredicateExpression.swift +++ b/Sources/FoundationEssentials/Predicate/PredicateExpression.swift @@ -172,10 +172,35 @@ extension PredicateExpressions { arg } - public static func build_KeyPath(root: Root, keyPath: Swift.KeyPath) -> PredicateExpressions.KeyPath { - KeyPath(root: root, keyPath: keyPath) + /* public */ + @usableFromInline static func build_KeyPath(root: Root, keyPath: Swift.KeyPath) -> PredicateExpressions.KeyPath { + KeyPath(root: root, keyPath: keyPath._unsafeAssumeSendable) } + + // A temporary workaround to a compiler bug that changes the ABI when adding the & Sendable constraint + // Should be removed and the above function should be made public when rdar://131764614 is resolved + @_alwaysEmitIntoClient + public static func build_KeyPath(root: Root, keyPath: Swift.KeyPath & Sendable) -> PredicateExpressions.KeyPath { + PredicateExpressions.build_KeyPath(root: root, keyPath: keyPath as Swift.KeyPath) + } +} +extension KeyPath { + package var _unsafeAssumeSendable: KeyPath & Sendable { + func _unsafeCast(_ t: T) -> U { + t as! U + } + return _unsafeCast(self) as KeyPath & Sendable + } +} + +extension AnyKeyPath { + package var _unsafeAssumeSendableAnyKeyPath: AnyKeyPath & Sendable { + func _unsafeCast(_ t: T) -> U { + t as! U + } + return _unsafeCast(self) as AnyKeyPath & Sendable + } } @available(FoundationPredicate 0.1, *) @@ -209,7 +234,7 @@ extension PredicateExpressions.KeyPath : Codable where Root : Codable { guard let kp = anykp as? Swift.KeyPath else { throw DecodingError.dataCorruptedError(forKey: .identifier, in: container, debugDescription: "Key path '\(anykp.debugDescription)' (KeyPath<\(_typeName(type(of: anykp).rootType)), \(_typeName(type(of: anykp).valueType))>) for identifier '\(identifier)' did not match the expression's requirement for KeyPath<\(_typeName(Root.Output.self)), \(_typeName(Output.self))>") } - self.keyPath = kp + self.keyPath = kp._unsafeAssumeSendable #else throw DecodingError.dataCorruptedError(forKey: .identifier, in: container, debugDescription: "Decoding PredicateExpressions.KeyPath is not supported") #endif // FOUNDATION_FRAMEWORK diff --git a/Sources/FoundationEssentials/SortComparator.swift b/Sources/FoundationEssentials/SortComparator.swift index a9ab4e072..c288dee68 100644 --- a/Sources/FoundationEssentials/SortComparator.swift +++ b/Sources/FoundationEssentials/SortComparator.swift @@ -11,8 +11,9 @@ //===----------------------------------------------------------------------===// /// A comparison algorithm for a given type. +@preconcurrency @available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) -public protocol SortComparator: Hashable { +public protocol SortComparator: Hashable, Sendable { /// The type that the `SortComparator` provides a comparison for. associatedtype Compared @@ -77,29 +78,26 @@ extension ComparisonResult { } @available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) -package struct AnySortComparator: SortComparator { - var _base: Any // internal for testing - - private var hashableBase: AnyHashable +package struct AnySortComparator: SortComparator, Sendable { + var _base: any Hashable & Sendable // internal for testing /// Takes `base` and two values to be compared and compares the two values /// using `base`. - private let _compare: (Any, Any, Any) -> ComparisonResult + private let _compare: @Sendable (Any, Any, Any) -> ComparisonResult /// Takes `base` inout, and a new `SortOrder` and changes `base`s `order` /// to match the new `SortOrder`. - private let setOrder: (inout Any, SortOrder) -> AnyHashable + private let setOrder: @Sendable (inout any Hashable & Sendable, SortOrder) -> any Hashable & Sendable /// Gets the current `order` property of `base`. - private let getOrder: (Any) -> SortOrder + private let getOrder: @Sendable (Any) -> SortOrder - package init(_ comparator: Comparator) { - self.hashableBase = AnyHashable(comparator) + package init(_ comparator: Comparator) where Comparator : Sendable { self._base = comparator self._compare = { (base: Any, lhs: Any, rhs: Any) -> ComparisonResult in (base as! Comparator).compare(lhs as! Comparator.Compared, rhs as! Comparator.Compared) } - self.setOrder = { (base: inout Any, newOrder: SortOrder) -> AnyHashable in + self.setOrder = { (base: inout any Hashable & Sendable, newOrder: SortOrder) -> AnyHashable in var typedBase = base as! Comparator typedBase.order = newOrder base = typedBase @@ -115,7 +113,7 @@ package struct AnySortComparator: SortComparator { return getOrder(_base) } set { - hashableBase = setOrder(&_base, newValue) + _base = setOrder(&_base, newValue) } } @@ -124,11 +122,18 @@ package struct AnySortComparator: SortComparator { } package func hash(into hasher: inout Hasher) { - hasher.combine(hashableBase) + hasher.combine(_base) } package static func == (lhs: Self, rhs: Self) -> Bool { - return lhs.hashableBase == rhs.hashableBase + func compare(_ l : L, _ r : R) -> Bool { + guard let rr = r as? L else { + return false + } + return l == rr + } + + return compare(lhs, rhs) } } @@ -185,6 +190,8 @@ package struct OptionalComparator: SortComparator { } } +extension OptionalComparator : Sendable where Base : Sendable { } + @available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) extension Never: SortComparator { public typealias Compared = Never diff --git a/Sources/FoundationInternationalization/String/KeyPathComparator.swift b/Sources/FoundationInternationalization/String/KeyPathComparator.swift index 8967652bd..38ec3bbc3 100644 --- a/Sources/FoundationInternationalization/String/KeyPathComparator.swift +++ b/Sources/FoundationInternationalization/String/KeyPathComparator.swift @@ -20,7 +20,8 @@ import FoundationEssentials @available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) public struct KeyPathComparator: SortComparator { /// The key path to the property to be used for comparisons. - public let keyPath: PartialKeyPath + @preconcurrency + public let keyPath: PartialKeyPath & Sendable public var order: SortOrder { get { @@ -33,7 +34,7 @@ public struct KeyPathComparator: SortComparator { var comparator: AnySortComparator - private let extractField: (Compared) -> Any + private let extractField: @Sendable (Compared) -> Any /// Get the field at `cachedOffset` if there is one, otherwise /// access the field directly through the keypath. @@ -49,6 +50,38 @@ public struct KeyPathComparator: SortComparator { .pointee } } + + // A temporary workaround to a compiler bug that changes the ABI when adding the & Sendable constraint + // Should be removed and the related functions should be made public when rdar://131764614 is resolved + @_alwaysEmitIntoClient + public init(_ keyPath: KeyPath & Sendable, order: SortOrder = .forward) { + self.init(keyPath as KeyPath, order: order) + } + + @_alwaysEmitIntoClient + public init(_ keyPath: KeyPath & Sendable, order: SortOrder = .forward) { + self.init(keyPath as KeyPath, order: order) + } + + @_alwaysEmitIntoClient + public init (_ keyPath: KeyPath & Sendable, comparator: Comparator) where Comparator.Compared == Value { + self.init(keyPath as KeyPath, comparator: comparator) + } + + @_alwaysEmitIntoClient + public init (_ keyPath: KeyPath & Sendable, comparator: Comparator) where Comparator.Compared == Value { + self.init(keyPath as KeyPath, comparator: comparator) + } + + @_alwaysEmitIntoClient + public init (_ keyPath: KeyPath & Sendable, comparator: Comparator, order: SortOrder) where Comparator.Compared == Value { + self.init(keyPath as KeyPath, comparator: comparator, order: order) + } + + @_alwaysEmitIntoClient + public init (_ keyPath: KeyPath & Sendable, comparator: Comparator, order: SortOrder) where Comparator.Compared == Value { + self.init(keyPath as KeyPath, comparator: comparator, order: order) + } /// Creates a `KeyPathComparator` that orders values based on a property /// that conforms to the `Comparable` protocol. @@ -60,8 +93,9 @@ public struct KeyPathComparator: SortComparator { /// - Parameters: /// - keyPath: The key path to the field to use for the comparison. /// - order: The initial order to use for comparison. - public init(_ keyPath: KeyPath, order: SortOrder = .forward) { - self.keyPath = keyPath + /*public*/ @usableFromInline init(_ keyPath: KeyPath, order: SortOrder = .forward) { + let sendableKP = keyPath._unsafeAssumeSendable + self.keyPath = sendableKP if Value.self is String.Type { #if FOUNDATION_FRAMEWORK self.comparator = AnySortComparator(String.StandardComparator.localizedStandard) @@ -79,7 +113,7 @@ public struct KeyPathComparator: SortComparator { ofType: Value.self, offset: cachedOffset, from: $0, - fallback: keyPath) + fallback: sendableKP) } self.order = order } @@ -97,8 +131,9 @@ public struct KeyPathComparator: SortComparator { /// - Parameters: /// - keyPath: The key path to the field to use for the comparison. /// - order: The initial order to use for comparison. - public init(_ keyPath: KeyPath, order: SortOrder = .forward) { - self.keyPath = keyPath + /*public*/ @usableFromInline init(_ keyPath: KeyPath, order: SortOrder = .forward) { + let sendableKP = keyPath._unsafeAssumeSendable + self.keyPath = sendableKP if Value.self is String.Type { #if FOUNDATION_FRAMEWORK self.comparator = AnySortComparator(OptionalComparator(String.StandardComparator.localizedStandard)) @@ -116,7 +151,7 @@ public struct KeyPathComparator: SortComparator { ofType: Value?.self, offset: cachedOffset, from: $0, - fallback: keyPath) as Any + fallback: sendableKP) as Any } self.order = order } @@ -130,8 +165,9 @@ public struct KeyPathComparator: SortComparator { /// - Parameters: /// - keyPath: The key path to the value used for the comparison. /// - comparator: The `SortComparator` used to order values. - public init (_ keyPath: KeyPath, comparator: Comparator) where Comparator.Compared == Value { - self.keyPath = keyPath + /*public*/ @usableFromInline init (_ keyPath: KeyPath, comparator: Comparator) where Comparator.Compared == Value { + let sendableKP = keyPath._unsafeAssumeSendable + self.keyPath = sendableKP self.comparator = AnySortComparator(comparator) let cachedOffset = MemoryLayout.offset(of: keyPath) self.extractField = { @@ -139,7 +175,7 @@ public struct KeyPathComparator: SortComparator { ofType: Value.self, offset: cachedOffset, from: $0, - fallback: keyPath) + fallback: sendableKP) } } @@ -155,8 +191,9 @@ public struct KeyPathComparator: SortComparator { /// - Parameters: /// - keyPath: The key path to the value used for the comparison. /// - comparator: The `SortComparator` used to order values. - public init (_ keyPath: KeyPath, comparator: Comparator) where Comparator.Compared == Value { - self.keyPath = keyPath + /*public*/ @usableFromInline init (_ keyPath: KeyPath, comparator: Comparator) where Comparator.Compared == Value { + let sendableKP = keyPath._unsafeAssumeSendable + self.keyPath = sendableKP self.comparator = AnySortComparator(OptionalComparator(comparator)) let cachedOffset = MemoryLayout.offset(of: keyPath) self.extractField = { @@ -164,7 +201,7 @@ public struct KeyPathComparator: SortComparator { ofType: Value?.self, offset: cachedOffset, from: $0, - fallback: keyPath) as Any + fallback: sendableKP) as Any } } @@ -175,8 +212,9 @@ public struct KeyPathComparator: SortComparator { /// - keyPath: The key path to the value used for the comparison. /// - comparator: The `SortComparator` used to order values. /// - order: The initial order to use for comparison. - public init (_ keyPath: KeyPath, comparator: Comparator, order: SortOrder) where Comparator.Compared == Value { - self.keyPath = keyPath + /*public*/ @usableFromInline init (_ keyPath: KeyPath, comparator: Comparator, order: SortOrder) where Comparator.Compared == Value { + let sendableKP = keyPath._unsafeAssumeSendable + self.keyPath = sendableKP self.comparator = AnySortComparator(comparator) let cachedOffset = MemoryLayout.offset(of: keyPath) self.extractField = { @@ -184,7 +222,7 @@ public struct KeyPathComparator: SortComparator { ofType: Value.self, offset: cachedOffset, from: $0, - fallback: keyPath) + fallback: sendableKP) } self.order = order } @@ -199,8 +237,9 @@ public struct KeyPathComparator: SortComparator { /// - keyPath: The key path to the value used for the comparison. /// - comparator: The `SortComparator` used to order values. /// - order: The initial order to use for comparison. - public init (_ keyPath: KeyPath, comparator: Comparator, order: SortOrder) where Comparator.Compared == Value { - self.keyPath = keyPath + /*public*/ @usableFromInline init (_ keyPath: KeyPath, comparator: Comparator, order: SortOrder) where Comparator.Compared == Value { + let sendableKP = keyPath._unsafeAssumeSendable + self.keyPath = sendableKP self.comparator = AnySortComparator(OptionalComparator(comparator)) let cachedOffset = MemoryLayout.offset(of: keyPath) self.extractField = { @@ -208,7 +247,7 @@ public struct KeyPathComparator: SortComparator { ofType: Value?.self, offset: cachedOffset, from: $0, - fallback: keyPath) as Any + fallback: sendableKP) as Any } self.order = order } diff --git a/Sources/FoundationInternationalization/String/SortDescriptor.swift b/Sources/FoundationInternationalization/String/SortDescriptor.swift index 5d0c2f473..29280c880 100644 --- a/Sources/FoundationInternationalization/String/SortDescriptor.swift +++ b/Sources/FoundationInternationalization/String/SortDescriptor.swift @@ -18,15 +18,15 @@ import FoundationEssentials @available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) public struct SortDescriptor: SortComparator, Codable, Sendable { /// The set of supported safely serializable comparisons. - enum AllowedComparison: Hashable, Codable { + enum AllowedComparison: Hashable, Codable, Sendable { /// Compare `String` by retrieving from key path, using using the given standard string comparator. - case comparableString(String.StandardComparator, KeyPath) + case comparableString(String.StandardComparator, KeyPath & Sendable) /// Compare `String?` by retrieving from key path, using using the given standard string comparator. - case comparableOptionalString(String.StandardComparator, KeyPath) + case comparableOptionalString(String.StandardComparator, KeyPath & Sendable) /// Compares using `Swift.Comparable` implementation. - case comparable(AnySortComparator, PartialKeyPath) + case comparable(AnySortComparator, PartialKeyPath & Sendable) #if FOUNDATION_FRAMEWORK /// Compares using the `compare` selector on the given type. @@ -233,6 +233,215 @@ public struct SortDescriptor: SortComparator, Codable, Sendable { // MARK: - Initializers for supported types. + + // A temporary workaround to a compiler bug that changes the ABI when adding the & Sendable constraint + // Should be removed and the related functions should be made public when rdar://131764614 is resolved + @_alwaysEmitIntoClient + @available(FoundationPreview 0.1, *) + public init(_ keyPath: KeyPath & Sendable, order: SortOrder = .forward) where Value: Comparable { + self.init(keyPath as KeyPath, order: order) + } + + @_alwaysEmitIntoClient + @available(FoundationPreview 0.1, *) + public init(_ keyPath: KeyPath & Sendable, order: SortOrder = .forward) where Value: Comparable { + self.init(keyPath as KeyPath, order: order) + } + + @_alwaysEmitIntoClient + @available(FoundationPreview 0.1, *) + public init(_ keyPath: KeyPath & Sendable, comparator: String.StandardComparator = .localizedStandard) { + self.init(keyPath as KeyPath, comparator: comparator) + } + + @_alwaysEmitIntoClient + @available(FoundationPreview 0.1, *) + public init(_ keyPath: KeyPath & Sendable, comparator: String.StandardComparator = .localizedStandard) { + self.init(keyPath as KeyPath, comparator: comparator) + } + + @_alwaysEmitIntoClient + @available(FoundationPreview 0.1, *) + public init(_ keyPath: KeyPath & Sendable, comparator: String.StandardComparator = .localizedStandard, order: SortOrder) { + self.init(keyPath as KeyPath, comparator: comparator, order: order) + } + + @_alwaysEmitIntoClient + @available(FoundationPreview 0.1, *) + public init(_ keyPath: KeyPath & Sendable, comparator: String.StandardComparator = .localizedStandard, order: SortOrder) { + self.init(keyPath as KeyPath, comparator: comparator, order: order) + } + + @_alwaysEmitIntoClient + public init(_ keyPath: KeyPath & Sendable, order: SortOrder = .forward) where Compared: NSObject { + self.init(keyPath as KeyPath, order: order) + } + + @_alwaysEmitIntoClient + public init(_ keyPath: KeyPath & Sendable, order: SortOrder = .forward) where Compared: NSObject { + self.init(keyPath as KeyPath, order: order) + } + + @_alwaysEmitIntoClient + public init(_ keyPath: KeyPath & Sendable, order: SortOrder = .forward) where Compared: NSObject { + self.init(keyPath as KeyPath, order: order) + } + + @_alwaysEmitIntoClient + public init(_ keyPath: KeyPath & Sendable, order: SortOrder = .forward) where Compared: NSObject { + self.init(keyPath as KeyPath, order: order) + } + + @_alwaysEmitIntoClient + public init(_ keyPath: KeyPath & Sendable, order: SortOrder = .forward) where Compared: NSObject { + self.init(keyPath as KeyPath, order: order) + } + + @_alwaysEmitIntoClient + public init(_ keyPath: KeyPath & Sendable, order: SortOrder = .forward) where Compared: NSObject { + self.init(keyPath as KeyPath, order: order) + } + + @_alwaysEmitIntoClient + public init(_ keyPath: KeyPath & Sendable, order: SortOrder = .forward) where Compared: NSObject { + self.init(keyPath as KeyPath, order: order) + } + + @_alwaysEmitIntoClient + public init(_ keyPath: KeyPath & Sendable, order: SortOrder = .forward) where Compared: NSObject { + self.init(keyPath as KeyPath, order: order) + } + + @_alwaysEmitIntoClient + public init(_ keyPath: KeyPath & Sendable, order: SortOrder = .forward) where Compared: NSObject { + self.init(keyPath as KeyPath, order: order) + } + + @_alwaysEmitIntoClient + public init(_ keyPath: KeyPath & Sendable, order: SortOrder = .forward) where Compared: NSObject { + self.init(keyPath as KeyPath, order: order) + } + + @_alwaysEmitIntoClient + public init(_ keyPath: KeyPath & Sendable, order: SortOrder = .forward) where Compared: NSObject { + self.init(keyPath as KeyPath, order: order) + } + + @_alwaysEmitIntoClient + public init(_ keyPath: KeyPath & Sendable, order: SortOrder = .forward) where Compared: NSObject { + self.init(keyPath as KeyPath, order: order) + } + + @_alwaysEmitIntoClient + public init(_ keyPath: KeyPath & Sendable, order: SortOrder = .forward) where Compared: NSObject { + self.init(keyPath as KeyPath, order: order) + } + + @_alwaysEmitIntoClient + public init(_ keyPath: KeyPath & Sendable, order: SortOrder = .forward) where Compared: NSObject { + self.init(keyPath as KeyPath, order: order) + } + + @_alwaysEmitIntoClient + public init(_ keyPath: KeyPath & Sendable, order: SortOrder = .forward) where Compared: NSObject { + self.init(keyPath as KeyPath, order: order) + } + + @_alwaysEmitIntoClient + public init(_ keyPath: KeyPath & Sendable, order: SortOrder = .forward) where Compared: NSObject { + self.init(keyPath as KeyPath, order: order) + } + + @_alwaysEmitIntoClient + public init(_ keyPath: KeyPath & Sendable, order: SortOrder = .forward) where Compared: NSObject { + self.init(keyPath as KeyPath, order: order) + } + + @_alwaysEmitIntoClient + public init(_ keyPath: KeyPath & Sendable, order: SortOrder = .forward) where Compared: NSObject { + self.init(keyPath as KeyPath, order: order) + } + + @_alwaysEmitIntoClient + public init(_ keyPath: KeyPath & Sendable, order: SortOrder = .forward) where Compared: NSObject { + self.init(keyPath as KeyPath, order: order) + } + + @_alwaysEmitIntoClient + public init(_ keyPath: KeyPath & Sendable, order: SortOrder = .forward) where Compared: NSObject { + self.init(keyPath as KeyPath, order: order) + } + + @_alwaysEmitIntoClient + public init(_ keyPath: KeyPath & Sendable, order: SortOrder = .forward) where Compared: NSObject { + self.init(keyPath as KeyPath, order: order) + } + + @_alwaysEmitIntoClient + public init(_ keyPath: KeyPath & Sendable, order: SortOrder = .forward) where Compared: NSObject { + self.init(keyPath as KeyPath, order: order) + } + + @_alwaysEmitIntoClient + public init(_ keyPath: KeyPath & Sendable, order: SortOrder = .forward) where Compared: NSObject { + self.init(keyPath as KeyPath, order: order) + } + + @_alwaysEmitIntoClient + public init(_ keyPath: KeyPath & Sendable, order: SortOrder = .forward) where Compared: NSObject { + self.init(keyPath as KeyPath, order: order) + } + + @_alwaysEmitIntoClient + public init(_ keyPath: KeyPath & Sendable, order: SortOrder = .forward) where Compared: NSObject { + self.init(keyPath as KeyPath, order: order) + } + + @_alwaysEmitIntoClient + public init(_ keyPath: KeyPath & Sendable, order: SortOrder = .forward) where Compared: NSObject { + self.init(keyPath as KeyPath, order: order) + } + + @_alwaysEmitIntoClient + public init(_ keyPath: KeyPath & Sendable, order: SortOrder = .forward) where Compared: NSObject { + self.init(keyPath as KeyPath, order: order) + } + + @_alwaysEmitIntoClient + public init(_ keyPath: KeyPath & Sendable, order: SortOrder = .forward) where Compared: NSObject { + self.init(keyPath as KeyPath, order: order) + } + + @_alwaysEmitIntoClient + public init(_ keyPath: KeyPath & Sendable, order: SortOrder = .forward) where Compared: NSObject { + self.init(keyPath as KeyPath, order: order) + } + + @_alwaysEmitIntoClient + public init(_ keyPath: KeyPath & Sendable, order: SortOrder = .forward) where Compared: NSObject { + self.init(keyPath as KeyPath, order: order) + } + + @_alwaysEmitIntoClient + public init(_ keyPath: KeyPath & Sendable, comparator: String.StandardComparator = .localizedStandard) where Compared: NSObject { + self.init(keyPath as KeyPath, comparator: comparator) + } + + @_alwaysEmitIntoClient + public init(_ keyPath: KeyPath & Sendable, comparator: String.StandardComparator = .localizedStandard) where Compared: NSObject { + self.init(keyPath as KeyPath, comparator: comparator) + } + + @_alwaysEmitIntoClient + public init(_ keyPath: KeyPath & Sendable, comparator: String.StandardComparator = .localizedStandard, order: SortOrder) where Compared: NSObject { + self.init(keyPath as KeyPath, comparator: comparator, order: order) + } + + @_alwaysEmitIntoClient + public init(_ keyPath: KeyPath & Sendable, comparator: String.StandardComparator = .localizedStandard, order: SortOrder) where Compared: NSObject { + self.init(keyPath as KeyPath, comparator: comparator, order: order) + } + /// Creates a `SortDescriptor` that orders values based on a `Value`'s /// `Comparable` implementation. @@ -244,12 +453,12 @@ public struct SortDescriptor: SortComparator, Codable, Sendable { /// - keyPath: The key path to the field to use for the comparison. /// - order: The initial order to use for comparison. @available(FoundationPreview 0.1, *) - public init(_ keyPath: KeyPath, order: SortOrder = .forward) where Value: Comparable { + /*public*/ @usableFromInline init(_ keyPath: KeyPath, order: SortOrder = .forward) where Value: Comparable { self.order = order self.keyString = nil self.comparison = .comparable( AnySortComparator(ComparableComparator(order: order)), - keyPath + keyPath._unsafeAssumeSendable ) } @@ -266,12 +475,12 @@ public struct SortDescriptor: SortComparator, Codable, Sendable { /// - keyPath: The key path to the field to use for the comparison. /// - order: The initial order to use for comparison. @available(FoundationPreview 0.1, *) - public init(_ keyPath: KeyPath, order: SortOrder = .forward) where Value: Comparable { + /*public*/ @usableFromInline init(_ keyPath: KeyPath, order: SortOrder = .forward) where Value: Comparable { self.order = order self.keyString = nil self.comparison = .comparable( AnySortComparator(OptionalComparator(ComparableComparator(order: order))), - keyPath + keyPath._unsafeAssumeSendable ) } @@ -295,10 +504,10 @@ public struct SortDescriptor: SortComparator, Codable, Sendable { /// - keyPath: The key path to the field to use for comparison. /// - comparator: The standard string comparator to use for comparison. @available(FoundationPreview 0.1, *) - public init(_ keyPath: KeyPath, comparator: String.StandardComparator = .localizedStandard) { + /*public*/ @usableFromInline init(_ keyPath: KeyPath, comparator: String.StandardComparator = .localizedStandard) { self.order = comparator.order self.keyString = nil - self.comparison = .comparableString(comparator, keyPath) + self.comparison = .comparableString(comparator, keyPath._unsafeAssumeSendable) } /// Creates a `SortDescriptor` that orders optional values using the given @@ -314,10 +523,10 @@ public struct SortDescriptor: SortComparator, Codable, Sendable { /// - keyPath: The key path to the field to use for comparison. /// - comparator: The standard string comparator to use for comparison. @available(FoundationPreview 0.1, *) - public init(_ keyPath: KeyPath, comparator: String.StandardComparator = .localizedStandard) { + /*public*/ @usableFromInline init(_ keyPath: KeyPath, comparator: String.StandardComparator = .localizedStandard) { self.order = comparator.order self.keyString = nil - self.comparison = .comparableOptionalString(comparator, keyPath) + self.comparison = .comparableOptionalString(comparator, keyPath._unsafeAssumeSendable) } /// Creates a `SortDescriptor` that orders optional values using the given @@ -334,12 +543,12 @@ public struct SortDescriptor: SortComparator, Codable, Sendable { /// - comparator: The standard string comparator to use for comparison. /// - order: The initial order to use for comparison. @available(FoundationPreview 0.1, *) - public init(_ keyPath: KeyPath, comparator: String.StandardComparator = .localizedStandard, order: SortOrder) { + /*public*/ @usableFromInline init(_ keyPath: KeyPath, comparator: String.StandardComparator = .localizedStandard, order: SortOrder) { self.order = order self.keyString = nil var comparator = comparator comparator.order = order - self.comparison = .comparableString(comparator, keyPath) + self.comparison = .comparableString(comparator, keyPath._unsafeAssumeSendable) } /// Creates a `SortDescriptor` that orders optional values using the given @@ -356,30 +565,30 @@ public struct SortDescriptor: SortComparator, Codable, Sendable { /// - comparator: The standard string comparator to use for comparison. /// - order: The initial order to use for comparison. @available(FoundationPreview 0.1, *) - public init(_ keyPath: KeyPath, comparator: String.StandardComparator = .localizedStandard, order: SortOrder) { + /*public*/ @usableFromInline init(_ keyPath: KeyPath, comparator: String.StandardComparator = .localizedStandard, order: SortOrder) { self.order = order self.keyString = nil var comparator = comparator comparator.order = order - self.comparison = .comparableOptionalString(comparator, keyPath) + self.comparison = .comparableOptionalString(comparator, keyPath._unsafeAssumeSendable) } #else /// Temporarily available as a replacement for `init(_:comparator:)` with a default argument. - public init(_ keyPath: KeyPath, comparator: String.StandardComparator) { + public init(_ keyPath: KeyPath & Sendable, comparator: String.StandardComparator) { self.order = comparator.order self.keyString = nil self.comparison = .comparableString(comparator, keyPath) } /// Temporarily available as a replacement for `init(_:comparator:)` with a default argument. - public init(_ keyPath: KeyPath, comparator: String.StandardComparator) { + public init(_ keyPath: KeyPath & Sendable, comparator: String.StandardComparator) { self.order = comparator.order self.keyString = nil self.comparison = .comparableOptionalString(comparator, keyPath) } /// Temporarily available as a replacement for `init(_:comparator:)` with a default argument. - public init(_ keyPath: KeyPath, comparator: String.StandardComparator, order: SortOrder) { + public init(_ keyPath: KeyPath & Sendable, comparator: String.StandardComparator, order: SortOrder) { self.order = order self.keyString = nil var comparator = comparator @@ -388,7 +597,7 @@ public struct SortDescriptor: SortComparator, Codable, Sendable { } /// Temporarily available as a replacement for `init(_:comparator:)` with a default argument. - public init(_ keyPath: KeyPath, comparator: String.StandardComparator, order: SortOrder) { + public init(_ keyPath: KeyPath & Sendable, comparator: String.StandardComparator, order: SortOrder) { self.order = order self.keyString = nil var comparator = comparator @@ -408,7 +617,7 @@ public struct SortDescriptor: SortComparator, Codable, Sendable { /// - Parameters: /// - keyPath: The key path to the field to use for the comparison. /// - order: The initial order to use for comparison. - public init(_ keyPath: KeyPath, order: SortOrder = .forward) where Compared: NSObject { + /*public*/ @usableFromInline init(_ keyPath: KeyPath, order: SortOrder = .forward) where Compared: NSObject { self.init(uncheckedCompareBasedKeyPath: keyPath, order: order) } @@ -421,7 +630,7 @@ public struct SortDescriptor: SortComparator, Codable, Sendable { /// - Parameters: /// - keyPath: The key path to the field to use for the comparison. /// - order: The initial order to use for comparison. - public init(_ keyPath: KeyPath, order: SortOrder = .forward) where Compared: NSObject { + /*public*/ @usableFromInline init(_ keyPath: KeyPath, order: SortOrder = .forward) where Compared: NSObject { self.init(uncheckedCompareBasedKeyPath: keyPath, order: order) } @@ -431,7 +640,7 @@ public struct SortDescriptor: SortComparator, Codable, Sendable { /// - Parameters: /// - keyPath: The key path to the field to use for the comparison. /// - order: The initial order to use for comparison. - public init(_ keyPath: KeyPath, order: SortOrder = .forward) where Compared: NSObject { + /*public*/ @usableFromInline init(_ keyPath: KeyPath, order: SortOrder = .forward) where Compared: NSObject { self.init(uncheckedCompareBasedKeyPath: keyPath, order: order) } @@ -444,7 +653,7 @@ public struct SortDescriptor: SortComparator, Codable, Sendable { /// - Parameters: /// - keyPath: The key path to the field to use for the comparison. /// - order: The initial order to use for comparison. - public init(_ keyPath: KeyPath, order: SortOrder = .forward) where Compared: NSObject { + /*public*/ @usableFromInline init(_ keyPath: KeyPath, order: SortOrder = .forward) where Compared: NSObject { self.init(uncheckedCompareBasedKeyPath: keyPath, order: order) } @@ -454,7 +663,7 @@ public struct SortDescriptor: SortComparator, Codable, Sendable { /// - Parameters: /// - keyPath: The key path to the field to use for the comparison. /// - order: The initial order to use for comparison. - public init(_ keyPath: KeyPath, order: SortOrder = .forward) where Compared: NSObject { + /*public*/ @usableFromInline init(_ keyPath: KeyPath, order: SortOrder = .forward) where Compared: NSObject { self.init(uncheckedCompareBasedKeyPath: keyPath, order: order) } @@ -467,7 +676,7 @@ public struct SortDescriptor: SortComparator, Codable, Sendable { /// - Parameters: /// - keyPath: The key path to the field to use for the comparison. /// - order: The initial order to use for comparison. - public init(_ keyPath: KeyPath, order: SortOrder = .forward) where Compared: NSObject { + /*public*/ @usableFromInline init(_ keyPath: KeyPath, order: SortOrder = .forward) where Compared: NSObject { self.init(uncheckedCompareBasedKeyPath: keyPath, order: order) } @@ -477,7 +686,7 @@ public struct SortDescriptor: SortComparator, Codable, Sendable { /// - Parameters: /// - keyPath: The key path to the field to use for the comparison. /// - order: The initial order to use for comparison. - public init(_ keyPath: KeyPath, order: SortOrder = .forward) where Compared: NSObject { + /*public*/ @usableFromInline init(_ keyPath: KeyPath, order: SortOrder = .forward) where Compared: NSObject { self.init(uncheckedCompareBasedKeyPath: keyPath, order: order) } @@ -490,7 +699,7 @@ public struct SortDescriptor: SortComparator, Codable, Sendable { /// - Parameters: /// - keyPath: The key path to the field to use for the comparison. /// - order: The initial order to use for comparison. - public init(_ keyPath: KeyPath, order: SortOrder = .forward) where Compared: NSObject { + /*public*/ @usableFromInline init(_ keyPath: KeyPath, order: SortOrder = .forward) where Compared: NSObject { self.init(uncheckedCompareBasedKeyPath: keyPath, order: order) } @@ -501,7 +710,7 @@ public struct SortDescriptor: SortComparator, Codable, Sendable { /// - Parameters: /// - keyPath: The key path to the field to use for the comparison. /// - order: The initial order to use for comparison. - public init(_ keyPath: KeyPath, order: SortOrder = .forward) where Compared: NSObject { + /*public*/ @usableFromInline init(_ keyPath: KeyPath, order: SortOrder = .forward) where Compared: NSObject { self.init(uncheckedCompareBasedKeyPath: keyPath, order: order) } @@ -514,7 +723,7 @@ public struct SortDescriptor: SortComparator, Codable, Sendable { /// - Parameters: /// - keyPath: The key path to the field to use for the comparison. /// - order: The initial order to use for comparison. - public init(_ keyPath: KeyPath, order: SortOrder = .forward) where Compared: NSObject { + /*public*/ @usableFromInline init(_ keyPath: KeyPath, order: SortOrder = .forward) where Compared: NSObject { self.init(uncheckedCompareBasedKeyPath: keyPath, order: order) } @@ -524,7 +733,7 @@ public struct SortDescriptor: SortComparator, Codable, Sendable { /// - Parameters: /// - keyPath: The key path to the field to use for the comparison. /// - order: The initial order to use for comparison. - public init(_ keyPath: KeyPath, order: SortOrder = .forward) where Compared: NSObject { + /*public*/ @usableFromInline init(_ keyPath: KeyPath, order: SortOrder = .forward) where Compared: NSObject { self.init(uncheckedCompareBasedKeyPath: keyPath, order: order) } @@ -537,7 +746,7 @@ public struct SortDescriptor: SortComparator, Codable, Sendable { /// - Parameters: /// - keyPath: The key path to the field to use for the comparison. /// - order: The initial order to use for comparison. - public init(_ keyPath: KeyPath, order: SortOrder = .forward) where Compared: NSObject { + /*public*/ @usableFromInline init(_ keyPath: KeyPath, order: SortOrder = .forward) where Compared: NSObject { self.init(uncheckedCompareBasedKeyPath: keyPath, order: order) } @@ -547,7 +756,7 @@ public struct SortDescriptor: SortComparator, Codable, Sendable { /// - Parameters: /// - keyPath: The key path to the field to use for the comparison. /// - order: The initial order to use for comparison. - public init(_ keyPath: KeyPath, order: SortOrder = .forward) where Compared: NSObject { + /*public*/ @usableFromInline init(_ keyPath: KeyPath, order: SortOrder = .forward) where Compared: NSObject { self.init(uncheckedCompareBasedKeyPath: keyPath, order: order) } @@ -560,7 +769,7 @@ public struct SortDescriptor: SortComparator, Codable, Sendable { /// - Parameters: /// - keyPath: The key path to the field to use for the comparison. /// - order: The initial order to use for comparison. - public init(_ keyPath: KeyPath, order: SortOrder = .forward) where Compared: NSObject { + /*public*/ @usableFromInline init(_ keyPath: KeyPath, order: SortOrder = .forward) where Compared: NSObject { self.init(uncheckedCompareBasedKeyPath: keyPath, order: order) } @@ -570,7 +779,7 @@ public struct SortDescriptor: SortComparator, Codable, Sendable { /// - Parameters: /// - keyPath: The key path to the field to use for the comparison. /// - order: The initial order to use for comparison. - public init(_ keyPath: KeyPath, order: SortOrder = .forward) where Compared: NSObject { + /*public*/ @usableFromInline init(_ keyPath: KeyPath, order: SortOrder = .forward) where Compared: NSObject { self.init(uncheckedCompareBasedKeyPath: keyPath, order: order) } @@ -583,7 +792,7 @@ public struct SortDescriptor: SortComparator, Codable, Sendable { /// - Parameters: /// - keyPath: The key path to the field to use for the comparison. /// - order: The initial order to use for comparison. - public init(_ keyPath: KeyPath, order: SortOrder = .forward) where Compared: NSObject { + /*public*/ @usableFromInline init(_ keyPath: KeyPath, order: SortOrder = .forward) where Compared: NSObject { self.init(uncheckedCompareBasedKeyPath: keyPath, order: order) } @@ -593,7 +802,7 @@ public struct SortDescriptor: SortComparator, Codable, Sendable { /// - Parameters: /// - keyPath: The key path to the field to use for the comparison. /// - order: The initial order to use for comparison. - public init(_ keyPath: KeyPath, order: SortOrder = .forward) where Compared: NSObject { + /*public*/ @usableFromInline init(_ keyPath: KeyPath, order: SortOrder = .forward) where Compared: NSObject { self.init(uncheckedCompareBasedKeyPath: keyPath, order: order) } @@ -606,7 +815,7 @@ public struct SortDescriptor: SortComparator, Codable, Sendable { /// - Parameters: /// - keyPath: The key path to the field to use for the comparison. /// - order: The initial order to use for comparison. - public init(_ keyPath: KeyPath, order: SortOrder = .forward) where Compared: NSObject { + /*public*/ @usableFromInline init(_ keyPath: KeyPath, order: SortOrder = .forward) where Compared: NSObject { self.init(uncheckedCompareBasedKeyPath: keyPath, order: order) } @@ -616,7 +825,7 @@ public struct SortDescriptor: SortComparator, Codable, Sendable { /// - Parameters: /// - keyPath: The key path to the field to use for the comparison. /// - order: The initial order to use for comparison. - public init(_ keyPath: KeyPath, order: SortOrder = .forward) where Compared: NSObject { + /*public*/ @usableFromInline init(_ keyPath: KeyPath, order: SortOrder = .forward) where Compared: NSObject { self.init(uncheckedCompareBasedKeyPath: keyPath, order: order) } @@ -629,7 +838,7 @@ public struct SortDescriptor: SortComparator, Codable, Sendable { /// - Parameters: /// - keyPath: The key path to the field to use for the comparison. /// - order: The initial order to use for comparison. - public init(_ keyPath: KeyPath, order: SortOrder = .forward) where Compared: NSObject { + /*public*/ @usableFromInline init(_ keyPath: KeyPath, order: SortOrder = .forward) where Compared: NSObject { self.init(uncheckedCompareBasedKeyPath: keyPath, order: order) } @@ -639,7 +848,7 @@ public struct SortDescriptor: SortComparator, Codable, Sendable { /// - Parameters: /// - keyPath: The key path to the field to use for the comparison. /// - order: The initial order to use for comparison. - public init(_ keyPath: KeyPath, order: SortOrder = .forward) where Compared: NSObject { + /*public*/ @usableFromInline init(_ keyPath: KeyPath, order: SortOrder = .forward) where Compared: NSObject { self.init(uncheckedCompareBasedKeyPath: keyPath, order: order) } @@ -652,7 +861,7 @@ public struct SortDescriptor: SortComparator, Codable, Sendable { /// - Parameters: /// - keyPath: The key path to the field to use for the comparison. /// - order: The initial order to use for comparison. - public init(_ keyPath: KeyPath, order: SortOrder = .forward) where Compared: NSObject { + /*public*/ @usableFromInline init(_ keyPath: KeyPath, order: SortOrder = .forward) where Compared: NSObject { self.init(uncheckedCompareBasedKeyPath: keyPath, order: order) } @@ -662,7 +871,7 @@ public struct SortDescriptor: SortComparator, Codable, Sendable { /// - Parameters: /// - keyPath: The key path to the field to use for the comparison. /// - order: The initial order to use for comparison. - public init(_ keyPath: KeyPath, order: SortOrder = .forward) where Compared: NSObject { + /*public*/ @usableFromInline init(_ keyPath: KeyPath, order: SortOrder = .forward) where Compared: NSObject { self.init(uncheckedCompareBasedKeyPath: keyPath, order: order) } @@ -675,7 +884,7 @@ public struct SortDescriptor: SortComparator, Codable, Sendable { /// - Parameters: /// - keyPath: The key path to the field to use for the comparison. /// - order: The initial order to use for comparison. - public init(_ keyPath: KeyPath, order: SortOrder = .forward) where Compared: NSObject { + /*public*/ @usableFromInline init(_ keyPath: KeyPath, order: SortOrder = .forward) where Compared: NSObject { self.init(uncheckedCompareBasedKeyPath: keyPath, order: order) } @@ -685,7 +894,7 @@ public struct SortDescriptor: SortComparator, Codable, Sendable { /// - Parameters: /// - keyPath: The key path to the field to use for the comparison. /// - order: The initial order to use for comparison. - public init(_ keyPath: KeyPath, order: SortOrder = .forward) where Compared: NSObject { + /*public*/ @usableFromInline init(_ keyPath: KeyPath, order: SortOrder = .forward) where Compared: NSObject { self.init(uncheckedCompareBasedKeyPath: keyPath, order: order) } @@ -698,7 +907,7 @@ public struct SortDescriptor: SortComparator, Codable, Sendable { /// - Parameters: /// - keyPath: The key path to the field to use for the comparison. /// - order: The initial order to use for comparison. - public init(_ keyPath: KeyPath, order: SortOrder = .forward) where Compared: NSObject { + /*public*/ @usableFromInline init(_ keyPath: KeyPath, order: SortOrder = .forward) where Compared: NSObject { self.init(uncheckedCompareBasedKeyPath: keyPath, order: order) } @@ -708,7 +917,7 @@ public struct SortDescriptor: SortComparator, Codable, Sendable { /// - Parameters: /// - keyPath: The key path to the field to use for the comparison. /// - order: The initial order to use for comparison. - public init(_ keyPath: KeyPath, order: SortOrder = .forward) where Compared: NSObject { + /*public*/ @usableFromInline init(_ keyPath: KeyPath, order: SortOrder = .forward) where Compared: NSObject { self.init(uncheckedCompareBasedKeyPath: keyPath, order: order) } @@ -721,7 +930,7 @@ public struct SortDescriptor: SortComparator, Codable, Sendable { /// - Parameters: /// - keyPath: The key path to the field to use for the comparison. /// - order: The initial order to use for comparison. - public init(_ keyPath: KeyPath, order: SortOrder = .forward) where Compared: NSObject { + /*public*/ @usableFromInline init(_ keyPath: KeyPath, order: SortOrder = .forward) where Compared: NSObject { self.init(uncheckedCompareBasedKeyPath: keyPath, order: order) } @@ -731,7 +940,7 @@ public struct SortDescriptor: SortComparator, Codable, Sendable { /// - Parameters: /// - keyPath: The key path to the field to use for the comparison. /// - order: The initial order to use for comparison. - public init(_ keyPath: KeyPath, order: SortOrder = .forward) where Compared: NSObject { + /*public*/ @usableFromInline init(_ keyPath: KeyPath, order: SortOrder = .forward) where Compared: NSObject { self.init(uncheckedCompareBasedKeyPath: keyPath, order: order) } @@ -744,7 +953,7 @@ public struct SortDescriptor: SortComparator, Codable, Sendable { /// - Parameters: /// - keyPath: The key path to the field to use for the comparison. /// - order: The initial order to use for comparison. - public init(_ keyPath: KeyPath, order: SortOrder = .forward) where Compared: NSObject { + /*public*/ @usableFromInline init(_ keyPath: KeyPath, order: SortOrder = .forward) where Compared: NSObject { self.init(uncheckedCompareBasedKeyPath: keyPath, order: order) } @@ -757,7 +966,7 @@ public struct SortDescriptor: SortComparator, Codable, Sendable { /// - Parameters: /// - keyPath: The key path to the field to use for comparison. /// - comparator: The standard string comparator to use for comparison. - public init(_ keyPath: KeyPath, comparator: String.StandardComparator = .localizedStandard) where Compared: NSObject { + /*public*/ @usableFromInline init(_ keyPath: KeyPath, comparator: String.StandardComparator = .localizedStandard) where Compared: NSObject { self.init( keyPath, comparator: comparator, @@ -777,7 +986,7 @@ public struct SortDescriptor: SortComparator, Codable, Sendable { /// - Parameters: /// - keyPath: The key path to the field to use for comparison. /// - comparator: The standard string comparator to use for comparison. - public init(_ keyPath: KeyPath, comparator: String.StandardComparator = .localizedStandard) where Compared: NSObject { + /*public*/ @usableFromInline init(_ keyPath: KeyPath, comparator: String.StandardComparator = .localizedStandard) where Compared: NSObject { self.init( keyPath, comparator: comparator, @@ -792,7 +1001,7 @@ public struct SortDescriptor: SortComparator, Codable, Sendable { /// - keyPath: The key path to the field to use for comparison. /// - comparator: The standard string comparator to use for comparison. /// - order: The initial order to use for comparison. - public init(_ keyPath: KeyPath, comparator: String.StandardComparator = .localizedStandard, order: SortOrder) where Compared: NSObject { + /*public*/ @usableFromInline init(_ keyPath: KeyPath, comparator: String.StandardComparator = .localizedStandard, order: SortOrder) where Compared: NSObject { guard let keyString = keyPath._kvcKeyPathString else { fatalError(""" \(String(describing: Compared.self)) must be introspectable by \ @@ -823,7 +1032,7 @@ public struct SortDescriptor: SortComparator, Codable, Sendable { /// - keyPath: The key path to the field to use for comparison. /// - comparator: The standard string comparator to use for comparison. /// - order: The initial order to use for comparison. - public init(_ keyPath: KeyPath, comparator: String.StandardComparator = .localizedStandard, order: SortOrder) where Compared: NSObject { + /*public*/ @usableFromInline init(_ keyPath: KeyPath, comparator: String.StandardComparator = .localizedStandard, order: SortOrder) where Compared: NSObject { guard let keyString = keyPath._kvcKeyPathString else { fatalError(""" \(String(describing: Compared.self)) must be introspectable by \ diff --git a/Tests/FoundationEssentialsTests/PredicateCodableTests.swift b/Tests/FoundationEssentialsTests/PredicateCodableTests.swift index ca0a375cc..9776c0485 100644 --- a/Tests/FoundationEssentialsTests/PredicateCodableTests.swift +++ b/Tests/FoundationEssentialsTests/PredicateCodableTests.swift @@ -70,7 +70,7 @@ final class PredicateCodableTests: XCTestCase { var g: [Int] var h: Object2 - static var predicateCodableKeyPaths: [String : PartialKeyPath] { + static var predicateCodableKeyPaths: [String : PartialKeyPath & Sendable] { [ "Object.f" : \.f, "Object.g" : \.g, @@ -85,7 +85,7 @@ final class PredicateCodableTests: XCTestCase { var a: Int var b: String - static var predicateCodableKeyPaths: [String : PartialKeyPath] { + static var predicateCodableKeyPaths: [String : PartialKeyPath & Sendable] { ["Object2.a" : \.a] } } From 2d7828cf2e891ef0b32c40b32aadda34ad6b4c94 Mon Sep 17 00:00:00 2001 From: Jeremy Schonfeld Date: Wed, 17 Jul 2024 08:40:57 -0700 Subject: [PATCH 2/2] (131556645) Fix build failures --- .../FoundationInternationalization/String/SortDescriptor.swift | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Sources/FoundationInternationalization/String/SortDescriptor.swift b/Sources/FoundationInternationalization/String/SortDescriptor.swift index 29280c880..6838c0863 100644 --- a/Sources/FoundationInternationalization/String/SortDescriptor.swift +++ b/Sources/FoundationInternationalization/String/SortDescriptor.swift @@ -248,6 +248,7 @@ public struct SortDescriptor: SortComparator, Codable, Sendable { self.init(keyPath as KeyPath, order: order) } + #if FOUNDATION_FRAMEWORK @_alwaysEmitIntoClient @available(FoundationPreview 0.1, *) public init(_ keyPath: KeyPath & Sendable, comparator: String.StandardComparator = .localizedStandard) { @@ -441,6 +442,7 @@ public struct SortDescriptor: SortComparator, Codable, Sendable { public init(_ keyPath: KeyPath & Sendable, comparator: String.StandardComparator = .localizedStandard, order: SortOrder) where Compared: NSObject { self.init(keyPath as KeyPath, comparator: comparator, order: order) } + #endif // FOUNDATION_FRAMEWORK /// Creates a `SortDescriptor` that orders values based on a `Value`'s