Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Address @Shared sendability. #3329

Merged
merged 16 commits into from
Sep 6, 2024
51 changes: 26 additions & 25 deletions .github/package.xcworkspace/xcshareddata/swiftpm/Package.resolved
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{
"originHash" : "a84dfeef15185f26bd546eb430da9b0b1f23f5a08c6ac0f99b345a8de1564068",
"pins" : [
{
"identity" : "combine-schedulers",
Expand Down Expand Up @@ -32,26 +33,26 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/pointfreeco/swift-case-paths",
"state" : {
"revision" : "71344dd930fde41e8f3adafe260adcbb2fc2a3dc",
"version" : "1.5.4"
"revision" : "642e6aab8e03e5f992d9c83e38c5be98cfad5078",
"version" : "1.5.5"
}
},
{
"identity" : "swift-clocks",
"kind" : "remoteSourceControl",
"location" : "https://github.com/pointfreeco/swift-clocks",
"state" : {
"revision" : "3581e280bf0d90c3fb9236fb23e75a5d8c46b533",
"version" : "1.0.4"
"revision" : "b9b24b69e2adda099a1fa381cda1eeec272d5b53",
"version" : "1.0.5"
}
},
{
"identity" : "swift-collections",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-collections",
"state" : {
"revision" : "3d2dc41a01f9e49d84f0a3925fb858bed64f702d",
"version" : "1.1.2"
"revision" : "9bf03ff58ce34478e66aaee630e491823326fd06",
"version" : "1.1.3"
}
},
{
Expand All @@ -77,23 +78,23 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/pointfreeco/swift-dependencies",
"state" : {
"revision" : "d7472be6b3c89251ce4c0db07d32405b43426781",
"version" : "1.3.7"
"revision" : "3ef38bb702a1a2f39c7e19fc0578403b8ee52b17",
"version" : "1.3.9"
}
},
{
"identity" : "swift-docc-plugin",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-docc-plugin",
"location" : "https://github.com/swiftlang/swift-docc-plugin",
"state" : {
"revision" : "26ac5758409154cc448d7ab82389c520fa8a8247",
"version" : "1.3.0"
"revision" : "2eb22993b3dfd0c0d32729b357c8dabb6cd44680",
"version" : "1.4.2"
}
},
{
"identity" : "swift-docc-symbolkit",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-docc-symbolkit",
"location" : "https://github.com/swiftlang/swift-docc-symbolkit",
"state" : {
"revision" : "b45d1f2ed151d057b54504d653e0da5552844e34",
"version" : "1.0.0"
Expand All @@ -113,55 +114,55 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/pointfreeco/swift-macro-testing",
"state" : {
"revision" : "a35257b7e9ce44e92636447003a8eeefb77b145c",
"version" : "0.5.1"
"revision" : "20c1a8f3b624fb5d1503eadcaa84743050c350f4",
"version" : "0.5.2"
}
},
{
"identity" : "swift-navigation",
"kind" : "remoteSourceControl",
"location" : "https://github.com/pointfreeco/swift-navigation",
"state" : {
"revision" : "47cfd149ed01223d14fc8e3f52ae27d3a35fe036",
"version" : "2.0.3"
"revision" : "e834b3760731160d7d448509ee6a1408c8582a6b",
"version" : "2.2.0"
}
},
{
"identity" : "swift-perception",
"kind" : "remoteSourceControl",
"location" : "https://github.com/pointfreeco/swift-perception",
"state" : {
"revision" : "1552c8f722ac256cc0b8daaf1a7073217d4fcdfb",
"version" : "1.3.4"
"revision" : "bc67aa8e461351c97282c2419153757a446ae1c9",
"version" : "1.3.5"
}
},
{
"identity" : "swift-snapshot-testing",
"kind" : "remoteSourceControl",
"location" : "https://github.com/pointfreeco/swift-snapshot-testing",
"state" : {
"revision" : "c097f955b4e724690f0fc8ffb7a6d4b881c9c4e3",
"version" : "1.17.2"
"revision" : "6d932a79e7173b275b96c600c86c603cf84f153c",
"version" : "1.17.4"
}
},
{
"identity" : "swift-syntax",
"kind" : "remoteSourceControl",
"location" : "https://github.com/swiftlang/swift-syntax",
"state" : {
"revision" : "4c6cc0a3b9e8f14b3ae2307c5ccae4de6167ac2c",
"version" : "600.0.0-prerelease-2024-06-12"
"revision" : "515f79b522918f83483068d99c68daeb5116342d",
"version" : "600.0.0-prerelease-2024-09-04"
}
},
{
"identity" : "xctest-dynamic-overlay",
"kind" : "remoteSourceControl",
"location" : "https://github.com/pointfreeco/xctest-dynamic-overlay",
"state" : {
"revision" : "357ca1e5dd31f613a1d43320870ebc219386a495",
"version" : "1.2.2"
"revision" : "96beb108a57f24c8476ae1f309239270772b2940",
"version" : "1.2.5"
}
}
],
"version" : 2
"version" : 3
}
8 changes: 6 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,20 @@ jobs:
runs-on: macos-14
strategy:
matrix:
xcode:
- 15.4
- 16_beta_6
config:
- debug
- release
steps:
- uses: actions/checkout@v4
- name: Select Xcode 15.4
run: sudo xcode-select -s /Applications/Xcode_15.4.app
- name: Select Xcode ${{ matrix.xcode }}
run: sudo xcode-select -s /Applications/Xcode_${{ matrix.xcode }}.app
- name: Build ${{ matrix.config }}
run: make CONFIG=${{ matrix.config }} build-all-platforms
- name: Run ${{ matrix.config }} tests
if: matrix.xcode == '15.4'
run: make CONFIG=${{ matrix.config }} test-library

# library-evolution:
Expand Down
7 changes: 4 additions & 3 deletions Examples/SyncUps/SyncUpsTests/AppFeatureTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import XCTest

final class AppFeatureTests: XCTestCase {
func testDetailEdit() async throws {
var syncUp = SyncUp.mock
let syncUp = SyncUp.mock
@Shared(.syncUps) var syncUps = [syncUp]
let store = await TestStore(initialState: AppFeature.State()) {
AppFeature()
Expand All @@ -21,8 +21,9 @@ final class AppFeatureTests: XCTestCase {
$0.path[id: 0]?.modify(\.detail) { $0.destination = .edit(SyncUpForm.State(syncUp: syncUp)) }
}

syncUp.title = "Blob"
await store.send(\.path[id:0].detail.destination.edit.binding.syncUp, syncUp) {
var newSyncUp = syncUp
newSyncUp.title = "Blob"
await store.send(\.path[id:0].detail.destination.edit.binding.syncUp, newSyncUp) {
$0.path[id: 0]?.modify(\.detail) {
$0.destination?.modify(\.edit) { $0.syncUp.title = "Blob" }
}
Expand Down
2 changes: 1 addition & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ let package = Package(
)

#if compiler(>=6)
for target in package.targets where target.type != .system {
for target in package.targets where target.type != .system && target.type != .test {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added this temporarily so that we don't get flooded with warnings in test targets, but maybe we should keep this around until we've addressed all/most warnings in TCA proper, and then we can later concentrate on tests?

target.swiftSettings = target.swiftSettings ?? []
target.swiftSettings?.append(contentsOf: [
.enableExperimentalFeature("StrictConcurrency"),
Expand Down
97 changes: 97 additions & 0 deletions Package@swift-6.0.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
// swift-tools-version:6.0

import CompilerPluginSupport
import PackageDescription

let package = Package(
name: "swift-composable-architecture",
platforms: [
.iOS(.v13),
.macOS(.v10_15),
.tvOS(.v13),
.watchOS(.v6),
],
products: [
.library(
name: "ComposableArchitecture",
targets: ["ComposableArchitecture"]
)
],
dependencies: [
.package(url: "https://github.com/apple/swift-collections", from: "1.1.0"),
.package(url: "https://github.com/google/swift-benchmark", from: "0.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-custom-dump", from: "1.3.2"),
.package(url: "https://github.com/pointfreeco/swift-dependencies", from: "1.3.5"),
.package(url: "https://github.com/pointfreeco/swift-identified-collections", from: "1.1.0"),
.package(url: "https://github.com/pointfreeco/swift-macro-testing", from: "0.2.0"),
.package(url: "https://github.com/pointfreeco/swift-navigation", from: "2.1.0"),
.package(url: "https://github.com/pointfreeco/swift-perception", from: "1.3.4"),
.package(url: "https://github.com/pointfreeco/xctest-dynamic-overlay", from: "1.2.2"),
.package(url: "https://github.com/swiftlang/swift-docc-plugin", from: "1.0.0"),
.package(url: "https://github.com/swiftlang/swift-syntax", "509.0.0"..<"601.0.0-prerelease"),
],
targets: [
.target(
name: "ComposableArchitecture",
dependencies: [
"ComposableArchitectureMacros",
.product(name: "CasePaths", package: "swift-case-paths"),
.product(name: "CombineSchedulers", package: "combine-schedulers"),
.product(name: "ConcurrencyExtras", package: "swift-concurrency-extras"),
.product(name: "CustomDump", package: "swift-custom-dump"),
.product(name: "Dependencies", package: "swift-dependencies"),
.product(name: "DependenciesMacros", package: "swift-dependencies"),
.product(name: "IdentifiedCollections", package: "swift-identified-collections"),
.product(name: "IssueReporting", package: "xctest-dynamic-overlay"),
.product(name: "OrderedCollections", package: "swift-collections"),
.product(name: "Perception", package: "swift-perception"),
.product(name: "SwiftUINavigation", package: "swift-navigation"),
.product(name: "UIKitNavigation", package: "swift-navigation"),
],
resources: [
.process("Resources/PrivacyInfo.xcprivacy")
]
),
.testTarget(
name: "ComposableArchitectureTests",
dependencies: [
"ComposableArchitecture",
.product(name: "IssueReportingTestSupport", package: "xctest-dynamic-overlay"),
]
),
.macro(
name: "ComposableArchitectureMacros",
dependencies: [
.product(name: "SwiftSyntaxMacros", package: "swift-syntax"),
.product(name: "SwiftCompilerPlugin", package: "swift-syntax"),
]
),
.testTarget(
name: "ComposableArchitectureMacrosTests",
dependencies: [
"ComposableArchitectureMacros",
.product(name: "MacroTesting", package: "swift-macro-testing"),
]
),
.executableTarget(
name: "swift-composable-architecture-benchmark",
dependencies: [
"ComposableArchitecture",
.product(name: "Benchmark", package: "swift-benchmark"),
]
),
],
swiftLanguageModes: [.v6]
)

for target in package.targets where target.type == .system || target.type == .test {
target.swiftSettings = target.swiftSettings ?? []
target.swiftSettings?.append(contentsOf: [
.swiftLanguageMode(.v5),
.enableExperimentalFeature("StrictConcurrency"),
.enableUpcomingFeature("InferSendableFromCaptures")
])
}
Original file line number Diff line number Diff line change
Expand Up @@ -730,7 +730,7 @@ public struct _PresentedID: Hashable, Sendable {

extension Task<Never, Never> {
internal static func _cancel(
id: some Hashable,
id: some Hashable & Sendable,
navigationID: NavigationIDPath
) {
withDependencies {
Expand All @@ -754,7 +754,7 @@ extension Effect {
}
}
internal static func _cancel(
id: some Hashable = _PresentedID(),
id: some Hashable & Sendable = _PresentedID(),
navigationID: NavigationIDPath
) -> Self {
withDependencies {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
///
/// See the article <doc:SharingState> for more information, in particular the
/// <doc:SharingState#Custom-persistence> section.
public protocol PersistenceReaderKey<Value> {
public protocol PersistenceReaderKey<Value>: Sendable {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Persistence keys need to be sendable because they are captured in some LockIsolated's, which currently require Sendable values and @Sendable transaction closures. If we weaken that, then perhaps this can be weakened too?

/// A type that can be loaded or subscribed to in an external system.
associatedtype Value
associatedtype Value: Sendable
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Value is captured in a variety of sendable contexts, such as in the subscription endpoint for persistence strategies. So I think this does really need to be full blown Sendable.


/// A type representing the hashable identity of a persistence key.
associatedtype ID: Hashable = Self
Expand Down
Loading