Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add explicit Sendable unavailability and add missing Sendable conformances #2578

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public struct NIOAsyncChannelInboundStream<Inbound: Sendable>: Sendable {
typealias Producer = NIOThrowingAsyncSequenceProducer<Inbound, Error, NIOAsyncSequenceProducerBackPressureStrategies.HighLowWatermark, NIOAsyncChannelInboundStreamChannelHandlerProducerDelegate>

/// A source used for driving a ``NIOAsyncChannelInboundStream`` during tests.
public struct TestSource {
public struct TestSource: Sendable{
@usableFromInline
internal let continuation: AsyncThrowingStream<Inbound, Error>.Continuation

Expand Down
3 changes: 3 additions & 0 deletions Sources/NIOCore/AsyncChannel/AsyncChannelOutboundWriter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -162,3 +162,6 @@ public struct NIOAsyncChannelOutboundWriter<OutboundOut: Sendable>: Sendable {

@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)
extension NIOAsyncChannelOutboundWriter.TestSink: Sendable {}

@available(*, unavailable)
extension NIOAsyncChannelOutboundWriter.TestSink.AsyncIterator: Sendable { }
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ extension NIOAsyncSequenceProducer {
}

/// The result of a call to ``NIOAsyncSequenceProducer/Source/yield(_:)``.
public enum YieldResult: Hashable {
public enum YieldResult: Hashable, Sendable {
/// Indicates that the caller should produce more elements for now. The delegate's ``NIOAsyncSequenceProducerDelegate/produceMore()``
/// will **NOT** get called, since the demand was already signalled through this ``NIOAsyncSequenceProducer/Source/YieldResult``.
case produceMore
Expand Down
5 changes: 4 additions & 1 deletion Sources/NIOCore/AsyncSequences/NIOAsyncWriter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ public struct NIOAsyncWriter<
/// This struct contains two properties:
/// 1. The ``sink`` which should be retained by the consumer and is used to set the writability.
/// 2. The ``writer`` which is the actual ``NIOAsyncWriter`` and should be passed to the producer.
public struct NewWriter {
public struct NewWriter: @unchecked Sendable {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unsure about that one the Sink is not Sendable right now because we expect it to be only held in one isolation domain at any given time even though it is fully thread-safe. We certainly can't make this type unchecked Sendable then. So we either make the Sink Sendable as well or don't make this one Sendable

/// The ``sink`` which **MUST** be retained by the consumer and is used to set the writability.
public let sink: Sink
/// The ``writer`` which is the actual ``NIOAsyncWriter`` and should be passed to the producer.
Expand Down Expand Up @@ -376,6 +376,9 @@ extension NIOAsyncWriter {
}
}

@available(*, unavailable)
extension NIOAsyncWriter.Sink: Sendable { }

@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)
extension NIOAsyncWriter {
/// This is the underlying storage of the writer. The goal of this is to synchronize the access to all state.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,7 @@ extension NIOThrowingAsyncSequenceProducer {
}

/// The result of a call to ``NIOThrowingAsyncSequenceProducer/Source/yield(_:)``.
public enum YieldResult: Hashable {
public enum YieldResult: Hashable, Sendable {
/// Indicates that the caller should produce more elements.
case produceMore
/// Indicates that the caller should stop producing elements.
Expand Down
2 changes: 1 addition & 1 deletion Sources/NIOCore/BSDSocketAPI.swift
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ let SO_TIMESTAMP = CNIOLinux_SO_TIMESTAMP
let SO_RCVTIMEO = CNIOLinux_SO_RCVTIMEO
#endif

public enum NIOBSDSocket {
public enum NIOBSDSocket: Sendable{
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we can make a socket Sendable it is the same as FileHandle

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is just a namespace.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah good catch. Then my comments from below apply. Should we really make namespaces Sendable?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't see any reason to do so.

#if os(Windows)
public typealias Handle = SOCKET
#else
Expand Down
2 changes: 1 addition & 1 deletion Sources/NIOCore/Channel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -378,7 +378,7 @@ extension ChannelError: Equatable { }
/// The removal of a `ChannelHandler` using `ChannelPipeline.removeHandler` has been attempted more than once.
public struct NIOAttemptedToRemoveHandlerMultipleTimesError: Error {}

public enum DatagramChannelError {
public enum DatagramChannelError: Sendable {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is just a namespace right? We probably shouldn't make it Sendable right now

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, I will mark it then as non-sendable. I don't think it really matters though.

public struct WriteOnUnconnectedSocketWithoutAddress: Error {
public init() {}
}
Expand Down
4 changes: 2 additions & 2 deletions Sources/NIOCore/ChannelOption.swift
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ public typealias ConnectTimeoutOption = ChannelOptions.Types.ConnectTimeoutOptio
public typealias AllowRemoteHalfClosureOption = ChannelOptions.Types.AllowRemoteHalfClosureOption

extension ChannelOptions {
public enum Types {
public enum Types: Sendable {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here. This is just a namespace right?


/// `SocketOption` allows users to specify configuration settings that are directly applied to the underlying socket file descriptor.
///
Expand Down Expand Up @@ -291,7 +291,7 @@ extension ChannelOptions {
}

/// Provides `ChannelOption`s to be used with a `Channel`, `Bootstrap` or `ServerBootstrap`.
public struct ChannelOptions {
public struct ChannelOptions: Sendable {
#if !os(Windows)
public static let socket = { (level: SocketOptionLevel, name: SocketOptionName) -> Types.SocketOption in
.init(level: NIOBSDSocket.OptionLevel(rawValue: CInt(level)), name: NIOBSDSocket.Option(rawValue: CInt(name)))
Expand Down
3 changes: 3 additions & 0 deletions Sources/NIOCore/FileHandle.swift
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,9 @@ public final class NIOFileHandle: FileDescriptor {
}
}

@available(*, unavailable)
extension NIOFileHandle: Sendable { }

extension NIOFileHandle {
/// `Mode` represents file access modes.
public struct Mode: OptionSet, Sendable {
Expand Down
2 changes: 1 addition & 1 deletion Sources/NIOCore/GlobalSingletons.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ import Musl
/// `NIOSingletons.singletonsEnabledSuggestion = false`. All singleton-creating facilities should check
/// this setting and if `false` restrain from creating any global singleton resources. Please note that disabling the
/// global singletons will lead to a crash if _any_ code attempts to use any of the singletons.
public enum NIOSingletons {
public enum NIOSingletons: Sendable {
}

extension NIOSingletons {
Expand Down
2 changes: 1 addition & 1 deletion Sources/NIOCore/IO.swift
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ import Darwin
/// An `Error` for an IO operation.
public struct IOError: Swift.Error {
@available(*, deprecated, message: "NIO no longer uses FailureDescription.")
public enum FailureDescription {
public enum FailureDescription : Sendable{
case function(StaticString)
case reason(String)
}
Expand Down
2 changes: 1 addition & 1 deletion Sources/NIOCore/IPProtocol.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
/// called "Protocol" to identify the next level protocol. This is an 8
/// bit field. In Internet Protocol version 6 (IPv6) [RFC8200], this field
/// is called the "Next Header" field.
public struct NIOIPProtocol: RawRepresentable, Hashable {
public struct NIOIPProtocol: RawRepresentable, Hashable, Sendable {
public typealias RawValue = UInt8
public var rawValue: RawValue

Expand Down
2 changes: 1 addition & 1 deletion Sources/NIOCore/Interfaces.swift
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ private extension ifaddrs {

/// A representation of a single network interface on a system.
@available(*, deprecated, renamed: "NIONetworkDevice")
public final class NIONetworkInterface {
public final class NIONetworkInterface: Sendable{
// This is a class because in almost all cases this will carry
// four structs that are backed by classes, and so will incur 4
// refcount operations each time it is copied.
Expand Down
8 changes: 8 additions & 0 deletions Sources/NIOCore/UniversalBootstrapSupport.swift
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,10 @@ public struct NIOClientTCPBootstrap {
}
}

@available(*, unavailable)
extension NIOClientTCPBootstrap: Sendable { }


public protocol NIOClientTLSProvider {
associatedtype Bootstrap

Expand All @@ -261,3 +265,7 @@ public struct NIOInsecureNoTLS<Bootstrap: NIOClientTCPBootstrapProtocol>: NIOCli
fatalError("NIOInsecureNoTLS cannot enable TLS.")
}
}

@available(*, unavailable)
extension NIOInsecureNoTLS: Sendable { }

2 changes: 1 addition & 1 deletion Sources/NIOCore/Utilities.swift
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ final class Box<T> {

extension Box: Sendable where T: Sendable {}

public enum System {
public enum System: Sendable {
/// A utility function that returns an estimate of the number of *logical* cores
/// on the system available for use.
///
Expand Down
3 changes: 2 additions & 1 deletion Sources/NIOEmbedded/AsyncTestingChannel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -611,7 +611,7 @@ public final class NIOAsyncTestingChannel: Channel {
}
}

public struct SynchronousOptions: NIOSynchronousChannelOptions {
public struct SynchronousOptions: NIOSynchronousChannelOptions, Sendable {
@usableFromInline
internal let channel: NIOAsyncTestingChannel

Expand All @@ -637,6 +637,7 @@ public final class NIOAsyncTestingChannel: Channel {
}
}


// MARK: Unchecked sendable
//
// Both of these types are unchecked Sendable because strictly, they aren't. This is
Expand Down
8 changes: 8 additions & 0 deletions Sources/NIOEmbedded/Embedded.swift
Original file line number Diff line number Diff line change
Expand Up @@ -857,6 +857,14 @@ public final class EmbeddedChannel: Channel {
}
}

// Stores NIOAny which isn't Sendable
@available(*, unavailable)
extension EmbeddedChannel.LeftOverState: Sendable { }

// Stores NIOAny which isn't Sendable
@available(*, unavailable)
extension EmbeddedChannel.BufferState: Sendable { }

extension EmbeddedChannel {
public struct SynchronousOptions: NIOSynchronousChannelOptions {
@usableFromInline
Expand Down
2 changes: 1 addition & 1 deletion Sources/NIOPosix/BSDSocketAPICommon.swift
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ extension NIOBSDSocket {
/// They aren't necessarily protocols in their own right: for example, ``mptcp``
/// is not. They act to modify the socket type instead: thus, ``mptcp`` acts
/// to modify `SOCK_STREAM` to ask for ``mptcp`` support.
public struct ProtocolSubtype: RawRepresentable, Hashable {
public struct ProtocolSubtype: RawRepresentable, Hashable, Sendable {
public typealias RawValue = CInt

/// The underlying value of the protocol subtype.
Expand Down
16 changes: 8 additions & 8 deletions Sources/NIOPosix/Bootstrap.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2269,8 +2269,8 @@ extension NIOPipeBootstrap {
let channelOptions = self._channelOptions

let channel: PipeChannel
let inputFileHandle: NIOFileHandle?
let outputFileHandle: NIOFileHandle?
let inputFileHandle: NIOLoopBound<NIOFileHandle?>
let outputFileHandle: NIOLoopBound<NIOFileHandle?>
do {
if let input = input {
try self.validateFileDescriptorIsNotAFile(input)
Expand All @@ -2279,12 +2279,12 @@ extension NIOPipeBootstrap {
try self.validateFileDescriptorIsNotAFile(output)
}

inputFileHandle = input.flatMap { NIOFileHandle(descriptor: $0) }
outputFileHandle = output.flatMap { NIOFileHandle(descriptor: $0) }
inputFileHandle = NIOLoopBound(input.flatMap { NIOFileHandle(descriptor: $0) }, eventLoop: eventLoop)
outputFileHandle = NIOLoopBound(output.flatMap { NIOFileHandle(descriptor: $0) }, eventLoop: eventLoop)
channel = try PipeChannel(
eventLoop: eventLoop as! SelectableEventLoop,
inputPipe: inputFileHandle,
outputPipe: outputFileHandle
inputPipe: inputFileHandle.value,
outputPipe: outputFileHandle.value
)
} catch {
return eventLoop.makeFailedFuture(error)
Expand All @@ -2302,10 +2302,10 @@ extension NIOPipeBootstrap {
channel.registerAlreadyConfigured0(promise: promise)
return promise.futureResult.map { result }
}.flatMap { result -> EventLoopFuture<ChannelInitializerResult> in
if inputFileHandle == nil {
if inputFileHandle.value == nil {
return channel.close(mode: .input).map { result }
}
if outputFileHandle == nil {
if outputFileHandle.value == nil {
return channel.close(mode: .output).map { result }
}
return channel.selectableEventLoop.makeSucceededFuture(result)
Expand Down
2 changes: 1 addition & 1 deletion Sources/NIOPosix/NIOThreadPool.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import NIOCore
import NIOConcurrencyHelpers

/// Errors that may be thrown when executing work on a `NIOThreadPool`
public enum NIOThreadPoolError {
public enum NIOThreadPoolError: Sendable{

/// The `NIOThreadPool` was not active.
public struct ThreadPoolInactive: Error {
Expand Down
2 changes: 1 addition & 1 deletion Sources/NIOPosix/NonBlockingFileIO.swift
Original file line number Diff line number Diff line change
Expand Up @@ -697,7 +697,7 @@ public struct NonBlockingFileIO: Sendable {

#if !os(Windows)
/// A `NIODirectoryEntry` represents a single directory entry.
public struct NIODirectoryEntry: Hashable {
public struct NIODirectoryEntry: Hashable, Sendable {
// File number of entry
public var ino: UInt64
// File type
Expand Down
2 changes: 2 additions & 0 deletions Sources/_NIODataStructures/_TinyArray.swift
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,8 @@ extension _TinyArray: RandomAccessCollection {
}
}

extension _TinyArray.Iterator: Sendable where Element: Sendable {}

extension _TinyArray {
@inlinable
public init(_ elements: some Sequence<Element>) {
Expand Down