diff --git a/Workflow/Sources/SubtreeManager.swift b/Workflow/Sources/SubtreeManager.swift index c92c7856d..987c6b766 100644 --- a/Workflow/Sources/SubtreeManager.swift +++ b/Workflow/Sources/SubtreeManager.swift @@ -114,7 +114,7 @@ extension WorkflowNode { extension WorkflowNode.SubtreeManager { enum Output { - case update(AnyWorkflowAction, source: WorkflowUpdateDebugInfo.Source) + case update(any WorkflowAction, source: WorkflowUpdateDebugInfo.Source) case childDidUpdate(WorkflowUpdateDebugInfo) } } @@ -175,7 +175,7 @@ extension WorkflowNode.SubtreeManager { /// Update the existing child existing.update( workflow: workflow, - outputMap: { AnyWorkflowAction(outputMap($0)) }, + outputMap: { outputMap($0) }, eventPipe: eventPipe ) child = existing @@ -184,7 +184,7 @@ extension WorkflowNode.SubtreeManager { /// This spins up a new workflow node, etc to host the newly created child. child = ChildWorkflow( workflow: workflow, - outputMap: { AnyWorkflowAction(outputMap($0)) }, + outputMap: { outputMap($0) }, eventPipe: eventPipe ) } @@ -272,7 +272,7 @@ extension WorkflowNode.SubtreeManager { fileprivate final class ReusableSink: AnyReusableSink where Action.WorkflowType == WorkflowType { func handle(action: Action) { - let output = Output.update(AnyWorkflowAction(action), source: .external) + let output = Output.update(action, source: .external) if case .pending = eventPipe.validationState { // Workflow is currently processing an `event`. @@ -387,9 +387,13 @@ extension WorkflowNode.SubtreeManager { fileprivate final class ChildWorkflow: AnyChildWorkflow { private let node: WorkflowNode - private var outputMap: (W.Output) -> AnyWorkflowAction + private var outputMap: (W.Output) -> any WorkflowAction - init(workflow: W, outputMap: @escaping (W.Output) -> AnyWorkflowAction, eventPipe: EventPipe) { + init( + workflow: W, + outputMap: @escaping (W.Output) -> any WorkflowAction, + eventPipe: EventPipe + ) { self.outputMap = outputMap self.node = WorkflowNode(workflow: workflow) @@ -408,7 +412,11 @@ extension WorkflowNode.SubtreeManager { return node.render(isRootNode: false) } - func update(workflow: W, outputMap: @escaping (W.Output) -> AnyWorkflowAction, eventPipe: EventPipe) { + func update( + workflow: W, + outputMap: @escaping (W.Output) -> any WorkflowAction, + eventPipe: EventPipe + ) { self.outputMap = outputMap self.eventPipe = eventPipe node.update(workflow: workflow) diff --git a/Workflow/Sources/WorkflowNode.swift b/Workflow/Sources/WorkflowNode.swift index a2af1a51c..4590dc975 100644 --- a/Workflow/Sources/WorkflowNode.swift +++ b/Workflow/Sources/WorkflowNode.swift @@ -48,9 +48,19 @@ final class WorkflowNode { let output: Output switch subtreeOutput { - case .update(let event, let source): - /// Apply the update to the current state - let outputEvent = event.apply(toState: &state) + case .update(let action, let source): + + /// 'Opens' the existential `any WorkflowAction` value + /// allowing the underlying conformance to be applied to the Workflow's State + func openAndApply( + _ action: A, + to state: inout WorkflowType.State + ) -> WorkflowType.Output? where A.WorkflowType == WorkflowType { + /// Apply the update to the current state + action.apply(toState: &state) + } + + let outputEvent = openAndApply(action, to: &state) /// Finally, we tell the outside world that our state has changed (including an output event if it exists). output = Output( diff --git a/Workflow/Tests/SubtreeManagerTests.swift b/Workflow/Tests/SubtreeManagerTests.swift index f2ac501b5..a7a43b589 100644 --- a/Workflow/Tests/SubtreeManagerTests.swift +++ b/Workflow/Tests/SubtreeManagerTests.swift @@ -72,7 +72,7 @@ final class SubtreeManagerTests: XCTestCase { manager.onUpdate = { switch $0 { case .update(let event, _): - events.append(event) + events.append(AnyWorkflowAction(event)) default: break }