diff --git a/Sources/Examples/Echo/Model/echo.grpc.swift b/Sources/Examples/Echo/Model/echo.grpc.swift index 599de4587..900fbd2d5 100644 --- a/Sources/Examples/Echo/Model/echo.grpc.swift +++ b/Sources/Examples/Echo/Model/echo.grpc.swift @@ -316,7 +316,7 @@ extension Echo_EchoAsyncClientProtocol { public func collect( _ requests: RequestStream, callOptions: CallOptions? = nil - ) async throws -> Echo_EchoResponse where RequestStream: AsyncSequence, RequestStream.Element == Echo_EchoRequest { + ) async throws -> Echo_EchoResponse where RequestStream: AsyncSequence & Sendable, RequestStream.Element == Echo_EchoRequest { return try await self.performAsyncClientStreamingCall( path: Echo_EchoClientMetadata.Methods.collect.path, requests: requests, @@ -340,7 +340,7 @@ extension Echo_EchoAsyncClientProtocol { public func update( _ requests: RequestStream, callOptions: CallOptions? = nil - ) -> GRPCAsyncResponseStream where RequestStream: AsyncSequence, RequestStream.Element == Echo_EchoRequest { + ) -> GRPCAsyncResponseStream where RequestStream: AsyncSequence & Sendable, RequestStream.Element == Echo_EchoRequest { return self.performAsyncBidirectionalStreamingCall( path: Echo_EchoClientMetadata.Methods.update.path, requests: requests, diff --git a/Sources/Examples/RouteGuide/Model/route_guide.grpc.swift b/Sources/Examples/RouteGuide/Model/route_guide.grpc.swift index c3b0e77a5..641d470cf 100644 --- a/Sources/Examples/RouteGuide/Model/route_guide.grpc.swift +++ b/Sources/Examples/RouteGuide/Model/route_guide.grpc.swift @@ -335,7 +335,7 @@ extension Routeguide_RouteGuideAsyncClientProtocol { public func recordRoute( _ requests: RequestStream, callOptions: CallOptions? = nil - ) async throws -> Routeguide_RouteSummary where RequestStream: AsyncSequence, RequestStream.Element == Routeguide_Point { + ) async throws -> Routeguide_RouteSummary where RequestStream: AsyncSequence & Sendable, RequestStream.Element == Routeguide_Point { return try await self.performAsyncClientStreamingCall( path: Routeguide_RouteGuideClientMetadata.Methods.recordRoute.path, requests: requests, @@ -359,7 +359,7 @@ extension Routeguide_RouteGuideAsyncClientProtocol { public func routeChat( _ requests: RequestStream, callOptions: CallOptions? = nil - ) -> GRPCAsyncResponseStream where RequestStream: AsyncSequence, RequestStream.Element == Routeguide_RouteNote { + ) -> GRPCAsyncResponseStream where RequestStream: AsyncSequence & Sendable, RequestStream.Element == Routeguide_RouteNote { return self.performAsyncBidirectionalStreamingCall( path: Routeguide_RouteGuideClientMetadata.Methods.routeChat.path, requests: requests, diff --git a/Sources/GRPC/AsyncAwaitSupport/AsyncWriter.swift b/Sources/GRPC/AsyncAwaitSupport/AsyncWriter.swift index fca2620c4..49d85aa7b 100644 --- a/Sources/GRPC/AsyncAwaitSupport/AsyncWriter.swift +++ b/Sources/GRPC/AsyncAwaitSupport/AsyncWriter.swift @@ -57,7 +57,7 @@ internal final actor AsyncWriter: Sendable { typealias PendingEnd = _Pending @usableFromInline - internal enum _CompletionState { + internal enum _CompletionState: Sendable { /// Finish hasn't been called yet. May move to `pending` or `completed`. case incomplete /// Finish has been called but the writer is paused. May move to `completed`. diff --git a/Sources/GRPC/AsyncAwaitSupport/GRPCAsyncBidirectionalStreamingCall.swift b/Sources/GRPC/AsyncAwaitSupport/GRPCAsyncBidirectionalStreamingCall.swift index 34bd21b40..af3d71430 100644 --- a/Sources/GRPC/AsyncAwaitSupport/GRPCAsyncBidirectionalStreamingCall.swift +++ b/Sources/GRPC/AsyncAwaitSupport/GRPCAsyncBidirectionalStreamingCall.swift @@ -19,7 +19,7 @@ import NIOHPACK /// Async-await variant of BidirectionalStreamingCall. @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) -public struct GRPCAsyncBidirectionalStreamingCall { +public struct GRPCAsyncBidirectionalStreamingCall: Sendable { private let call: Call private let responseParts: StreamingResponseParts private let responseSource: PassthroughMessageSource diff --git a/Sources/GRPC/AsyncAwaitSupport/GRPCAsyncClientStreamingCall.swift b/Sources/GRPC/AsyncAwaitSupport/GRPCAsyncClientStreamingCall.swift index ef662ba3e..19c9b3713 100644 --- a/Sources/GRPC/AsyncAwaitSupport/GRPCAsyncClientStreamingCall.swift +++ b/Sources/GRPC/AsyncAwaitSupport/GRPCAsyncClientStreamingCall.swift @@ -19,7 +19,7 @@ import NIOHPACK /// Async-await variant of `ClientStreamingCall`. @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) -public struct GRPCAsyncClientStreamingCall { +public struct GRPCAsyncClientStreamingCall: Sendable { private let call: Call private let responseParts: UnaryResponseParts diff --git a/Sources/GRPC/AsyncAwaitSupport/GRPCAsyncRequestStream.swift b/Sources/GRPC/AsyncAwaitSupport/GRPCAsyncRequestStream.swift index f2beff823..25df9899c 100644 --- a/Sources/GRPC/AsyncAwaitSupport/GRPCAsyncRequestStream.swift +++ b/Sources/GRPC/AsyncAwaitSupport/GRPCAsyncRequestStream.swift @@ -52,4 +52,9 @@ public struct GRPCAsyncRequestStream: AsyncSequence { } } +@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) +extension GRPCAsyncRequestStream: Sendable where Element: Sendable {} +@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) +extension GRPCAsyncRequestStream.Iterator: Sendable where Element: Sendable {} + #endif diff --git a/Sources/GRPC/AsyncAwaitSupport/GRPCAsyncRequestStreamWriter.swift b/Sources/GRPC/AsyncAwaitSupport/GRPCAsyncRequestStreamWriter.swift index f1d6c9d66..073fa9d28 100644 --- a/Sources/GRPC/AsyncAwaitSupport/GRPCAsyncRequestStreamWriter.swift +++ b/Sources/GRPC/AsyncAwaitSupport/GRPCAsyncRequestStreamWriter.swift @@ -31,7 +31,7 @@ /// try await stream.finish() /// ``` @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) -public struct GRPCAsyncRequestStreamWriter { +public struct GRPCAsyncRequestStreamWriter: Sendable { @usableFromInline internal let asyncWriter: AsyncWriter> diff --git a/Sources/GRPC/AsyncAwaitSupport/GRPCAsyncResponseStream.swift b/Sources/GRPC/AsyncAwaitSupport/GRPCAsyncResponseStream.swift index 7a2116aed..a0d1441fd 100644 --- a/Sources/GRPC/AsyncAwaitSupport/GRPCAsyncResponseStream.swift +++ b/Sources/GRPC/AsyncAwaitSupport/GRPCAsyncResponseStream.swift @@ -49,4 +49,9 @@ public struct GRPCAsyncResponseStream: AsyncSequence { } } +@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) +extension GRPCAsyncResponseStream: Sendable where Element: Sendable {} +@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) +extension GRPCAsyncResponseStream.Iterator: Sendable where Element: Sendable {} + #endif diff --git a/Sources/GRPC/AsyncAwaitSupport/GRPCAsyncResponseStreamWriter.swift b/Sources/GRPC/AsyncAwaitSupport/GRPCAsyncResponseStreamWriter.swift index 28e81ca70..454dfa808 100644 --- a/Sources/GRPC/AsyncAwaitSupport/GRPCAsyncResponseStreamWriter.swift +++ b/Sources/GRPC/AsyncAwaitSupport/GRPCAsyncResponseStreamWriter.swift @@ -18,7 +18,7 @@ /// Writer for server-streaming RPC handlers to provide responses. @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) -public struct GRPCAsyncResponseStreamWriter { +public struct GRPCAsyncResponseStreamWriter: Sendable { @usableFromInline internal typealias Element = (Response, Compression) diff --git a/Sources/GRPC/AsyncAwaitSupport/GRPCAsyncUnaryCall.swift b/Sources/GRPC/AsyncAwaitSupport/GRPCAsyncUnaryCall.swift index 18f756a44..484f2985c 100644 --- a/Sources/GRPC/AsyncAwaitSupport/GRPCAsyncUnaryCall.swift +++ b/Sources/GRPC/AsyncAwaitSupport/GRPCAsyncUnaryCall.swift @@ -22,7 +22,7 @@ import NIOHPACK /// Note: while this object is a `struct`, its implementation delegates to `Call`. It therefore /// has reference semantics. @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) -public struct GRPCAsyncUnaryCall { +public struct GRPCAsyncUnaryCall: Sendable { private let call: Call private let responseParts: UnaryResponseParts diff --git a/Sources/GRPC/AsyncAwaitSupport/GRPCClient+AsyncAwaitSupport.swift b/Sources/GRPC/AsyncAwaitSupport/GRPCClient+AsyncAwaitSupport.swift index 1169644ef..d60941ef1 100644 --- a/Sources/GRPC/AsyncAwaitSupport/GRPCClient+AsyncAwaitSupport.swift +++ b/Sources/GRPC/AsyncAwaitSupport/GRPCClient+AsyncAwaitSupport.swift @@ -19,7 +19,7 @@ import SwiftProtobuf @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) extension GRPCClient { - public func makeAsyncUnaryCall( + public func makeAsyncUnaryCall( path: String, request: Request, callOptions: CallOptions? = nil, @@ -34,7 +34,7 @@ extension GRPCClient { ) } - public func makeAsyncUnaryCall( + public func makeAsyncUnaryCall( path: String, request: Request, callOptions: CallOptions? = nil, @@ -50,8 +50,8 @@ extension GRPCClient { } public func makeAsyncServerStreamingCall< - Request: SwiftProtobuf.Message, - Response: SwiftProtobuf.Message + Request: SwiftProtobuf.Message & Sendable, + Response: SwiftProtobuf.Message & Sendable >( path: String, request: Request, @@ -67,7 +67,10 @@ extension GRPCClient { ) } - public func makeAsyncServerStreamingCall( + public func makeAsyncServerStreamingCall< + Request: GRPCPayload & Sendable, + Response: GRPCPayload & Sendable + >( path: String, request: Request, callOptions: CallOptions? = nil, @@ -83,8 +86,8 @@ extension GRPCClient { } public func makeAsyncClientStreamingCall< - Request: SwiftProtobuf.Message, - Response: SwiftProtobuf.Message + Request: SwiftProtobuf.Message & Sendable, + Response: SwiftProtobuf.Message & Sendable >( path: String, callOptions: CallOptions? = nil, @@ -99,7 +102,10 @@ extension GRPCClient { ) } - public func makeAsyncClientStreamingCall( + public func makeAsyncClientStreamingCall< + Request: GRPCPayload & Sendable, + Response: GRPCPayload & Sendable + >( path: String, callOptions: CallOptions? = nil, interceptors: [ClientInterceptor] = [], @@ -114,8 +120,8 @@ extension GRPCClient { } public func makeAsyncBidirectionalStreamingCall< - Request: SwiftProtobuf.Message, - Response: SwiftProtobuf.Message + Request: SwiftProtobuf.Message & Sendable, + Response: SwiftProtobuf.Message & Sendable >( path: String, callOptions: CallOptions? = nil, @@ -131,8 +137,8 @@ extension GRPCClient { } public func makeAsyncBidirectionalStreamingCall< - Request: GRPCPayload, - Response: GRPCPayload + Request: GRPCPayload & Sendable, + Response: GRPCPayload & Sendable >( path: String, callOptions: CallOptions? = nil, @@ -152,7 +158,7 @@ extension GRPCClient { @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) extension GRPCClient { - public func performAsyncUnaryCall( + public func performAsyncUnaryCall( path: String, request: Request, callOptions: CallOptions? = nil, @@ -167,7 +173,10 @@ extension GRPCClient { ).response } - public func performAsyncUnaryCall( + public func performAsyncUnaryCall< + Request: GRPCPayload & Sendable, + Response: GRPCPayload & Sendable + >( path: String, request: Request, callOptions: CallOptions? = nil, @@ -183,8 +192,8 @@ extension GRPCClient { } public func performAsyncServerStreamingCall< - Request: SwiftProtobuf.Message, - Response: SwiftProtobuf.Message + Request: SwiftProtobuf.Message & Sendable, + Response: SwiftProtobuf.Message & Sendable >( path: String, request: Request, @@ -200,7 +209,10 @@ extension GRPCClient { ).responseStream } - public func performAsyncServerStreamingCall( + public func performAsyncServerStreamingCall< + Request: GRPCPayload & Sendable, + Response: GRPCPayload & Sendable + >( path: String, request: Request, callOptions: CallOptions? = nil, @@ -216,9 +228,9 @@ extension GRPCClient { } public func performAsyncClientStreamingCall< - Request: SwiftProtobuf.Message, - Response: SwiftProtobuf.Message, - RequestStream + Request: SwiftProtobuf.Message & Sendable, + Response: SwiftProtobuf.Message & Sendable, + RequestStream: AsyncSequence & Sendable >( path: String, requests: RequestStream, @@ -226,8 +238,7 @@ extension GRPCClient { interceptors: [ClientInterceptor] = [], requestType: Request.Type = Request.self, responseType: Response.Type = Response.self - ) async throws -> Response - where RequestStream: AsyncSequence, RequestStream.Element == Request { + ) async throws -> Response where RequestStream.Element == Request { let call = self.channel.makeAsyncClientStreamingCall( path: path, callOptions: callOptions ?? self.defaultCallOptions, @@ -237,9 +248,9 @@ extension GRPCClient { } public func performAsyncClientStreamingCall< - Request: GRPCPayload, - Response: GRPCPayload, - RequestStream + Request: GRPCPayload & Sendable, + Response: GRPCPayload & Sendable, + RequestStream: AsyncSequence & Sendable >( path: String, requests: RequestStream, @@ -247,8 +258,7 @@ extension GRPCClient { interceptors: [ClientInterceptor] = [], requestType: Request.Type = Request.self, responseType: Response.Type = Response.self - ) async throws -> Response - where RequestStream: AsyncSequence, RequestStream.Element == Request { + ) async throws -> Response where RequestStream.Element == Request { let call = self.channel.makeAsyncClientStreamingCall( path: path, callOptions: callOptions ?? self.defaultCallOptions, @@ -258,9 +268,9 @@ extension GRPCClient { } public func performAsyncClientStreamingCall< - Request: SwiftProtobuf.Message, - Response: SwiftProtobuf.Message, - RequestStream + Request: SwiftProtobuf.Message & Sendable, + Response: SwiftProtobuf.Message & Sendable, + RequestStream: Sequence >( path: String, requests: RequestStream, @@ -268,8 +278,7 @@ extension GRPCClient { interceptors: [ClientInterceptor] = [], requestType: Request.Type = Request.self, responseType: Response.Type = Response.self - ) async throws -> Response - where RequestStream: Sequence, RequestStream.Element == Request { + ) async throws -> Response where RequestStream.Element == Request { let call = self.channel.makeAsyncClientStreamingCall( path: path, callOptions: callOptions ?? self.defaultCallOptions, @@ -279,9 +288,9 @@ extension GRPCClient { } public func performAsyncClientStreamingCall< - Request: GRPCPayload, - Response: GRPCPayload, - RequestStream + Request: GRPCPayload & Sendable, + Response: GRPCPayload & Sendable, + RequestStream: Sequence >( path: String, requests: RequestStream, @@ -289,8 +298,7 @@ extension GRPCClient { interceptors: [ClientInterceptor] = [], requestType: Request.Type = Request.self, responseType: Response.Type = Response.self - ) async throws -> Response - where RequestStream: Sequence, RequestStream.Element == Request { + ) async throws -> Response where RequestStream.Element == Request { let call = self.channel.makeAsyncClientStreamingCall( path: path, callOptions: callOptions ?? self.defaultCallOptions, @@ -300,8 +308,8 @@ extension GRPCClient { } public func performAsyncBidirectionalStreamingCall< - Request: SwiftProtobuf.Message, - Response: SwiftProtobuf.Message, + Request: SwiftProtobuf.Message & Sendable, + Response: SwiftProtobuf.Message & Sendable, RequestStream: AsyncSequence >( path: String, @@ -321,8 +329,8 @@ extension GRPCClient { } public func performAsyncBidirectionalStreamingCall< - Request: GRPCPayload, - Response: GRPCPayload, + Request: GRPCPayload & Sendable, + Response: GRPCPayload & Sendable, RequestStream: AsyncSequence >( path: String, @@ -342,8 +350,8 @@ extension GRPCClient { } public func performAsyncBidirectionalStreamingCall< - Request: SwiftProtobuf.Message, - Response: SwiftProtobuf.Message, + Request: SwiftProtobuf.Message & Sendable, + Response: SwiftProtobuf.Message & Sendable, RequestStream: Sequence >( path: String, @@ -352,8 +360,7 @@ extension GRPCClient { interceptors: [ClientInterceptor] = [], requestType: Request.Type = Request.self, responseType: Response.Type = Response.self - ) -> GRPCAsyncResponseStream - where RequestStream.Element == Request { + ) -> GRPCAsyncResponseStream where RequestStream.Element == Request { let call = self.channel.makeAsyncBidirectionalStreamingCall( path: path, callOptions: callOptions ?? self.defaultCallOptions, @@ -363,8 +370,8 @@ extension GRPCClient { } public func performAsyncBidirectionalStreamingCall< - Request: GRPCPayload, - Response: GRPCPayload, + Request: GRPCPayload & Sendable, + Response: GRPCPayload & Sendable, RequestStream: Sequence >( path: String, @@ -373,8 +380,7 @@ extension GRPCClient { interceptors: [ClientInterceptor] = [], requestType: Request.Type = Request.self, responseType: Response.Type = Response.self - ) -> GRPCAsyncResponseStream - where RequestStream.Element == Request { + ) -> GRPCAsyncResponseStream where RequestStream.Element == Request { let call = self.channel.makeAsyncBidirectionalStreamingCall( path: path, callOptions: callOptions ?? self.defaultCallOptions, @@ -387,11 +393,14 @@ extension GRPCClient { @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) extension GRPCClient { @inlinable - internal func perform( + internal func perform< + Request: Sendable, + Response: Sendable, + RequestStream: AsyncSequence & Sendable + >( _ call: GRPCAsyncClientStreamingCall, with requests: RequestStream - ) async throws -> Response - where RequestStream: AsyncSequence, RequestStream.Element == Request { + ) async throws -> Response where RequestStream.Element == Request { // We use a detached task because we use cancellation to signal early, but successful exit. let requestsTask = Task.detached { try Task.checkCancellation() @@ -420,12 +429,14 @@ extension GRPCClient { } @inlinable - internal func perform( + internal func perform< + Request: Sendable, + Response: Sendable, + RequestStream: AsyncSequence & Sendable + >( _ call: GRPCAsyncBidirectionalStreamingCall, with requests: RequestStream - ) - -> GRPCAsyncResponseStream - where RequestStream: AsyncSequence, RequestStream.Element == Request { + ) -> GRPCAsyncResponseStream where RequestStream.Element == Request { Task { try await withTaskCancellationHandler { try Task.checkCancellation() diff --git a/Sources/GRPC/AsyncAwaitSupport/PassthroughMessageSequence.swift b/Sources/GRPC/AsyncAwaitSupport/PassthroughMessageSequence.swift index 2dacee55e..31f384a8d 100644 --- a/Sources/GRPC/AsyncAwaitSupport/PassthroughMessageSequence.swift +++ b/Sources/GRPC/AsyncAwaitSupport/PassthroughMessageSequence.swift @@ -55,4 +55,9 @@ internal struct PassthroughMessageSequence: AsyncSequen } } +@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) +extension PassthroughMessageSequence: Sendable where Element: Sendable {} +@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) +extension PassthroughMessageSequence.Iterator: Sendable where Element: Sendable {} + #endif // compiler(>=5.6) diff --git a/Sources/GRPC/AsyncAwaitSupport/PassthroughMessageSource.swift b/Sources/GRPC/AsyncAwaitSupport/PassthroughMessageSource.swift index 963286558..82b04ced7 100644 --- a/Sources/GRPC/AsyncAwaitSupport/PassthroughMessageSource.swift +++ b/Sources/GRPC/AsyncAwaitSupport/PassthroughMessageSource.swift @@ -160,4 +160,8 @@ internal final class PassthroughMessageSource { } } +@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) +// @unchecked is ok: mutable state is accessed/modified via a lock. +extension PassthroughMessageSource: @unchecked Sendable where Element: Sendable {} + #endif // compiler(>=5.6) diff --git a/Sources/GRPC/ClientCalls/Call.swift b/Sources/GRPC/ClientCalls/Call.swift index b847f3098..9244a1687 100644 --- a/Sources/GRPC/ClientCalls/Call.swift +++ b/Sources/GRPC/ClientCalls/Call.swift @@ -37,7 +37,7 @@ import protocol SwiftProtobuf.Message /// /// Callers are not able to create `Call` objects directly, rather they must be created via an /// object conforming to `GRPCChannel` such as `ClientConnection`. -public class Call { +public final class Call { @usableFromInline internal enum State { /// Idle, waiting to be invoked. @@ -417,3 +417,8 @@ extension Call { self._send(.metadata(self.options.customMetadata), promise: nil) } } + +#if compiler(>=5.6) +// @unchecked is ok: all mutable state is accessed/modified from the appropriate event loop. +extension Call: @unchecked Sendable where Request: Sendable, Response: Sendable {} +#endif diff --git a/Sources/GRPC/ClientCalls/ResponseContainers.swift b/Sources/GRPC/ClientCalls/ResponseContainers.swift index c34e2d6d2..e20e14fed 100644 --- a/Sources/GRPC/ClientCalls/ResponseContainers.swift +++ b/Sources/GRPC/ClientCalls/ResponseContainers.swift @@ -190,3 +190,9 @@ extension Error { } } } + +#if compiler(>=5.6) +// @unchecked is ok: all mutable state is accessed/modified from an appropriate event loop. +extension UnaryResponseParts: @unchecked Sendable where Response: Sendable {} +extension StreamingResponseParts: @unchecked Sendable where Response: Sendable {} +#endif diff --git a/Sources/protoc-gen-grpc-swift/Generator-Client+AsyncAwait.swift b/Sources/protoc-gen-grpc-swift/Generator-Client+AsyncAwait.swift index c11970038..967b81344 100644 --- a/Sources/protoc-gen-grpc-swift/Generator-Client+AsyncAwait.swift +++ b/Sources/protoc-gen-grpc-swift/Generator-Client+AsyncAwait.swift @@ -155,7 +155,10 @@ extension Generator { let streamsResponses = [.serverStreaming, .bidirectionalStreaming].contains(rpcType) let streamsRequests = [.clientStreaming, .bidirectionalStreaming].contains(rpcType) - let sequenceProtocols = streamsRequests ? ["Sequence", "AsyncSequence"] : [nil] + // (protocol, requires sendable) + let sequenceProtocols: [(String, Bool)?] = streamsRequests + ? [("Sequence", false), ("AsyncSequence", true)] + : [nil] for (j, sequenceProtocol) in sequenceProtocols.enumerated() { // Print a new line if this is not the first function in the extension. @@ -170,8 +173,13 @@ extension Generator { let returnType = streamsResponses ? Types.responseStream(of: self.methodOutputName) : self.methodOutputName - let maybeWhereClause = sequenceProtocol.map { - "where RequestStream: \($0), RequestStream.Element == \(self.methodInputName)" + let maybeWhereClause = sequenceProtocol.map { protocolName, mustBeSendable -> String in + let constraints = [ + "RequestStream: \(protocolName)" + (mustBeSendable ? " & Sendable" : ""), + "RequestStream.Element == \(self.methodInputName)", + ] + + return "where " + constraints.joined(separator: ", ") } self.printFunction( name: functionName, diff --git a/Tests/GRPCTests/Codegen/Normalization/normalization.grpc.swift b/Tests/GRPCTests/Codegen/Normalization/normalization.grpc.swift index 00945c23b..112d29900 100644 --- a/Tests/GRPCTests/Codegen/Normalization/normalization.grpc.swift +++ b/Tests/GRPCTests/Codegen/Normalization/normalization.grpc.swift @@ -500,7 +500,7 @@ extension Normalization_NormalizationAsyncClientProtocol { internal func ClientStreaming( _ requests: RequestStream, callOptions: CallOptions? = nil - ) async throws -> Normalization_FunctionName where RequestStream: AsyncSequence, RequestStream.Element == SwiftProtobuf.Google_Protobuf_Empty { + ) async throws -> Normalization_FunctionName where RequestStream: AsyncSequence & Sendable, RequestStream.Element == SwiftProtobuf.Google_Protobuf_Empty { return try await self.performAsyncClientStreamingCall( path: Normalization_NormalizationClientMetadata.Methods.ClientStreaming.path, requests: requests, @@ -524,7 +524,7 @@ extension Normalization_NormalizationAsyncClientProtocol { internal func clientStreaming( _ requests: RequestStream, callOptions: CallOptions? = nil - ) async throws -> Normalization_FunctionName where RequestStream: AsyncSequence, RequestStream.Element == SwiftProtobuf.Google_Protobuf_Empty { + ) async throws -> Normalization_FunctionName where RequestStream: AsyncSequence & Sendable, RequestStream.Element == SwiftProtobuf.Google_Protobuf_Empty { return try await self.performAsyncClientStreamingCall( path: Normalization_NormalizationClientMetadata.Methods.clientStreaming.path, requests: requests, @@ -548,7 +548,7 @@ extension Normalization_NormalizationAsyncClientProtocol { internal func BidirectionalStreaming( _ requests: RequestStream, callOptions: CallOptions? = nil - ) -> GRPCAsyncResponseStream where RequestStream: AsyncSequence, RequestStream.Element == SwiftProtobuf.Google_Protobuf_Empty { + ) -> GRPCAsyncResponseStream where RequestStream: AsyncSequence & Sendable, RequestStream.Element == SwiftProtobuf.Google_Protobuf_Empty { return self.performAsyncBidirectionalStreamingCall( path: Normalization_NormalizationClientMetadata.Methods.BidirectionalStreaming.path, requests: requests, @@ -572,7 +572,7 @@ extension Normalization_NormalizationAsyncClientProtocol { internal func bidirectionalStreaming( _ requests: RequestStream, callOptions: CallOptions? = nil - ) -> GRPCAsyncResponseStream where RequestStream: AsyncSequence, RequestStream.Element == SwiftProtobuf.Google_Protobuf_Empty { + ) -> GRPCAsyncResponseStream where RequestStream: AsyncSequence & Sendable, RequestStream.Element == SwiftProtobuf.Google_Protobuf_Empty { return self.performAsyncBidirectionalStreamingCall( path: Normalization_NormalizationClientMetadata.Methods.bidirectionalStreaming.path, requests: requests,