From f9f3e3a4cb9eaa44c221a9a8054bd961e343d979 Mon Sep 17 00:00:00 2001 From: Stephen Celis Date: Tue, 8 Oct 2024 13:08:38 -0700 Subject: [PATCH] Use `AnyHashableSendable` from Concurrency Extras (#3428) * Use `AnyHashableSendable` from Concurrency Extras Rather than use an ad hoc implementation with an `AnyHashable` under the hood that may not be concurrency safe, let's adopt the helper we added to the Concurrency Extras packages. * fix * wip * wip --- .../xcshareddata/swiftpm/Package.resolved | 4 ++-- .../xcshareddata/swiftpm/Package.resolved | 6 +++--- .../SwiftUICaseStudies/03-Effects-LongLiving.swift | 12 +++++------- .../CaseStudies/SwiftUICaseStudies/FactClient.swift | 7 ------- Package.swift | 2 +- Package@swift-6.0.swift | 2 +- Sources/ComposableArchitecture/Effect.swift | 4 ++-- .../Internal/NavigationID.swift | 7 ------- .../FileStorageTests.swift | 4 ++-- 9 files changed, 16 insertions(+), 32 deletions(-) diff --git a/.github/package.xcworkspace/xcshareddata/swiftpm/Package.resolved b/.github/package.xcworkspace/xcshareddata/swiftpm/Package.resolved index efb86cba4a2e..1b27355aecfd 100644 --- a/.github/package.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/.github/package.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -59,8 +59,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/pointfreeco/swift-concurrency-extras", "state" : { - "revision" : "bb5059bde9022d69ac516803f4f227d8ac967f71", - "version" : "1.1.0" + "revision" : "6054df64b55186f08b6d0fd87152081b8ad8d613", + "version" : "1.2.0" } }, { diff --git a/ComposableArchitecture.xcworkspace/xcshareddata/swiftpm/Package.resolved b/ComposableArchitecture.xcworkspace/xcshareddata/swiftpm/Package.resolved index 803d119f856b..21dcd6eceb2b 100644 --- a/ComposableArchitecture.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/ComposableArchitecture.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -1,5 +1,5 @@ { - "originHash" : "9b77567b796b05ea9be9bbcac20aca003b91f34244a7fd2740f2b5306c013c45", + "originHash" : "876e72a5524942f6ac9fd0ebc53b055352a228c6f751c04f66249c1eeefd2cbc", "pins" : [ { "identity" : "combine-schedulers", @@ -42,8 +42,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/pointfreeco/swift-concurrency-extras", "state" : { - "revision" : "bb5059bde9022d69ac516803f4f227d8ac967f71", - "version" : "1.1.0" + "revision" : "6054df64b55186f08b6d0fd87152081b8ad8d613", + "version" : "1.2.0" } }, { diff --git a/Examples/CaseStudies/SwiftUICaseStudies/03-Effects-LongLiving.swift b/Examples/CaseStudies/SwiftUICaseStudies/03-Effects-LongLiving.swift index c83a6e24d016..895197492149 100644 --- a/Examples/CaseStudies/SwiftUICaseStudies/03-Effects-LongLiving.swift +++ b/Examples/CaseStudies/SwiftUICaseStudies/03-Effects-LongLiving.swift @@ -48,19 +48,17 @@ struct LongLivingEffects { } extension DependencyValues { - var screenshots: @Sendable () async -> AsyncStream { + var screenshots: @Sendable () async -> any AsyncSequence { get { self[ScreenshotsKey.self] } set { self[ScreenshotsKey.self] = newValue } } } private enum ScreenshotsKey: DependencyKey { - static let liveValue: @Sendable () async -> AsyncStream = { - AsyncStream( - NotificationCenter.default - .notifications(named: UIApplication.userDidTakeScreenshotNotification) - .map { _ in } - ) + static let liveValue: @Sendable () async -> any AsyncSequence = { + NotificationCenter.default + .notifications(named: UIApplication.userDidTakeScreenshotNotification) + .map { _ in } } } diff --git a/Examples/CaseStudies/SwiftUICaseStudies/FactClient.swift b/Examples/CaseStudies/SwiftUICaseStudies/FactClient.swift index 0059c857c0ba..d54f68846b60 100644 --- a/Examples/CaseStudies/SwiftUICaseStudies/FactClient.swift +++ b/Examples/CaseStudies/SwiftUICaseStudies/FactClient.swift @@ -30,10 +30,3 @@ extension FactClient: DependencyKey { /// to prove do not need the dependency. static let testValue = Self() } - -struct AnyHashableSendable: Hashable, @unchecked Sendable { - let base: AnyHashable - init(_ base: Base) { - self.base = base - } -} diff --git a/Package.swift b/Package.swift index cd5c14c359cc..7fc45df39623 100644 --- a/Package.swift +++ b/Package.swift @@ -21,7 +21,7 @@ let package = Package( .package(url: "https://github.com/apple/swift-collections", from: "1.1.0"), .package(url: "https://github.com/pointfreeco/combine-schedulers", from: "1.0.2"), .package(url: "https://github.com/pointfreeco/swift-case-paths", from: "1.5.4"), - .package(url: "https://github.com/pointfreeco/swift-concurrency-extras", from: "1.1.0"), + .package(url: "https://github.com/pointfreeco/swift-concurrency-extras", from: "1.2.0"), .package(url: "https://github.com/pointfreeco/swift-custom-dump", from: "1.3.2"), .package(url: "https://github.com/pointfreeco/swift-dependencies", from: "1.4.0"), .package(url: "https://github.com/pointfreeco/swift-identified-collections", from: "1.1.0"), diff --git a/Package@swift-6.0.swift b/Package@swift-6.0.swift index d85340b73292..b06fd823b18c 100644 --- a/Package@swift-6.0.swift +++ b/Package@swift-6.0.swift @@ -21,7 +21,7 @@ let package = Package( .package(url: "https://github.com/apple/swift-collections", from: "1.1.0"), .package(url: "https://github.com/pointfreeco/combine-schedulers", from: "1.0.2"), .package(url: "https://github.com/pointfreeco/swift-case-paths", from: "1.5.4"), - .package(url: "https://github.com/pointfreeco/swift-concurrency-extras", from: "1.1.0"), + .package(url: "https://github.com/pointfreeco/swift-concurrency-extras", from: "1.2.0"), .package(url: "https://github.com/pointfreeco/swift-custom-dump", from: "1.3.2"), .package(url: "https://github.com/pointfreeco/swift-dependencies", from: "1.4.0"), .package(url: "https://github.com/pointfreeco/swift-identified-collections", from: "1.1.0"), diff --git a/Sources/ComposableArchitecture/Effect.swift b/Sources/ComposableArchitecture/Effect.swift index 4c5669705faf..2afaf5b526f1 100644 --- a/Sources/ComposableArchitecture/Effect.swift +++ b/Sources/ComposableArchitecture/Effect.swift @@ -46,11 +46,11 @@ extension Effect { /// Wraps an asynchronous unit of work that can emit actions any number of times in an effect. /// - /// For example, if you had an async stream in a dependency client: + /// For example, if you had an async sequence in a dependency client: /// /// ```swift /// struct EventsClient { - /// var events: () -> AsyncStream + /// var events: () -> any AsyncSequence /// } /// ``` /// diff --git a/Sources/ComposableArchitecture/Internal/NavigationID.swift b/Sources/ComposableArchitecture/Internal/NavigationID.swift index 52d7a3d21ac8..484493562f93 100644 --- a/Sources/ComposableArchitecture/Internal/NavigationID.swift +++ b/Sources/ComposableArchitecture/Internal/NavigationID.swift @@ -123,10 +123,3 @@ struct NavigationID: Hashable, @unchecked Sendable { hasher.combine(self.tag) } } - -@_spi(Internals) public struct AnyHashableSendable: Hashable, @unchecked Sendable { - @_spi(Internals) public let base: AnyHashable - init(_ base: Base) { - self.base = base - } -} diff --git a/Tests/ComposableArchitectureTests/FileStorageTests.swift b/Tests/ComposableArchitectureTests/FileStorageTests.swift index 9eca3a9edf2a..28990729ed05 100644 --- a/Tests/ComposableArchitectureTests/FileStorageTests.swift +++ b/Tests/ComposableArchitectureTests/FileStorageTests.swift @@ -409,8 +409,8 @@ final class FileStorageTests: XCTestCase { await Task.yield() expectNoDifference(users, [.blob]) - $users.withLock { $0 = [.blobJr] } // NB: Saved immediately - $users.withLock { $0 = [.blobSr] } // NB: Throttled for 1 second + await $users.withLock { $0 = [.blobJr] } // NB: Saved immediately + await $users.withLock { $0 = [.blobSr] } // NB: Throttled for 1 second try FileManager.default.removeItem(at: .fileURL) try await Task.sleep(nanoseconds: 1_200_000_000) expectNoDifference(users, [.blob])