-
Notifications
You must be signed in to change notification settings - Fork 117
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
Adopt Sendable
#621
Adopt Sendable
#621
Conversation
647569b
to
7d1ca5c
Compare
@@ -647,4 +647,47 @@ extension AsyncSequence where Element == ByteBuffer { | |||
} | |||
} | |||
} | |||
|
|||
struct AnySendableSequence<Element>: @unchecked Sendable { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have used AnySequence
and AnyCollection
to force a specific overload of the HTTPClientRequest.Body.bytes
method. The Sequence/Collection passed to these methods need to be Sendable
now but AnySequence
and AnyCollection
are not Sendable
. AnySendableSequence
and AnySendableCollection
are simple wrappers of their non-Sendable
counterparts.
@@ -541,16 +541,26 @@ final class TransactionTests: XCTestCase { | |||
// tasks. Since we want to wait for things to happen in tests, we need to `async let`, which creates | |||
// implicit tasks. Therefore we need to wrap our iterator struct. | |||
@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) | |||
actor SharedIterator<Iterator: AsyncIteratorProtocol> { | |||
private var iterator: Iterator | |||
actor SharedIterator<Wrapped: AsyncSequence> where Wrapped.Element: Sendable { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wrapped.Element: Sendable
constraint necessary in Swift 5.8 because return types of actor isolated functions need to be Sendable
since SE-0338
and Wrapped.Element
is the return type of next()
.
|
||
init(_ iterator: Iterator) { | ||
self.iterator = iterator | ||
init(_ sequence: Wrapped) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Iterator is now created in the actor instead of outside the actor. This is necessary because AsyncIterator
s are often non-Sendable
but AsyncSequence
s themself are often Sendable
. Passing in an non-Sendable
value produces a warning with Swift 5.8 (Swift Development Snapshot 2022-08-18 (a)) e.g.:
actor Actor<Element> {
init(_ element: Element) {}
}
class NonSendableClass {}
let nonSendable = NonSendableClass()
_ = Actor(nonSendable) // warning: Non-sendable type 'NonSendableClass' passed in call to nonisolated initializer 'init(_:)' cannot cross actor boundary
I'm not 100% sure if this warning is correct and need to think a bit more about this warning. However, the change doesn't hurt either.
precondition(self.nextCallInProgress == false) | ||
self.nextCallInProgress = true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This construct is quite unsafe and doesn't support reentrancy. nextCallInProgress
makes it a bit safe and will crash if next is called while another call to next is still in progress.
API breakages are all false positives. Adding a
|
Updates
swift-nio
,swift-nio-ssl
andswift-nio-extras
to the latest released version to use the latestSendable
changes in these libraries.