Skip to content

Commit 051e5bd

Browse files
authored
Address RootStore sendability warnings (#3321)
1 parent cad094a commit 051e5bd

File tree

1 file changed

+40
-41
lines changed

1 file changed

+40
-41
lines changed

Sources/ComposableArchitecture/RootStore.swift

Lines changed: 40 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ public final class RootStore {
3030

3131
self.isSending = true
3232
var currentState = self.state as! State
33-
let tasks = Box<[Task<Void, Never>]>(wrappedValue: [])
33+
let tasks = LockIsolated<[Task<Void, Never>]>([])
3434
defer {
3535
withExtendedLifetime(self.bufferedActions) {
3636
self.bufferedActions.removeAll()
@@ -42,7 +42,7 @@ public final class RootStore {
4242
self.bufferedActions.removeLast(),
4343
originatingFrom: originatingAction
4444
) {
45-
tasks.wrappedValue.append(task)
45+
tasks.withValue { $0.append(task) }
4646
}
4747
}
4848
}
@@ -75,7 +75,7 @@ public final class RootStore {
7575
if let task = continuation.yield({
7676
self.send(effectAction, originatingFrom: action)
7777
}) {
78-
tasks.wrappedValue.append(task)
78+
tasks.withValue { $0.append(task) }
7979
}
8080
}
8181
)
@@ -87,63 +87,62 @@ public final class RootStore {
8787
effectCancellable.cancel()
8888
}
8989
boxedTask.wrappedValue = task
90-
tasks.wrappedValue.append(task)
90+
tasks.withValue { $0.append(task) }
9191
self.effectCancellables[uuid] = effectCancellable
9292
}
9393
case let .run(priority, operation):
9494
withEscapedDependencies { continuation in
95-
tasks.wrappedValue.append(
96-
Task(priority: priority) { @MainActor in
97-
let isCompleted = LockIsolated(false)
98-
defer { isCompleted.setValue(true) }
99-
await operation(
100-
Send { effectAction in
101-
if isCompleted.value {
102-
reportIssue(
103-
"""
104-
An action was sent from a completed effect:
95+
let task = Task(priority: priority) { @MainActor in
96+
let isCompleted = LockIsolated(false)
97+
defer { isCompleted.setValue(true) }
98+
await operation(
99+
Send { effectAction in
100+
if isCompleted.value {
101+
reportIssue(
102+
"""
103+
An action was sent from a completed effect:
105104
106-
Action:
107-
\(debugCaseOutput(effectAction))
105+
Action:
106+
\(debugCaseOutput(effectAction))
108107
109-
Effect returned from:
110-
\(debugCaseOutput(action))
108+
Effect returned from:
109+
\(debugCaseOutput(action))
111110
112-
Avoid sending actions using the 'send' argument from 'Effect.run' after \
113-
the effect has completed. This can happen if you escape the 'send' \
114-
argument in an unstructured context.
111+
Avoid sending actions using the 'send' argument from 'Effect.run' after \
112+
the effect has completed. This can happen if you escape the 'send' \
113+
argument in an unstructured context.
115114
116-
To fix this, make sure that your 'run' closure does not return until \
117-
you're done calling 'send'.
118-
"""
119-
)
120-
}
121-
if let task = continuation.yield({
122-
self.send(effectAction, originatingFrom: action)
123-
}) {
124-
tasks.wrappedValue.append(task)
125-
}
115+
To fix this, make sure that your 'run' closure does not return until \
116+
you're done calling 'send'.
117+
"""
118+
)
126119
}
127-
)
128-
}
129-
)
120+
if let task = continuation.yield({
121+
self.send(effectAction, originatingFrom: action)
122+
}) {
123+
tasks.withValue { $0.append(task) }
124+
}
125+
}
126+
)
127+
}
128+
tasks.withValue { $0.append(task) }
130129
}
131130
}
132131
}
133132

134-
guard !tasks.wrappedValue.isEmpty else { return nil }
133+
guard !tasks.isEmpty else { return nil }
135134
return Task { @MainActor in
136135
await withTaskCancellationHandler {
137-
var index = tasks.wrappedValue.startIndex
138-
while index < tasks.wrappedValue.endIndex {
136+
var index = tasks.startIndex
137+
while index < tasks.endIndex {
139138
defer { index += 1 }
140-
await tasks.wrappedValue[index].value
139+
await tasks[index].value
141140
}
142141
} onCancel: {
143-
var index = tasks.wrappedValue.startIndex
144-
while index < tasks.wrappedValue.endIndex {
142+
var index = tasks.startIndex
143+
while index < tasks.endIndex {
145144
defer { index += 1 }
146-
tasks.wrappedValue[index].cancel()
145+
tasks[index].cancel()
147146
}
148147
}
149148
}

0 commit comments

Comments
 (0)