From 5901e467d2117235e2550a1d8f324ff6d6b98374 Mon Sep 17 00:00:00 2001 From: x_0o0 Date: Tue, 12 Dec 2023 07:57:44 +0900 Subject: [PATCH] [VER] Bump up Swift compiler version to 5.7.1 to follow Apple's policy (#140) * [VER] Bump up Swift compiler version to 5.7.1 * [MOD] Modified swiftwasm version to use over 5.7.0 package --- .github/workflows/ci.yml | 2 +- Package.swift | 2 +- Sources/Dependencies/DependencyKey.swift | 8 +- .../DependencyValues/Clocks.swift | 2 +- .../Internal/OpenExistential.swift | 30 +- Sources/Dependencies/WithDependencies.swift | 275 +++++++----------- .../WithValue.swift | 64 ++-- 7 files changed, 138 insertions(+), 245 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b3da653f..65ad8c68 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -62,7 +62,7 @@ jobs: steps: - uses: actions/checkout@v3 - run: echo "${{ matrix.toolchain }}" > .swift-version - - uses: swiftwasm/swiftwasm-action@v5.7 + - uses: swiftwasm/swiftwasm-action@v5.8 with: shell-action: carton test --environment node diff --git a/Package.swift b/Package.swift index bc229bcb..344fd396 100644 --- a/Package.swift +++ b/Package.swift @@ -1,4 +1,4 @@ -// swift-tools-version: 5.6 +// swift-tools-version: 5.7.1 import PackageDescription diff --git a/Sources/Dependencies/DependencyKey.swift b/Sources/Dependencies/DependencyKey.swift index 8966a1e6..417b939d 100644 --- a/Sources/Dependencies/DependencyKey.swift +++ b/Sources/Dependencies/DependencyKey.swift @@ -120,13 +120,7 @@ public protocol DependencyKey: TestDependencyKey { /// See ``DependencyKey`` to define a static, default value for the live application. public protocol TestDependencyKey { /// The associated type representing the type of the dependency key's value. - #if swift(>=5.7.1) - associatedtype Value: Sendable = Self - #else - // NB: Can't constrain to `Sendable` on earlier Swift versions due to this bug: - // https://github.com/apple/swift/issues/60649 - associatedtype Value = Self - #endif + associatedtype Value: Sendable = Self /// The preview value for the dependency key. /// diff --git a/Sources/Dependencies/DependencyValues/Clocks.swift b/Sources/Dependencies/DependencyValues/Clocks.swift index afed1ab9..a6bc0547 100644 --- a/Sources/Dependencies/DependencyValues/Clocks.swift +++ b/Sources/Dependencies/DependencyValues/Clocks.swift @@ -1,4 +1,4 @@ -#if swift(>=5.7) && (canImport(RegexBuilder) || !os(macOS) && !targetEnvironment(macCatalyst)) +#if (canImport(RegexBuilder) || !os(macOS) && !targetEnvironment(macCatalyst)) @available(iOS 16, macOS 13, tvOS 16, watchOS 9, *) extension DependencyValues { /// The current clock that features should use when a `ContinuousClock` would be appropriate. diff --git a/Sources/Dependencies/Internal/OpenExistential.swift b/Sources/Dependencies/Internal/OpenExistential.swift index 2d290d09..dd2ee441 100644 --- a/Sources/Dependencies/Internal/OpenExistential.swift +++ b/Sources/Dependencies/Internal/OpenExistential.swift @@ -1,27 +1,3 @@ -#if swift(>=5.7) - // MARK: swift(>=5.7) - - func _liveValue(_ key: Any.Type) -> Any? { - (key as? any DependencyKey.Type)?.liveValue - } -#else - // MARK: - - // MARK: swift(<5.7) - - private enum Witness {} - - func _liveValue(_ key: Any.Type) -> Any? { - func open(_: T.Type) -> Any? { - (Witness.self as? AnyDependencyKey.Type)?.liveValue - } - return _openExistential(key, do: open) - } - - protocol AnyDependencyKey { - static var liveValue: Any { get } - } - - extension Witness: AnyDependencyKey where T: DependencyKey { - static var liveValue: Any { T.liveValue } - } -#endif +func _liveValue(_ key: Any.Type) -> Any? { + (key as? any DependencyKey.Type)?.liveValue +} diff --git a/Sources/Dependencies/WithDependencies.swift b/Sources/Dependencies/WithDependencies.swift index 4d766e85..9746ed5e 100644 --- a/Sources/Dependencies/WithDependencies.swift +++ b/Sources/Dependencies/WithDependencies.swift @@ -39,67 +39,45 @@ public func withDependencies( } } -#if swift(>=5.7) - /// Updates the current dependencies for the duration of an asynchronous operation. - /// - /// Any mutations made to ``DependencyValues`` inside `updateValuesForOperation` will be visible - /// to everything executed in the operation. For example, if you wanted to force the - /// ``DependencyValues/date`` dependency to be a particular date, you can do: - /// - /// ```swift - /// await withDependencies { - /// $0.date.now = Date(timeIntervalSince1970: 1234567890) - /// } operation: { - /// // References to date in here are pinned to 1234567890. - /// } - /// ``` - /// - /// - Parameters: - /// - updateValuesForOperation: A closure for updating the current dependency values for the - /// duration of the operation. - /// - operation: An operation to perform wherein dependencies have been overridden. - /// - Returns: The result returned from `operation`. - @_unsafeInheritExecutor - @discardableResult - public func withDependencies( - _ updateValuesForOperation: (inout DependencyValues) async throws -> Void, - operation: () async throws -> R - ) async rethrows -> R { - try await isSetting(true) { - var dependencies = DependencyValues._current - try await updateValuesForOperation(&dependencies) - return try await DependencyValues.$_current.withValue(dependencies) { - try await isSetting(false) { - let result = try await operation() - if R.self is AnyClass { - dependencyObjects.store(result as AnyObject) - } - return result - } - } - } - } -#else - @discardableResult - public func withDependencies( - _ updateValuesForOperation: (inout DependencyValues) async throws -> Void, - operation: () async throws -> R - ) async rethrows -> R { - try await isSetting(true) { - var dependencies = DependencyValues._current - try await updateValuesForOperation(&dependencies) - return try await DependencyValues.$_current.withValue(dependencies) { - try await isSetting(false) { - let result = try await operation() - if R.self is AnyClass { - dependencyObjects.store(result as AnyObject) - } - return result +/// Updates the current dependencies for the duration of an asynchronous operation. +/// +/// Any mutations made to ``DependencyValues`` inside `updateValuesForOperation` will be visible +/// to everything executed in the operation. For example, if you wanted to force the +/// ``DependencyValues/date`` dependency to be a particular date, you can do: +/// +/// ```swift +/// await withDependencies { +/// $0.date.now = Date(timeIntervalSince1970: 1234567890) +/// } operation: { +/// // References to date in here are pinned to 1234567890. +/// } +/// ``` +/// +/// - Parameters: +/// - updateValuesForOperation: A closure for updating the current dependency values for the +/// duration of the operation. +/// - operation: An operation to perform wherein dependencies have been overridden. +/// - Returns: The result returned from `operation`. +@_unsafeInheritExecutor +@discardableResult +public func withDependencies( + _ updateValuesForOperation: (inout DependencyValues) async throws -> Void, + operation: () async throws -> R +) async rethrows -> R { + try await isSetting(true) { + var dependencies = DependencyValues._current + try await updateValuesForOperation(&dependencies) + return try await DependencyValues.$_current.withValue(dependencies) { + try await isSetting(false) { + let result = try await operation() + if R.self is AnyClass { + dependencyObjects.store(result as AnyObject) } + return result } } } -#endif +} /// Updates the current dependencies for the duration of a synchronous operation by taking the /// dependencies tied to a given object. @@ -168,129 +146,76 @@ public func withDependencies( ) } -#if swift(>=5.7) - /// Updates the current dependencies for the duration of an asynchronous operation by taking the - /// dependencies tied to a given object. - /// - /// - Parameters: - /// - model: An object with dependencies. The given model should have at least one `@Dependency` - /// property, or should have been initialized and returned from a `withDependencies` - /// operation. - /// - updateValuesForOperation: A closure for updating the current dependency values for the - /// duration of the operation. - /// - operation: The operation to run with the updated dependencies. - /// - Returns: The result returned from `operation`. - @_unsafeInheritExecutor - @discardableResult - public func withDependencies( - from model: Model, - _ updateValuesForOperation: (inout DependencyValues) async throws -> Void, - operation: () async throws -> R, - file: StaticString? = nil, - line: UInt? = nil - ) async rethrows -> R { - guard let values = dependencyObjects.values(from: model) - else { - runtimeWarn( - """ - You are trying to propagate dependencies to a child model from a model with no \ - dependencies. To fix this, the given '\(Model.self)' must be returned from another \ - 'withDependencies' closure, or the class must hold at least one '@Dependency' property. - """, - file: file, - line: line - ) - return try await operation() - } - return try await withDependencies { - $0 = values.merging(DependencyValues._current) - try await updateValuesForOperation(&$0) - } operation: { - let result = try await operation() - if R.self is AnyClass { - dependencyObjects.store(result as AnyObject) - } - return result - } - } -#else - @discardableResult - public func withDependencies( - from model: Model, - _ updateValuesForOperation: (inout DependencyValues) async throws -> Void, - operation: () async throws -> R, - file: StaticString? = nil, - line: UInt? = nil - ) async rethrows -> R { - guard let values = dependencyObjects.values(from: model) - else { - runtimeWarn( - """ - You are trying to propagate dependencies to a child model from a model with no \ - dependencies. To fix this, the given '\(Model.self)' must be returned from another \ - 'withDependencies' closure, or the class must hold at least one '@Dependency' property. - """, - file: file, - line: line - ) - return try await operation() - } - return try await withDependencies { - $0 = values.merging(DependencyValues._current) - try await updateValuesForOperation(&$0) - } operation: { - let result = try await operation() - if R.self is AnyClass { - dependencyObjects.store(result as AnyObject) - } - return result - } - } -#endif - -#if swift(>=5.7) - /// Updates the current dependencies for the duration of an asynchronous operation by taking the - /// dependencies tied to a given object. - /// - /// - Parameters: - /// - model: An object with dependencies. The given model should have at least one `@Dependency` - /// property, or should have been initialized and returned from a `withDependencies` - /// operation. - /// - operation: The operation to run with the updated dependencies. - /// - Returns: The result returned from `operation`. - @_unsafeInheritExecutor - @discardableResult - public func withDependencies( - from model: Model, - operation: () async throws -> R, - file: StaticString? = nil, - line: UInt? = nil - ) async rethrows -> R { - try await withDependencies( - from: model, - { _ in }, - operation: operation, +/// Updates the current dependencies for the duration of an asynchronous operation by taking the +/// dependencies tied to a given object. +/// +/// - Parameters: +/// - model: An object with dependencies. The given model should have at least one `@Dependency` +/// property, or should have been initialized and returned from a `withDependencies` +/// operation. +/// - updateValuesForOperation: A closure for updating the current dependency values for the +/// duration of the operation. +/// - operation: The operation to run with the updated dependencies. +/// - Returns: The result returned from `operation`. +@_unsafeInheritExecutor +@discardableResult +public func withDependencies( + from model: Model, + _ updateValuesForOperation: (inout DependencyValues) async throws -> Void, + operation: () async throws -> R, + file: StaticString? = nil, + line: UInt? = nil +) async rethrows -> R { + guard let values = dependencyObjects.values(from: model) + else { + runtimeWarn( + """ + You are trying to propagate dependencies to a child model from a model with no \ + dependencies. To fix this, the given '\(Model.self)' must be returned from another \ + 'withDependencies' closure, or the class must hold at least one '@Dependency' property. + """, file: file, line: line ) + return try await operation() } -#else - @discardableResult - public func withDependencies( - from model: Model, - operation: () async throws -> R, - file: StaticString? = nil, - line: UInt? = nil - ) async rethrows -> R { - try await withDependencies( - from: model, - { _ in }, - operation: operation, - file: file, - line: line - ) + return try await withDependencies { + $0 = values.merging(DependencyValues._current) + try await updateValuesForOperation(&$0) + } operation: { + let result = try await operation() + if R.self is AnyClass { + dependencyObjects.store(result as AnyObject) + } + return result } -#endif +} + +/// Updates the current dependencies for the duration of an asynchronous operation by taking the +/// dependencies tied to a given object. +/// +/// - Parameters: +/// - model: An object with dependencies. The given model should have at least one `@Dependency` +/// property, or should have been initialized and returned from a `withDependencies` +/// operation. +/// - operation: The operation to run with the updated dependencies. +/// - Returns: The result returned from `operation`. +@_unsafeInheritExecutor +@discardableResult +public func withDependencies( + from model: Model, + operation: () async throws -> R, + file: StaticString? = nil, + line: UInt? = nil +) async rethrows -> R { + try await withDependencies( + from: model, + { _ in }, + operation: operation, + file: file, + line: line + ) +} /// Propagates the current dependencies to an escaping context. /// diff --git a/Sources/swift-dependencies-benchmark/WithValue.swift b/Sources/swift-dependencies-benchmark/WithValue.swift index 980baffb..5056a376 100644 --- a/Sources/swift-dependencies-benchmark/WithValue.swift +++ b/Sources/swift-dependencies-benchmark/WithValue.swift @@ -3,57 +3,55 @@ import Dependencies import Foundation let withValueSuite = BenchmarkSuite(name: "Dependencies") { suite in - #if swift(>=5.7) - _ = DependencyValues._current.date.now - _ = DependencyValues._current.calendar - _ = DependencyValues._current.context - _ = DependencyValues._current.locale - _ = DependencyValues._current.timeZone - _ = DependencyValues._current.urlSession - _ = DependencyValues._current.uuid - _ = DependencyValues._current.withRandomNumberGenerator - @Dependency(\.someValue) var someValue: Int + _ = DependencyValues._current.date.now + _ = DependencyValues._current.calendar + _ = DependencyValues._current.context + _ = DependencyValues._current.locale + _ = DependencyValues._current.timeZone + _ = DependencyValues._current.urlSession + _ = DependencyValues._current.uuid + _ = DependencyValues._current.withRandomNumberGenerator + @Dependency(\.someValue) var someValue: Int - suite.benchmark("Dependency key writing") { - let value = withDependencies { - $0.someValue = 1 + suite.benchmark("Dependency key writing") { + let value = withDependencies { + $0.someValue = 1 + } operation: { + withDependencies { + $0.someValue = 2 } operation: { withDependencies { - $0.someValue = 2 + $0.someValue = 3 } operation: { withDependencies { - $0.someValue = 3 + $0.someValue = 4 } operation: { withDependencies { - $0.someValue = 4 + $0.someValue = 5 } operation: { withDependencies { - $0.someValue = 5 + $0.someValue = 6 } operation: { withDependencies { - $0.someValue = 6 + $0.someValue = 7 } operation: { withDependencies { - $0.someValue = 7 + $0.someValue = 8 } operation: { withDependencies { - $0.someValue = 8 + $0.someValue = 9 } operation: { withDependencies { - $0.someValue = 9 + $0.someValue = 10 } operation: { withDependencies { - $0.someValue = 10 + $0.date = .constant(Date()) + $0.calendar = Calendar(identifier: .gregorian) + $0.context = .live + $0.locale = Locale(identifier: "en_US") + $0.uuid = .incrementing } operation: { - withDependencies { - $0.date = .constant(Date()) - $0.calendar = Calendar(identifier: .gregorian) - $0.context = .live - $0.locale = Locale(identifier: "en_US") - $0.uuid = .incrementing - } operation: { - someValue - } + someValue } } } @@ -64,9 +62,9 @@ let withValueSuite = BenchmarkSuite(name: "Dependencies") { suite in } } } - precondition(value == 10) } - #endif + precondition(value == 10) + } } private enum SomeValueKey: DependencyKey {