From 5e2361fb813571289739a54f128f6c62521d1678 Mon Sep 17 00:00:00 2001 From: Franz Busch Date: Thu, 27 Jul 2023 21:54:23 +0100 Subject: [PATCH] Fix more `Sendable` warnings and flaky test # Motivation We still had some `Sendable` warnings left under strict Concurrency checking. # Modification This PR fixes a bunch of `Sendable` warnings but we still have some left in the validation tests. Additionally, I fixed a flaky test. --- Package.swift | 25 +++++++-- Package@swift-5.7.swift | 51 +++++++++++++++++++ .../AsyncAlgorithms/Merge/MergeStorage.swift | 2 +- .../Interspersed/TestInterspersed.swift | 7 +-- .../Performance/ThroughputMeasurement.swift | 4 +- Tests/AsyncAlgorithmsTests/TestChunk.swift | 2 + 6 files changed, 77 insertions(+), 14 deletions(-) create mode 100644 Package@swift-5.7.swift diff --git a/Package.swift b/Package.swift index 56417e84..36c4e078 100644 --- a/Package.swift +++ b/Package.swift @@ -1,4 +1,4 @@ -// swift-tools-version: 5.6 +// swift-tools-version: 5.8 import PackageDescription @@ -20,18 +20,33 @@ let package = Package( targets: [ .target( name: "AsyncAlgorithms", - dependencies: [.product(name: "Collections", package: "swift-collections")] + dependencies: [.product(name: "Collections", package: "swift-collections")], + swiftSettings: [ + .enableExperimentalFeature("StrictConcurrency=complete"), + ] ), .target( name: "AsyncSequenceValidation", - dependencies: ["_CAsyncSequenceValidationSupport", "AsyncAlgorithms"]), + dependencies: ["_CAsyncSequenceValidationSupport", "AsyncAlgorithms"], + swiftSettings: [ + .enableExperimentalFeature("StrictConcurrency=complete"), + ] + ), .systemLibrary(name: "_CAsyncSequenceValidationSupport"), .target( name: "AsyncAlgorithms_XCTest", - dependencies: ["AsyncAlgorithms", "AsyncSequenceValidation"]), + dependencies: ["AsyncAlgorithms", "AsyncSequenceValidation"], + swiftSettings: [ + .enableExperimentalFeature("StrictConcurrency=complete"), + ] + ), .testTarget( name: "AsyncAlgorithmsTests", - dependencies: ["AsyncAlgorithms", "AsyncSequenceValidation", "AsyncAlgorithms_XCTest"]), + dependencies: ["AsyncAlgorithms", "AsyncSequenceValidation", "AsyncAlgorithms_XCTest"], + swiftSettings: [ + .enableExperimentalFeature("StrictConcurrency=complete"), + ] + ), ] ) diff --git a/Package@swift-5.7.swift b/Package@swift-5.7.swift new file mode 100644 index 00000000..56417e84 --- /dev/null +++ b/Package@swift-5.7.swift @@ -0,0 +1,51 @@ +// swift-tools-version: 5.6 + +import PackageDescription + +let package = Package( + name: "swift-async-algorithms", + platforms: [ + .macOS("10.15"), + .iOS("13.0"), + .tvOS("13.0"), + .watchOS("6.0") + ], + products: [ + .library(name: "AsyncAlgorithms", targets: ["AsyncAlgorithms"]), + .library(name: "AsyncSequenceValidation", targets: ["AsyncSequenceValidation"]), + .library(name: "_CAsyncSequenceValidationSupport", type: .static, targets: ["AsyncSequenceValidation"]), + .library(name: "AsyncAlgorithms_XCTest", targets: ["AsyncAlgorithms_XCTest"]), + ], + dependencies: [.package(url: "https://github.com/apple/swift-collections.git", .upToNextMajor(from: "1.0.4"))], + targets: [ + .target( + name: "AsyncAlgorithms", + dependencies: [.product(name: "Collections", package: "swift-collections")] + ), + .target( + name: "AsyncSequenceValidation", + dependencies: ["_CAsyncSequenceValidationSupport", "AsyncAlgorithms"]), + .systemLibrary(name: "_CAsyncSequenceValidationSupport"), + .target( + name: "AsyncAlgorithms_XCTest", + dependencies: ["AsyncAlgorithms", "AsyncSequenceValidation"]), + .testTarget( + name: "AsyncAlgorithmsTests", + dependencies: ["AsyncAlgorithms", "AsyncSequenceValidation", "AsyncAlgorithms_XCTest"]), + ] +) + +#if canImport(Darwin) +import Darwin +let buildingDocs = getenv("BUILDING_FOR_DOCUMENTATION_GENERATION") != nil +#elseif canImport(Glibc) +import Glibc +let buildingDocs = getenv("BUILDING_FOR_DOCUMENTATION_GENERATION") != nil +#else +let buildingDocs = false +#endif + +// Only require the docc plugin when building documentation +package.dependencies += buildingDocs ? [ + .package(url: "https://github.com/apple/swift-docc-plugin", from: "1.0.0"), +] : [] diff --git a/Sources/AsyncAlgorithms/Merge/MergeStorage.swift b/Sources/AsyncAlgorithms/Merge/MergeStorage.swift index 42712cae..9dedee76 100644 --- a/Sources/AsyncAlgorithms/Merge/MergeStorage.swift +++ b/Sources/AsyncAlgorithms/Merge/MergeStorage.swift @@ -198,7 +198,7 @@ final class MergeStorage< private func iterateAsyncSequence( _ base: AsyncSequence, in taskGroup: inout ThrowingTaskGroup - ) where AsyncSequence.Element == Base1.Element { + ) where AsyncSequence.Element == Base1.Element, AsyncSequence: Sendable { // For each upstream sequence we are adding a child task that // is consuming the upstream sequence taskGroup.addTask { diff --git a/Tests/AsyncAlgorithmsTests/Interspersed/TestInterspersed.swift b/Tests/AsyncAlgorithmsTests/Interspersed/TestInterspersed.swift index 6e09e84d..e51a4817 100644 --- a/Tests/AsyncAlgorithmsTests/Interspersed/TestInterspersed.swift +++ b/Tests/AsyncAlgorithmsTests/Interspersed/TestInterspersed.swift @@ -166,10 +166,6 @@ final class TestInterspersed: XCTestCase { while let _ = await iterator.next() {} - let pastEnd = await iterator.next() - XCTAssertNil(pastEnd) - - // Information the parent task that we finished consuming await lockStepChannel.send(()) } @@ -179,8 +175,7 @@ final class TestInterspersed: XCTestCase { // Now we cancel the child group.cancelAll() - // Waiting until the child task finished consuming - _ = await lockStepChannel.first { _ in true } + await group.waitForAll() } } } diff --git a/Tests/AsyncAlgorithmsTests/Performance/ThroughputMeasurement.swift b/Tests/AsyncAlgorithmsTests/Performance/ThroughputMeasurement.swift index c8991bdd..db223f3e 100644 --- a/Tests/AsyncAlgorithmsTests/Performance/ThroughputMeasurement.swift +++ b/Tests/AsyncAlgorithmsTests/Performance/ThroughputMeasurement.swift @@ -56,7 +56,7 @@ final class _ThroughputMetric: NSObject, XCTMetric, @unchecked Sendable { } extension XCTestCase { - public func measureChannelThroughput(output: @escaping @autoclosure () -> Output) async { + public func measureChannelThroughput(output: @Sendable @escaping @autoclosure () -> Output) async { let metric = _ThroughputMetric() let sampleTime: Double = 0.1 @@ -85,7 +85,7 @@ extension XCTestCase { } } - public func measureThrowingChannelThroughput(output: @escaping @autoclosure () -> Output) async { + public func measureThrowingChannelThroughput(output: @Sendable @escaping @autoclosure () -> Output) async { let metric = _ThroughputMetric() let sampleTime: Double = 0.1 diff --git a/Tests/AsyncAlgorithmsTests/TestChunk.swift b/Tests/AsyncAlgorithmsTests/TestChunk.swift index 4970cdc0..eee61247 100644 --- a/Tests/AsyncAlgorithmsTests/TestChunk.swift +++ b/Tests/AsyncAlgorithmsTests/TestChunk.swift @@ -13,10 +13,12 @@ import XCTest import AsyncSequenceValidation import AsyncAlgorithms +@Sendable func sumCharacters(_ array: [String]) -> String { return "\(array.reduce(into: 0) { $0 = $0 + Int($1)! })" } +@Sendable func concatCharacters(_ array: [String]) -> String { return array.joined() }