Skip to content

Commit 7c6fb26

Browse files
Address @shared sendability. (#3329)
* Address @shared sendability. * Undo UncheckedSendable<UserDefaults>. * clean up * wip * drop AnySendable. * wip * Address `Effect.throttle` sendability (#3325) * Address effect cancellation sendability (#3326) * Address effect cancellation sendability * fix * wip * wip * Separate SendableDefaultSubscript from DefaultSubscript. * fix test * drop escaping * switch on swift 6 language mode * xcode 16 * update test * wip --------- Co-authored-by: Stephen Celis <[email protected]>
1 parent 83ed123 commit 7c6fb26

File tree

19 files changed

+237
-113
lines changed

19 files changed

+237
-113
lines changed

.github/package.xcworkspace/xcshareddata/swiftpm/Package.resolved

+26-25
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
{
2+
"originHash" : "a84dfeef15185f26bd546eb430da9b0b1f23f5a08c6ac0f99b345a8de1564068",
23
"pins" : [
34
{
45
"identity" : "combine-schedulers",
@@ -32,26 +33,26 @@
3233
"kind" : "remoteSourceControl",
3334
"location" : "https://github.com/pointfreeco/swift-case-paths",
3435
"state" : {
35-
"revision" : "71344dd930fde41e8f3adafe260adcbb2fc2a3dc",
36-
"version" : "1.5.4"
36+
"revision" : "642e6aab8e03e5f992d9c83e38c5be98cfad5078",
37+
"version" : "1.5.5"
3738
}
3839
},
3940
{
4041
"identity" : "swift-clocks",
4142
"kind" : "remoteSourceControl",
4243
"location" : "https://github.com/pointfreeco/swift-clocks",
4344
"state" : {
44-
"revision" : "3581e280bf0d90c3fb9236fb23e75a5d8c46b533",
45-
"version" : "1.0.4"
45+
"revision" : "b9b24b69e2adda099a1fa381cda1eeec272d5b53",
46+
"version" : "1.0.5"
4647
}
4748
},
4849
{
4950
"identity" : "swift-collections",
5051
"kind" : "remoteSourceControl",
5152
"location" : "https://github.com/apple/swift-collections",
5253
"state" : {
53-
"revision" : "3d2dc41a01f9e49d84f0a3925fb858bed64f702d",
54-
"version" : "1.1.2"
54+
"revision" : "9bf03ff58ce34478e66aaee630e491823326fd06",
55+
"version" : "1.1.3"
5556
}
5657
},
5758
{
@@ -77,23 +78,23 @@
7778
"kind" : "remoteSourceControl",
7879
"location" : "https://github.com/pointfreeco/swift-dependencies",
7980
"state" : {
80-
"revision" : "d7472be6b3c89251ce4c0db07d32405b43426781",
81-
"version" : "1.3.7"
81+
"revision" : "3ef38bb702a1a2f39c7e19fc0578403b8ee52b17",
82+
"version" : "1.3.9"
8283
}
8384
},
8485
{
8586
"identity" : "swift-docc-plugin",
8687
"kind" : "remoteSourceControl",
87-
"location" : "https://github.com/apple/swift-docc-plugin",
88+
"location" : "https://github.com/swiftlang/swift-docc-plugin",
8889
"state" : {
89-
"revision" : "26ac5758409154cc448d7ab82389c520fa8a8247",
90-
"version" : "1.3.0"
90+
"revision" : "2eb22993b3dfd0c0d32729b357c8dabb6cd44680",
91+
"version" : "1.4.2"
9192
}
9293
},
9394
{
9495
"identity" : "swift-docc-symbolkit",
9596
"kind" : "remoteSourceControl",
96-
"location" : "https://github.com/apple/swift-docc-symbolkit",
97+
"location" : "https://github.com/swiftlang/swift-docc-symbolkit",
9798
"state" : {
9899
"revision" : "b45d1f2ed151d057b54504d653e0da5552844e34",
99100
"version" : "1.0.0"
@@ -113,55 +114,55 @@
113114
"kind" : "remoteSourceControl",
114115
"location" : "https://github.com/pointfreeco/swift-macro-testing",
115116
"state" : {
116-
"revision" : "a35257b7e9ce44e92636447003a8eeefb77b145c",
117-
"version" : "0.5.1"
117+
"revision" : "20c1a8f3b624fb5d1503eadcaa84743050c350f4",
118+
"version" : "0.5.2"
118119
}
119120
},
120121
{
121122
"identity" : "swift-navigation",
122123
"kind" : "remoteSourceControl",
123124
"location" : "https://github.com/pointfreeco/swift-navigation",
124125
"state" : {
125-
"revision" : "47cfd149ed01223d14fc8e3f52ae27d3a35fe036",
126-
"version" : "2.0.3"
126+
"revision" : "e834b3760731160d7d448509ee6a1408c8582a6b",
127+
"version" : "2.2.0"
127128
}
128129
},
129130
{
130131
"identity" : "swift-perception",
131132
"kind" : "remoteSourceControl",
132133
"location" : "https://github.com/pointfreeco/swift-perception",
133134
"state" : {
134-
"revision" : "1552c8f722ac256cc0b8daaf1a7073217d4fcdfb",
135-
"version" : "1.3.4"
135+
"revision" : "bc67aa8e461351c97282c2419153757a446ae1c9",
136+
"version" : "1.3.5"
136137
}
137138
},
138139
{
139140
"identity" : "swift-snapshot-testing",
140141
"kind" : "remoteSourceControl",
141142
"location" : "https://github.com/pointfreeco/swift-snapshot-testing",
142143
"state" : {
143-
"revision" : "c097f955b4e724690f0fc8ffb7a6d4b881c9c4e3",
144-
"version" : "1.17.2"
144+
"revision" : "6d932a79e7173b275b96c600c86c603cf84f153c",
145+
"version" : "1.17.4"
145146
}
146147
},
147148
{
148149
"identity" : "swift-syntax",
149150
"kind" : "remoteSourceControl",
150151
"location" : "https://github.com/swiftlang/swift-syntax",
151152
"state" : {
152-
"revision" : "4c6cc0a3b9e8f14b3ae2307c5ccae4de6167ac2c",
153-
"version" : "600.0.0-prerelease-2024-06-12"
153+
"revision" : "515f79b522918f83483068d99c68daeb5116342d",
154+
"version" : "600.0.0-prerelease-2024-09-04"
154155
}
155156
},
156157
{
157158
"identity" : "xctest-dynamic-overlay",
158159
"kind" : "remoteSourceControl",
159160
"location" : "https://github.com/pointfreeco/xctest-dynamic-overlay",
160161
"state" : {
161-
"revision" : "357ca1e5dd31f613a1d43320870ebc219386a495",
162-
"version" : "1.2.2"
162+
"revision" : "96beb108a57f24c8476ae1f309239270772b2940",
163+
"version" : "1.2.5"
163164
}
164165
}
165166
],
166-
"version" : 2
167+
"version" : 3
167168
}

.github/workflows/ci.yml

+6-2
Original file line numberDiff line numberDiff line change
@@ -19,16 +19,20 @@ jobs:
1919
runs-on: macos-14
2020
strategy:
2121
matrix:
22+
xcode:
23+
- 15.4
24+
- 16_beta_6
2225
config:
2326
- debug
2427
- release
2528
steps:
2629
- uses: actions/checkout@v4
27-
- name: Select Xcode 15.4
28-
run: sudo xcode-select -s /Applications/Xcode_15.4.app
30+
- name: Select Xcode ${{ matrix.xcode }}
31+
run: sudo xcode-select -s /Applications/Xcode_${{ matrix.xcode }}.app
2932
- name: Build ${{ matrix.config }}
3033
run: make CONFIG=${{ matrix.config }} build-all-platforms
3134
- name: Run ${{ matrix.config }} tests
35+
if: matrix.xcode == '15.4'
3236
run: make CONFIG=${{ matrix.config }} test-library
3337

3438
# library-evolution:

Examples/SyncUps/SyncUpsTests/AppFeatureTests.swift

+4-3
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import XCTest
55

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

24-
syncUp.title = "Blob"
25-
await store.send(\.path[id:0].detail.destination.edit.binding.syncUp, syncUp) {
24+
var newSyncUp = syncUp
25+
newSyncUp.title = "Blob"
26+
await store.send(\.path[id:0].detail.destination.edit.binding.syncUp, newSyncUp) {
2627
$0.path[id: 0]?.modify(\.detail) {
2728
$0.destination?.modify(\.edit) { $0.syncUp.title = "Blob" }
2829
}

Package.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ let package = Package(
8787
)
8888

8989
#if compiler(>=6)
90-
for target in package.targets where target.type != .system {
90+
for target in package.targets where target.type != .system && target.type != .test {
9191
target.swiftSettings = target.swiftSettings ?? []
9292
target.swiftSettings?.append(contentsOf: [
9393
.enableExperimentalFeature("StrictConcurrency"),

[email protected]

+97
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
// swift-tools-version:6.0
2+
3+
import CompilerPluginSupport
4+
import PackageDescription
5+
6+
let package = Package(
7+
name: "swift-composable-architecture",
8+
platforms: [
9+
.iOS(.v13),
10+
.macOS(.v10_15),
11+
.tvOS(.v13),
12+
.watchOS(.v6),
13+
],
14+
products: [
15+
.library(
16+
name: "ComposableArchitecture",
17+
targets: ["ComposableArchitecture"]
18+
)
19+
],
20+
dependencies: [
21+
.package(url: "https://github.com/apple/swift-collections", from: "1.1.0"),
22+
.package(url: "https://github.com/google/swift-benchmark", from: "0.1.0"),
23+
.package(url: "https://github.com/pointfreeco/combine-schedulers", from: "1.0.2"),
24+
.package(url: "https://github.com/pointfreeco/swift-case-paths", from: "1.5.4"),
25+
.package(url: "https://github.com/pointfreeco/swift-concurrency-extras", from: "1.1.0"),
26+
.package(url: "https://github.com/pointfreeco/swift-custom-dump", from: "1.3.2"),
27+
.package(url: "https://github.com/pointfreeco/swift-dependencies", from: "1.3.5"),
28+
.package(url: "https://github.com/pointfreeco/swift-identified-collections", from: "1.1.0"),
29+
.package(url: "https://github.com/pointfreeco/swift-macro-testing", from: "0.2.0"),
30+
.package(url: "https://github.com/pointfreeco/swift-navigation", from: "2.1.0"),
31+
.package(url: "https://github.com/pointfreeco/swift-perception", from: "1.3.4"),
32+
.package(url: "https://github.com/pointfreeco/xctest-dynamic-overlay", from: "1.2.2"),
33+
.package(url: "https://github.com/swiftlang/swift-docc-plugin", from: "1.0.0"),
34+
.package(url: "https://github.com/swiftlang/swift-syntax", "509.0.0"..<"601.0.0-prerelease"),
35+
],
36+
targets: [
37+
.target(
38+
name: "ComposableArchitecture",
39+
dependencies: [
40+
"ComposableArchitectureMacros",
41+
.product(name: "CasePaths", package: "swift-case-paths"),
42+
.product(name: "CombineSchedulers", package: "combine-schedulers"),
43+
.product(name: "ConcurrencyExtras", package: "swift-concurrency-extras"),
44+
.product(name: "CustomDump", package: "swift-custom-dump"),
45+
.product(name: "Dependencies", package: "swift-dependencies"),
46+
.product(name: "DependenciesMacros", package: "swift-dependencies"),
47+
.product(name: "IdentifiedCollections", package: "swift-identified-collections"),
48+
.product(name: "IssueReporting", package: "xctest-dynamic-overlay"),
49+
.product(name: "OrderedCollections", package: "swift-collections"),
50+
.product(name: "Perception", package: "swift-perception"),
51+
.product(name: "SwiftUINavigation", package: "swift-navigation"),
52+
.product(name: "UIKitNavigation", package: "swift-navigation"),
53+
],
54+
resources: [
55+
.process("Resources/PrivacyInfo.xcprivacy")
56+
]
57+
),
58+
.testTarget(
59+
name: "ComposableArchitectureTests",
60+
dependencies: [
61+
"ComposableArchitecture",
62+
.product(name: "IssueReportingTestSupport", package: "xctest-dynamic-overlay"),
63+
]
64+
),
65+
.macro(
66+
name: "ComposableArchitectureMacros",
67+
dependencies: [
68+
.product(name: "SwiftSyntaxMacros", package: "swift-syntax"),
69+
.product(name: "SwiftCompilerPlugin", package: "swift-syntax"),
70+
]
71+
),
72+
.testTarget(
73+
name: "ComposableArchitectureMacrosTests",
74+
dependencies: [
75+
"ComposableArchitectureMacros",
76+
.product(name: "MacroTesting", package: "swift-macro-testing"),
77+
]
78+
),
79+
.executableTarget(
80+
name: "swift-composable-architecture-benchmark",
81+
dependencies: [
82+
"ComposableArchitecture",
83+
.product(name: "Benchmark", package: "swift-benchmark"),
84+
]
85+
),
86+
],
87+
swiftLanguageModes: [.v6]
88+
)
89+
90+
for target in package.targets where target.type == .system || target.type == .test {
91+
target.swiftSettings = target.swiftSettings ?? []
92+
target.swiftSettings?.append(contentsOf: [
93+
.swiftLanguageMode(.v5),
94+
.enableExperimentalFeature("StrictConcurrency"),
95+
.enableUpcomingFeature("InferSendableFromCaptures")
96+
])
97+
}

Sources/ComposableArchitecture/Reducer/Reducers/PresentationReducer.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -730,7 +730,7 @@ public struct _PresentedID: Hashable, Sendable {
730730

731731
extension Task<Never, Never> {
732732
internal static func _cancel(
733-
id: some Hashable,
733+
id: some Hashable & Sendable,
734734
navigationID: NavigationIDPath
735735
) {
736736
withDependencies {
@@ -754,7 +754,7 @@ extension Effect {
754754
}
755755
}
756756
internal static func _cancel(
757-
id: some Hashable = _PresentedID(),
757+
id: some Hashable & Sendable = _PresentedID(),
758758
navigationID: NavigationIDPath
759759
) -> Self {
760760
withDependencies {

Sources/ComposableArchitecture/SharedState/PersistenceKey.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@
77
///
88
/// See the article <doc:SharingState> for more information, in particular the
99
/// <doc:SharingState#Custom-persistence> section.
10-
public protocol PersistenceReaderKey<Value> {
10+
public protocol PersistenceReaderKey<Value>: Sendable {
1111
/// A type that can be loaded or subscribed to in an external system.
12-
associatedtype Value
12+
associatedtype Value: Sendable
1313

1414
/// A type representing the hashable identity of a persistence key.
1515
associatedtype ID: Hashable = Self

0 commit comments

Comments
 (0)