@@ -93,6 +93,14 @@ private struct LambdaHTTPServer {
9393 case serverReturned( Swift . Result < Void , any Error > )
9494 }
9595
96+ struct UnsafeTransferBox < Value> : @unchecked Sendable {
97+ let value : Value
98+
99+ init ( value: sending Value) {
100+ self . value = value
101+ }
102+ }
103+
96104 static func withLocalServer< Result: Sendable > (
97105 invocationEndpoint: String ? ,
98106 host: String = " 127.0.0.1 " ,
@@ -135,18 +143,13 @@ private struct LambdaHTTPServer {
135143
136144 let server = LambdaHTTPServer ( invocationEndpoint: invocationEndpoint)
137145
138- // We are handling each incoming connection in a separate child task. It is important
139- // to use a discarding task group here which automatically discards finished child tasks.
140- // A normal task group retains all child tasks and their outputs in memory until they are
141- // consumed by iterating the group or by exiting the group. Since, we are never consuming
142- // the results of the group we need the group to automatically discard them; otherwise, this
143- // would result in a memory leak over time.
146+ // Sadly the Swift compiler does not understand that the passed in closure will only be
147+ // invoked once. Because of this we need an unsafe transfer box here. Buuuh!
148+ let closureBox = UnsafeTransferBox ( value: closure)
144149 let result = await withTaskGroup ( of: TaskResult< Result> . self , returning: Swift . Result < Result , any Error > . self) { group in
145-
146- let c = closure
147150 group. addTask {
151+ let c = closureBox. value
148152 do {
149-
150153 let result = try await c ( )
151154 return . closureResult( . success( result) )
152155 } catch {
@@ -156,6 +159,12 @@ private struct LambdaHTTPServer {
156159
157160 group. addTask {
158161 do {
162+ // We are handling each incoming connection in a separate child task. It is important
163+ // to use a discarding task group here which automatically discards finished child tasks.
164+ // A normal task group retains all child tasks and their outputs in memory until they are
165+ // consumed by iterating the group or by exiting the group. Since, we are never consuming
166+ // the results of the group we need the group to automatically discard them; otherwise, this
167+ // would result in a memory leak over time.
159168 try await withThrowingDiscardingTaskGroup { taskGroup in
160169 try await channel. executeThenClose { inbound in
161170 for try await connectionChannel in inbound {
0 commit comments