From 16ca28f31c300f92a8225b4901a40366f70662ea Mon Sep 17 00:00:00 2001 From: Daniel Tartaglia Date: Wed, 10 Jul 2024 13:25:54 -0400 Subject: [PATCH 01/11] Allow VirtualTimeScheduler to run on any thread as long as critical methods are all called on the same thread. --- RxSwift/Schedulers/VirtualTimeScheduler.swift | 31 ++++++++++++++----- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/RxSwift/Schedulers/VirtualTimeScheduler.swift b/RxSwift/Schedulers/VirtualTimeScheduler.swift index 4f55d29d7..b54b6144c 100644 --- a/RxSwift/Schedulers/VirtualTimeScheduler.swift +++ b/RxSwift/Schedulers/VirtualTimeScheduler.swift @@ -24,6 +24,8 @@ open class VirtualTimeScheduler private var nextId = 0 + private var thread: Thread! + /// - returns: Current time. public var now: RxTime { self.converter.convertFromVirtualTime(self.clock) @@ -106,7 +108,10 @@ open class VirtualTimeScheduler - returns: The disposable object used to cancel the scheduled action (best effort). */ public func scheduleAbsoluteVirtual(_ state: StateType, time: VirtualTime, action: @escaping (StateType) -> Disposable) -> Disposable { - MainScheduler.ensureExecutingOnScheduler() + guard thread == nil || Thread.current == thread else { + rxFatalError("Executing on the wrong thread. Please ensure all work on the same thread.") + } + thread = Thread.current let compositeDisposable = CompositeDisposable() @@ -130,12 +135,15 @@ open class VirtualTimeScheduler /// Starts the virtual time scheduler. public func start() { - MainScheduler.ensureExecutingOnScheduler() - if self.running { return } + guard thread == nil || Thread.current == thread else { + rxFatalError("Executing on the wrong thread. Please ensure all work on the same thread.") + } + thread = Thread.current + self.running = true repeat { guard let next = self.findNext() else { @@ -170,12 +178,15 @@ open class VirtualTimeScheduler /// /// - parameter virtualTime: Absolute time to advance the scheduler's clock to. public func advanceTo(_ virtualTime: VirtualTime) { - MainScheduler.ensureExecutingOnScheduler() - if self.running { fatalError("Scheduler is already running") } + guard thread == nil || Thread.current == thread else { + rxFatalError("Executing on the wrong thread. Please ensure all work on the same thread.") + } + thread = Thread.current + self.running = true repeat { guard let next = self.findNext() else { @@ -199,7 +210,10 @@ open class VirtualTimeScheduler /// Advances the scheduler's clock by the specified relative time. public func sleep(_ virtualInterval: VirtualTimeInterval) { - MainScheduler.ensureExecutingOnScheduler() + guard thread == nil || Thread.current == thread else { + rxFatalError("Executing on the wrong thread. Please ensure all work on the same thread.") + } + thread = Thread.current let sleepTo = self.converter.offsetVirtualTime(self.clock, offset: virtualInterval) if self.converter.compareVirtualTime(sleepTo, self.clock).lessThen { @@ -211,7 +225,10 @@ open class VirtualTimeScheduler /// Stops the virtual time scheduler. public func stop() { - MainScheduler.ensureExecutingOnScheduler() + guard thread == nil || Thread.current == thread else { + rxFatalError("Executing on the wrong thread. Please ensure all work on the same thread.") + } + thread = Thread.current self.running = false } From f63eb1361492955380e3c93862fe26449daa9182 Mon Sep 17 00:00:00 2001 From: Daniel Tartaglia Date: Wed, 17 Jul 2024 11:17:02 -0400 Subject: [PATCH 02/11] Move thread assignment to init method. --- RxSwift/Schedulers/VirtualTimeScheduler.swift | 39 +++++++------------ 1 file changed, 13 insertions(+), 26 deletions(-) diff --git a/RxSwift/Schedulers/VirtualTimeScheduler.swift b/RxSwift/Schedulers/VirtualTimeScheduler.swift index b54b6144c..5d2d61e14 100644 --- a/RxSwift/Schedulers/VirtualTimeScheduler.swift +++ b/RxSwift/Schedulers/VirtualTimeScheduler.swift @@ -24,7 +24,7 @@ open class VirtualTimeScheduler private var nextId = 0 - private var thread: Thread! + private let thread: Thread /// - returns: Current time. public var now: RxTime { @@ -43,6 +43,7 @@ open class VirtualTimeScheduler self.currentClock = initialClock self.running = false self.converter = converter + self.thread = Thread.current self.schedulerQueue = PriorityQueue(hasHigherPriority: { switch converter.compareVirtualTime($0.time, $1.time) { case .lessThan: @@ -108,11 +109,7 @@ open class VirtualTimeScheduler - returns: The disposable object used to cancel the scheduled action (best effort). */ public func scheduleAbsoluteVirtual(_ state: StateType, time: VirtualTime, action: @escaping (StateType) -> Disposable) -> Disposable { - guard thread == nil || Thread.current == thread else { - rxFatalError("Executing on the wrong thread. Please ensure all work on the same thread.") - } - thread = Thread.current - + ensusreRunningOnCorrectThread() let compositeDisposable = CompositeDisposable() let item = VirtualSchedulerItem(action: { @@ -139,11 +136,7 @@ open class VirtualTimeScheduler return } - guard thread == nil || Thread.current == thread else { - rxFatalError("Executing on the wrong thread. Please ensure all work on the same thread.") - } - thread = Thread.current - + ensusreRunningOnCorrectThread() self.running = true repeat { guard let next = self.findNext() else { @@ -182,11 +175,7 @@ open class VirtualTimeScheduler fatalError("Scheduler is already running") } - guard thread == nil || Thread.current == thread else { - rxFatalError("Executing on the wrong thread. Please ensure all work on the same thread.") - } - thread = Thread.current - + ensusreRunningOnCorrectThread() self.running = true repeat { guard let next = self.findNext() else { @@ -210,11 +199,7 @@ open class VirtualTimeScheduler /// Advances the scheduler's clock by the specified relative time. public func sleep(_ virtualInterval: VirtualTimeInterval) { - guard thread == nil || Thread.current == thread else { - rxFatalError("Executing on the wrong thread. Please ensure all work on the same thread.") - } - thread = Thread.current - + ensusreRunningOnCorrectThread() let sleepTo = self.converter.offsetVirtualTime(self.clock, offset: virtualInterval) if self.converter.compareVirtualTime(sleepTo, self.clock).lessThen { fatalError("Can't sleep to past.") @@ -225,11 +210,7 @@ open class VirtualTimeScheduler /// Stops the virtual time scheduler. public func stop() { - guard thread == nil || Thread.current == thread else { - rxFatalError("Executing on the wrong thread. Please ensure all work on the same thread.") - } - thread = Thread.current - + ensusreRunningOnCorrectThread() self.running = false } @@ -238,6 +219,12 @@ open class VirtualTimeScheduler _ = Resources.decrementTotal() } #endif + + private func ensusreRunningOnCorrectThread() { + guard Thread.current == thread else { + rxFatalError("Executing on the wrong thread. Please ensure all work on the same thread.") + } + } } // MARK: description From 9ce63f8b37b6b3c7a8a65edde5b3f76ab48cfd83 Mon Sep 17 00:00:00 2001 From: Andrei Ardelean <> Date: Mon, 21 Oct 2024 13:19:58 +0300 Subject: [PATCH 03/11] Make closures sendable --- Platform/RecursiveLock.swift | 2 +- .../Traits/Driver/Driver+Subscription.swift | 12 ++--- .../SharedSequence+Operators.swift | 26 ++++----- .../Traits/Signal/Signal+Subscription.swift | 12 ++--- RxSwift/AnyObserver.swift | 2 +- RxSwift/Binder.swift | 7 +-- RxSwift/Concurrency/AsyncLock.swift | 2 +- RxSwift/Disposables/AnonymousDisposable.swift | 4 +- RxSwift/Disposables/ScheduledDisposable.swift | 2 +- RxSwift/ImmediateSchedulerType.swift | 4 +- RxSwift/Observable+Concurrency.swift | 2 +- RxSwift/ObservableType+Extensions.swift | 22 ++++---- RxSwift/Observables/Amb.swift | 4 +- RxSwift/Observables/Catch.swift | 6 +-- .../CombineLatest+Collection.swift | 4 +- RxSwift/Observables/CombineLatest+arity.swift | 28 +++++----- RxSwift/Observables/CombineLatest.swift | 2 +- RxSwift/Observables/CompactMap.swift | 6 +-- RxSwift/Observables/Create.swift | 4 +- RxSwift/Observables/Debounce.swift | 1 + RxSwift/Observables/Deferred.swift | 4 +- RxSwift/Observables/Delay.swift | 1 + .../Observables/DistinctUntilChanged.swift | 10 ++-- RxSwift/Observables/Do.swift | 18 +++---- RxSwift/Observables/Filter.swift | 6 +-- RxSwift/Observables/GroupBy.swift | 4 +- RxSwift/Observables/Map.swift | 6 +-- RxSwift/Observables/Merge.swift | 18 +++---- RxSwift/Observables/Multicast.swift | 6 +-- RxSwift/Observables/ObserveOn.swift | 1 + RxSwift/Observables/Reduce.swift | 8 +-- RxSwift/Observables/Scan.swift | 4 +- RxSwift/Observables/SingleAsync.swift | 4 +- RxSwift/Observables/SkipWhile.swift | 6 +-- RxSwift/Observables/Switch.swift | 8 +-- RxSwift/Observables/TakeWithPredicate.swift | 6 +-- RxSwift/Observables/Throttle.swift | 1 + RxSwift/Observables/Using.swift | 6 +-- RxSwift/Observables/WithLatestFrom.swift | 4 +- RxSwift/Observables/Zip+Collection.swift | 4 +- RxSwift/Observables/Zip+arity.swift | 28 +++++----- RxSwift/Observables/Zip.swift | 2 +- RxSwift/ObserverType.swift | 1 + RxSwift/Observers/AnonymousObserver.swift | 2 +- RxSwift/SchedulerType.swift | 8 +-- .../Schedulers/CurrentThreadScheduler.swift | 2 +- .../Internal/DispatchQueueConfiguration.swift | 4 +- .../Schedulers/Internal/ScheduledItem.swift | 2 +- RxSwift/Schedulers/RecursiveScheduler.swift | 10 ++-- .../SchedulerServices+Emulation.swift | 5 +- RxSwift/Schedulers/VirtualTimeScheduler.swift | 10 ++-- .../Infallible+CombineLatest+Collection.swift | 2 +- .../Infallible+CombineLatest+arity.swift | 14 ++--- .../Traits/Infallible/Infallible+Create.swift | 2 +- .../Infallible/Infallible+Operators.swift | 30 +++++------ .../Infallible/Infallible+Zip+arity.swift | 14 ++--- RxSwift/Traits/Infallible/Infallible.swift | 16 +++--- .../PrimitiveSequence/Completable.swift | 34 ++++++------ RxSwift/Traits/PrimitiveSequence/Maybe.swift | 46 ++++++++-------- .../PrimitiveSequence+Concurrency.swift | 10 ++-- .../PrimitiveSequence+Zip+arity.swift | 28 +++++----- .../PrimitiveSequence/PrimitiveSequence.swift | 2 +- RxSwift/Traits/PrimitiveSequence/Single.swift | 54 +++++++++---------- 63 files changed, 306 insertions(+), 297 deletions(-) diff --git a/Platform/RecursiveLock.swift b/Platform/RecursiveLock.swift index 10b9bbb0b..b7363105d 100644 --- a/Platform/RecursiveLock.swift +++ b/Platform/RecursiveLock.swift @@ -9,7 +9,7 @@ import Foundation #if TRACE_RESOURCES - class RecursiveLock: NSRecursiveLock { + class RecursiveLock: NSRecursiveLock, @unchecked Sendable { override init() { _ = Resources.incrementTotal() super.init() diff --git a/RxCocoa/Traits/Driver/Driver+Subscription.swift b/RxCocoa/Traits/Driver/Driver+Subscription.swift index 0b9024c75..c7efd9845 100644 --- a/RxCocoa/Traits/Driver/Driver+Subscription.swift +++ b/RxCocoa/Traits/Driver/Driver+Subscription.swift @@ -157,9 +157,9 @@ extension SharedSequenceConvertibleType where SharingStrategy == DriverSharingSt */ public func drive( with object: Object, - onNext: ((Object, Element) -> Void)? = nil, - onCompleted: ((Object) -> Void)? = nil, - onDisposed: ((Object) -> Void)? = nil + onNext: (@Sendable (Object, Element) -> Void)? = nil, + onCompleted: (@Sendable (Object) -> Void)? = nil, + onDisposed: (@Sendable (Object) -> Void)? = nil ) -> Disposable { MainScheduler.ensureRunningOnMainThread(errorMessage: errorMessage) return self.asObservable().subscribe(with: object, onNext: onNext, onCompleted: onCompleted, onDisposed: onDisposed) @@ -179,9 +179,9 @@ extension SharedSequenceConvertibleType where SharingStrategy == DriverSharingSt - returns: Subscription object used to unsubscribe from the observable sequence. */ public func drive( - onNext: ((Element) -> Void)? = nil, - onCompleted: (() -> Void)? = nil, - onDisposed: (() -> Void)? = nil + onNext: (@Sendable (Element) -> Void)? = nil, + onCompleted: (@Sendable () -> Void)? = nil, + onDisposed: (@Sendable () -> Void)? = nil ) -> Disposable { MainScheduler.ensureRunningOnMainThread(errorMessage: errorMessage) return self.asObservable().subscribe(onNext: onNext, onCompleted: onCompleted, onDisposed: onDisposed) diff --git a/RxCocoa/Traits/SharedSequence/SharedSequence+Operators.swift b/RxCocoa/Traits/SharedSequence/SharedSequence+Operators.swift index 1d53b03d9..cc832b0c7 100644 --- a/RxCocoa/Traits/SharedSequence/SharedSequence+Operators.swift +++ b/RxCocoa/Traits/SharedSequence/SharedSequence+Operators.swift @@ -17,7 +17,7 @@ extension SharedSequenceConvertibleType { - parameter selector: A transform function to apply to each source element. - returns: An observable sequence whose elements are the result of invoking the transform function on each element of source. */ - public func map(_ selector: @escaping (Element) -> Result) -> SharedSequence { + public func map(_ selector: @escaping @Sendable (Element) -> Result) -> SharedSequence { let source = self .asObservable() .map(selector) @@ -35,7 +35,7 @@ extension SharedSequenceConvertibleType { - returns: An observable sequence whose elements are the result of filtering the transform function for each element of the source. */ - public func compactMap(_ selector: @escaping (Element) -> Result?) -> SharedSequence { + public func compactMap(_ selector: @escaping @Sendable (Element) -> Result?) -> SharedSequence { let source = self .asObservable() .compactMap(selector) @@ -51,7 +51,7 @@ extension SharedSequenceConvertibleType { - parameter predicate: A function to test each source element for a condition. - returns: An observable sequence that contains elements from the input sequence that satisfy the condition. */ - public func filter(_ predicate: @escaping (Element) -> Bool) -> SharedSequence { + public func filter(_ predicate: @escaping @Sendable (Element) -> Bool) -> SharedSequence { let source = self .asObservable() .filter(predicate) @@ -92,7 +92,7 @@ extension SharedSequenceConvertibleType { - returns: An observable sequence whose elements are the result of invoking the transform function on each element of source producing an Observable of Observable sequences and that at any point in time produces the elements of the most recent inner observable sequence that has been received. */ - public func flatMapLatest(_ selector: @escaping (Element) -> SharedSequence) + public func flatMapLatest(_ selector: @escaping @Sendable (Element) -> SharedSequence) -> SharedSequence { let source: Observable = self .asObservable() @@ -111,7 +111,7 @@ extension SharedSequenceConvertibleType { - parameter selector: A transform function to apply to element that was observed while no observable is executing in parallel. - returns: An observable sequence whose elements are the result of invoking the one-to-many transform function on each element of the input sequence that was received while no other sequence was being calculated. */ - public func flatMapFirst(_ selector: @escaping (Element) -> SharedSequence) + public func flatMapFirst(_ selector: @escaping @Sendable (Element) -> SharedSequence) -> SharedSequence { let source: Observable = self .asObservable() @@ -134,7 +134,7 @@ extension SharedSequenceConvertibleType { - parameter onDispose: Action to invoke after subscription to source observable has been disposed for any reason. It can be either because sequence terminates for some reason or observer subscription being disposed. - returns: The source sequence with the side-effecting behavior applied. */ - public func `do`(onNext: ((Element) -> Void)? = nil, afterNext: ((Element) -> Void)? = nil, onCompleted: (() -> Void)? = nil, afterCompleted: (() -> Void)? = nil, onSubscribe: (() -> Void)? = nil, onSubscribed: (() -> Void)? = nil, onDispose: (() -> Void)? = nil) + public func `do`(onNext: (@Sendable (Element) -> Void)? = nil, afterNext: (@Sendable (Element) -> Void)? = nil, onCompleted: (@Sendable () -> Void)? = nil, afterCompleted: (@Sendable () -> Void)? = nil, onSubscribe: (@Sendable () -> Void)? = nil, onSubscribed: (@Sendable () -> Void)? = nil, onDispose: (@Sendable () -> Void)? = nil) -> SharedSequence { let source = self.asObservable() .do(onNext: onNext, afterNext: afterNext, onCompleted: onCompleted, afterCompleted: afterCompleted, onSubscribe: onSubscribe, onSubscribed: onSubscribed, onDispose: onDispose) @@ -184,7 +184,7 @@ extension SharedSequenceConvertibleType { - parameter keySelector: A function to compute the comparison key for each element. - returns: An observable sequence only containing the distinct contiguous elements, based on a computed key value, from the source sequence. */ - public func distinctUntilChanged(_ keySelector: @escaping (Element) -> Key) -> SharedSequence { + public func distinctUntilChanged(_ keySelector: @escaping @Sendable (Element) -> Key) -> SharedSequence { let source = self.asObservable() .distinctUntilChanged(keySelector, comparer: { $0 == $1 }) return SharedSequence(source) @@ -196,7 +196,7 @@ extension SharedSequenceConvertibleType { - parameter comparer: Equality comparer for computed key values. - returns: An observable sequence only containing the distinct contiguous elements, based on `comparer`, from the source sequence. */ - public func distinctUntilChanged(_ comparer: @escaping (Element, Element) -> Bool) -> SharedSequence { + public func distinctUntilChanged(_ comparer: @escaping @Sendable (Element, Element) -> Bool) -> SharedSequence { let source = self.asObservable() .distinctUntilChanged({ $0 }, comparer: comparer) return SharedSequence(source) @@ -209,7 +209,7 @@ extension SharedSequenceConvertibleType { - parameter comparer: Equality comparer for computed key values. - returns: An observable sequence only containing the distinct contiguous elements, based on a computed key value and the comparer, from the source sequence. */ - public func distinctUntilChanged(_ keySelector: @escaping (Element) -> K, comparer: @escaping (K, K) -> Bool) -> SharedSequence { + public func distinctUntilChanged(_ keySelector: @escaping @Sendable (Element) -> K, comparer: @escaping @Sendable (K, K) -> Bool) -> SharedSequence { let source = self.asObservable() .distinctUntilChanged(keySelector, comparer: comparer) return SharedSequence(source) @@ -226,7 +226,7 @@ extension SharedSequenceConvertibleType { - parameter selector: A transform function to apply to each element. - returns: An observable sequence whose elements are the result of invoking the one-to-many transform function on each element of the input sequence. */ - public func flatMap(_ selector: @escaping (Element) -> SharedSequence) -> SharedSequence { + public func flatMap(_ selector: @escaping @Sendable (Element) -> SharedSequence) -> SharedSequence { let source = self.asObservable() .flatMap(selector) @@ -398,7 +398,7 @@ extension SharedSequence { - parameter resultSelector: Function to invoke for each series of elements at corresponding indexes in the sources. - returns: An observable sequence containing the result of combining elements of the sources using the specified result selector function. */ - public static func zip(_ collection: Collection, resultSelector: @escaping ([Element]) throws -> Result) -> SharedSequence + public static func zip(_ collection: Collection, resultSelector: @escaping @Sendable ([Element]) throws -> Result) -> SharedSequence where Collection.Element == SharedSequence { let source = Observable.zip(collection.map { $0.asSharedSequence().asObservable() }, resultSelector: resultSelector) return SharedSequence(source) @@ -425,7 +425,7 @@ extension SharedSequence { - parameter resultSelector: Function to invoke whenever any of the sources produces an element. - returns: An observable sequence containing the result of combining elements of the sources using the specified result selector function. */ - public static func combineLatest(_ collection: Collection, resultSelector: @escaping ([Element]) throws -> Result) -> SharedSequence + public static func combineLatest(_ collection: Collection, resultSelector: @escaping @Sendable ([Element]) throws -> Result) -> SharedSequence where Collection.Element == SharedSequence { let source = Observable.combineLatest(collection.map { $0.asObservable() }, resultSelector: resultSelector) return SharedSequence(source) @@ -503,7 +503,7 @@ extension SharedSequenceConvertibleType { - parameter resultSelector: Function to invoke for each element from the self combined with the latest element from the second source, if any. - returns: An observable sequence containing the result of combining each element of the self with the latest element from the second source, if any, using the specified result selector function. */ - public func withLatestFrom(_ second: SecondO, resultSelector: @escaping (Element, SecondO.Element) -> ResultType) -> SharedSequence where SecondO.SharingStrategy == SharingStrategy { + public func withLatestFrom(_ second: SecondO, resultSelector: @escaping @Sendable (Element, SecondO.Element) -> ResultType) -> SharedSequence where SecondO.SharingStrategy == SharingStrategy { let source = self.asObservable() .withLatestFrom(second.asSharedSequence(), resultSelector: resultSelector) diff --git a/RxCocoa/Traits/Signal/Signal+Subscription.swift b/RxCocoa/Traits/Signal/Signal+Subscription.swift index 4a6add336..bc9cf733b 100644 --- a/RxCocoa/Traits/Signal/Signal+Subscription.swift +++ b/RxCocoa/Traits/Signal/Signal+Subscription.swift @@ -132,9 +132,9 @@ extension SharedSequenceConvertibleType where SharingStrategy == SignalSharingSt */ public func emit( with object: Object, - onNext: ((Object, Element) -> Void)? = nil, - onCompleted: ((Object) -> Void)? = nil, - onDisposed: ((Object) -> Void)? = nil + onNext: (@Sendable (Object, Element) -> Void)? = nil, + onCompleted: (@Sendable (Object) -> Void)? = nil, + onDisposed: (@Sendable (Object) -> Void)? = nil ) -> Disposable { self.asObservable().subscribe( with: object, @@ -157,9 +157,9 @@ extension SharedSequenceConvertibleType where SharingStrategy == SignalSharingSt - returns: Subscription object used to unsubscribe from the observable sequence. */ public func emit( - onNext: ((Element) -> Void)? = nil, - onCompleted: (() -> Void)? = nil, - onDisposed: (() -> Void)? = nil + onNext: (@Sendable (Element) -> Void)? = nil, + onCompleted: (@Sendable () -> Void)? = nil, + onDisposed: (@Sendable () -> Void)? = nil ) -> Disposable { self.asObservable().subscribe(onNext: onNext, onCompleted: onCompleted, onDisposed: onDisposed) } diff --git a/RxSwift/AnyObserver.swift b/RxSwift/AnyObserver.swift index e92cc816e..fb2537c11 100644 --- a/RxSwift/AnyObserver.swift +++ b/RxSwift/AnyObserver.swift @@ -11,7 +11,7 @@ /// Forwards operations to an arbitrary underlying observer with the same `Element` type, hiding the specifics of the underlying observer type. public struct AnyObserver : ObserverType { /// Anonymous event handler type. - public typealias EventHandler = (Event) -> Void + public typealias EventHandler = @Sendable (Event) -> Void private let observer: EventHandler diff --git a/RxSwift/Binder.swift b/RxSwift/Binder.swift index 1aae09592..ab87a341c 100644 --- a/RxSwift/Binder.swift +++ b/RxSwift/Binder.swift @@ -15,10 +15,10 @@ By default it binds elements on main scheduler. */ -public struct Binder: ObserverType { +public struct Binder: ObserverType, @unchecked Sendable { public typealias Element = Value - private let binding: (Event) -> Void + private let binding: @Sendable (Event) -> Void /// Initializes `Binder` /// @@ -26,7 +26,7 @@ public struct Binder: ObserverType { /// - parameter scheduler: Scheduler used to bind the events. /// - parameter binding: Binding logic. public init(_ target: Target, scheduler: ImmediateSchedulerType = MainScheduler(), binding: @escaping (Target, Value) -> Void) { - weak var weakTarget = target + nonisolated(unsafe) weak var weakTarget = target self.binding = { event in switch event { @@ -46,6 +46,7 @@ public struct Binder: ObserverType { } /// Binds next element to owner view as described in `binding`. + @Sendable public func on(_ event: Event) { self.binding(event) } diff --git a/RxSwift/Concurrency/AsyncLock.swift b/RxSwift/Concurrency/AsyncLock.swift index 6bee59c11..7821f3831 100644 --- a/RxSwift/Concurrency/AsyncLock.swift +++ b/RxSwift/Concurrency/AsyncLock.swift @@ -20,7 +20,7 @@ final class AsyncLock : Disposable , Lock , SynchronizedDisposeType { - typealias Action = () -> Void + typealias Action = @Sendable () -> Void private var _lock = SpinLock() diff --git a/RxSwift/Disposables/AnonymousDisposable.swift b/RxSwift/Disposables/AnonymousDisposable.swift index 591aafa5e..2f8e79948 100644 --- a/RxSwift/Disposables/AnonymousDisposable.swift +++ b/RxSwift/Disposables/AnonymousDisposable.swift @@ -10,7 +10,7 @@ /// /// When dispose method is called, disposal action will be dereferenced. private final class AnonymousDisposable : DisposeBase, Cancelable { - public typealias DisposeAction = () -> Void + public typealias DisposeAction = @Sendable () -> Void private let disposed = AtomicInt(0) private var disposeAction: DisposeAction? @@ -52,7 +52,7 @@ extension Disposables { /// Constructs a new disposable with the given action used for disposal. /// /// - parameter dispose: Disposal action which will be run upon calling `dispose`. - public static func create(with dispose: @escaping () -> Void) -> Cancelable { + public static func create(with dispose: @escaping @Sendable () -> Void) -> Cancelable { AnonymousDisposable(disposeAction: dispose) } diff --git a/RxSwift/Disposables/ScheduledDisposable.swift b/RxSwift/Disposables/ScheduledDisposable.swift index 2cf997bca..672391b6f 100644 --- a/RxSwift/Disposables/ScheduledDisposable.swift +++ b/RxSwift/Disposables/ScheduledDisposable.swift @@ -6,7 +6,7 @@ // Copyright © 2015 Krunoslav Zaher. All rights reserved. // -private let disposeScheduledDisposable: (ScheduledDisposable) -> Disposable = { sd in +private let disposeScheduledDisposable: @Sendable (ScheduledDisposable) -> Disposable = { sd in sd.disposeInner() return Disposables.create() } diff --git a/RxSwift/ImmediateSchedulerType.swift b/RxSwift/ImmediateSchedulerType.swift index 954fbf04b..1e90aa76e 100644 --- a/RxSwift/ImmediateSchedulerType.swift +++ b/RxSwift/ImmediateSchedulerType.swift @@ -15,7 +15,7 @@ public protocol ImmediateSchedulerType { - parameter action: Action to be executed. - returns: The disposable object used to cancel the scheduled action (best effort). */ - func schedule(_ state: StateType, action: @escaping (StateType) -> Disposable) -> Disposable + func schedule(_ state: StateType, action: @escaping @Sendable (StateType) -> Disposable) -> Disposable } extension ImmediateSchedulerType { @@ -26,7 +26,7 @@ extension ImmediateSchedulerType { - parameter action: Action to execute recursively. The last parameter passed to the action is used to trigger recursive scheduling of the action, passing in recursive invocation state. - returns: The disposable object used to cancel the scheduled action (best effort). */ - public func scheduleRecursive(_ state: State, action: @escaping (_ state: State, _ recurse: (State) -> Void) -> Void) -> Disposable { + public func scheduleRecursive(_ state: State, action: @escaping @Sendable (_ state: State, _ recurse: (State) -> Void) -> Void) -> Disposable { let recursiveScheduler = RecursiveImmediateScheduler(action: action, scheduler: self) recursiveScheduler.schedule(state) diff --git a/RxSwift/Observable+Concurrency.swift b/RxSwift/Observable+Concurrency.swift index af3ec72bc..f086c3a81 100644 --- a/RxSwift/Observable+Concurrency.swift +++ b/RxSwift/Observable+Concurrency.swift @@ -27,7 +27,7 @@ public extension ObservableConvertibleType { /// ``` var values: AsyncThrowingStream { AsyncThrowingStream { continuation in - var isFinished = false + nonisolated(unsafe) var isFinished = false let disposable = asObservable().subscribe( onNext: { value in continuation.yield(value) }, onError: { error in diff --git a/RxSwift/ObservableType+Extensions.swift b/RxSwift/ObservableType+Extensions.swift index ac850c3ba..71bae2c13 100644 --- a/RxSwift/ObservableType+Extensions.swift +++ b/RxSwift/ObservableType+Extensions.swift @@ -17,7 +17,7 @@ extension ObservableType { - parameter on: Action to invoke for each event in the observable sequence. - returns: Subscription object used to unsubscribe from the observable sequence. */ - public func subscribe(_ on: @escaping (Event) -> Void) -> Disposable { + public func subscribe(_ on: @escaping @Sendable (Event) -> Void) -> Disposable { let observer = AnonymousObserver { e in on(e) } @@ -41,10 +41,10 @@ extension ObservableType { */ public func subscribe( with object: Object, - onNext: ((Object, Element) -> Void)? = nil, - onError: ((Object, Swift.Error) -> Void)? = nil, - onCompleted: ((Object) -> Void)? = nil, - onDisposed: ((Object) -> Void)? = nil + onNext: (@Sendable (Object, Element) -> Void)? = nil, + onError: (@Sendable (Object, Swift.Error) -> Void)? = nil, + onCompleted: (@Sendable (Object) -> Void)? = nil, + onDisposed: (@Sendable (Object) -> Void)? = nil ) -> Disposable { subscribe( onNext: { [weak object] in @@ -77,10 +77,10 @@ extension ObservableType { - returns: Subscription object used to unsubscribe from the observable sequence. */ public func subscribe( - onNext: ((Element) -> Void)? = nil, - onError: ((Swift.Error) -> Void)? = nil, - onCompleted: (() -> Void)? = nil, - onDisposed: (() -> Void)? = nil + onNext: (@Sendable (Element) -> Void)? = nil, + onError: (@Sendable (Swift.Error) -> Void)? = nil, + onCompleted: (@Sendable () -> Void)? = nil, + onDisposed: (@Sendable () -> Void)? = nil ) -> Disposable { let disposable: Disposable @@ -130,8 +130,8 @@ extension ObservableType { import Foundation extension Hooks { - public typealias DefaultErrorHandler = (_ subscriptionCallStack: [String], _ error: Error) -> Void - public typealias CustomCaptureSubscriptionCallstack = () -> [String] + public typealias DefaultErrorHandler = @Sendable (_ subscriptionCallStack: [String], _ error: Error) -> Void + public typealias CustomCaptureSubscriptionCallstack = @Sendable () -> [String] private static let lock = RecursiveLock() private static var _defaultErrorHandler: DefaultErrorHandler = { subscriptionCallStack, error in diff --git a/RxSwift/Observables/Amb.swift b/RxSwift/Observables/Amb.swift index efc17a8d9..73fcda60b 100644 --- a/RxSwift/Observables/Amb.swift +++ b/RxSwift/Observables/Amb.swift @@ -49,7 +49,7 @@ final private class AmbObserver: ObserverType { typealias Element = Observer.Element typealias Parent = AmbSink typealias This = AmbObserver - typealias Sink = (This, Event) -> Void + typealias Sink = @Sendable (This, Event) -> Void private let parent: Parent fileprivate var sink: Sink @@ -100,7 +100,7 @@ final private class AmbSink: Sink { let subscription2 = SingleAssignmentDisposable() let disposeAll = Disposables.create(subscription1, subscription2) - let forwardEvent = { (o: AmbObserverType, event: Event) -> Void in + let forwardEvent = { @Sendable (o: AmbObserverType, event: Event) -> Void in self.forwardOn(event) if event.isStopEvent { self.dispose() diff --git a/RxSwift/Observables/Catch.swift b/RxSwift/Observables/Catch.swift index 2efd66062..4d7c6fe34 100644 --- a/RxSwift/Observables/Catch.swift +++ b/RxSwift/Observables/Catch.swift @@ -16,7 +16,7 @@ extension ObservableType { - parameter handler: Error handler function, producing another observable sequence. - returns: An observable sequence containing the source sequence's elements, followed by the elements produced by the handler's resulting observable sequence in case an error occurred. */ - public func `catch`(_ handler: @escaping (Swift.Error) throws -> Observable) + public func `catch`(_ handler: @escaping @Sendable (Swift.Error) throws -> Observable) -> Observable { Catch(source: self.asObservable(), handler: handler) } @@ -30,7 +30,7 @@ extension ObservableType { - returns: An observable sequence containing the source sequence's elements, followed by the elements produced by the handler's resulting observable sequence in case an error occurred. */ @available(*, deprecated, renamed: "catch(_:)") - public func catchError(_ handler: @escaping (Swift.Error) throws -> Observable) + public func catchError(_ handler: @escaping @Sendable (Swift.Error) throws -> Observable) -> Observable { `catch`(handler) } @@ -189,7 +189,7 @@ final private class CatchSink: Sink, ObserverT } final private class Catch: Producer { - typealias Handler = (Swift.Error) throws -> Observable + typealias Handler = @Sendable (Swift.Error) throws -> Observable fileprivate let source: Observable fileprivate let handler: Handler diff --git a/RxSwift/Observables/CombineLatest+Collection.swift b/RxSwift/Observables/CombineLatest+Collection.swift index b56d050bb..0c828f0f3 100644 --- a/RxSwift/Observables/CombineLatest+Collection.swift +++ b/RxSwift/Observables/CombineLatest+Collection.swift @@ -15,7 +15,7 @@ extension ObservableType { - parameter resultSelector: Function to invoke whenever any of the sources produces an element. - returns: An observable sequence containing the result of combining elements of the sources using the specified result selector function. */ - public static func combineLatest(_ collection: Collection, resultSelector: @escaping ([Collection.Element.Element]) throws -> Element) -> Observable + public static func combineLatest(_ collection: Collection, resultSelector: @escaping @Sendable ([Collection.Element.Element]) throws -> Element) -> Observable where Collection.Element: ObservableType { CombineLatestCollectionType(sources: collection, resultSelector: resultSelector) } @@ -145,7 +145,7 @@ final class CombineLatestCollectionTypeSink: Producer where Collection.Element: ObservableConvertibleType { - typealias ResultSelector = ([Collection.Element.Element]) throws -> Result + typealias ResultSelector = @Sendable ([Collection.Element.Element]) throws -> Result let sources: Collection let resultSelector: ResultSelector diff --git a/RxSwift/Observables/CombineLatest+arity.swift b/RxSwift/Observables/CombineLatest+arity.swift index e69bbab4a..1e1e3d5b9 100644 --- a/RxSwift/Observables/CombineLatest+arity.swift +++ b/RxSwift/Observables/CombineLatest+arity.swift @@ -21,7 +21,7 @@ extension ObservableType { - returns: An observable sequence containing the result of combining elements of the sources using the specified result selector function. */ public static func combineLatest - (_ source1: O1, _ source2: O2, resultSelector: @escaping (O1.Element, O2.Element) throws -> Element) + (_ source1: O1, _ source2: O2, resultSelector: @escaping @Sendable (O1.Element, O2.Element) throws -> Element) -> Observable { return CombineLatest2( source1: source1.asObservable(), source2: source2.asObservable(), @@ -84,7 +84,7 @@ final class CombineLatestSink2_ : CombineLatestS } final class CombineLatest2 : Producer { - typealias ResultSelector = (E1, E2) throws -> Result + typealias ResultSelector = @Sendable (E1, E2) throws -> Result let source1: Observable let source2: Observable @@ -119,7 +119,7 @@ extension ObservableType { - returns: An observable sequence containing the result of combining elements of the sources using the specified result selector function. */ public static func combineLatest - (_ source1: O1, _ source2: O2, _ source3: O3, resultSelector: @escaping (O1.Element, O2.Element, O3.Element) throws -> Element) + (_ source1: O1, _ source2: O2, _ source3: O3, resultSelector: @escaping @Sendable (O1.Element, O2.Element, O3.Element) throws -> Element) -> Observable { return CombineLatest3( source1: source1.asObservable(), source2: source2.asObservable(), source3: source3.asObservable(), @@ -187,7 +187,7 @@ final class CombineLatestSink3_ : CombineLat } final class CombineLatest3 : Producer { - typealias ResultSelector = (E1, E2, E3) throws -> Result + typealias ResultSelector = @Sendable (E1, E2, E3) throws -> Result let source1: Observable let source2: Observable @@ -224,7 +224,7 @@ extension ObservableType { - returns: An observable sequence containing the result of combining elements of the sources using the specified result selector function. */ public static func combineLatest - (_ source1: O1, _ source2: O2, _ source3: O3, _ source4: O4, resultSelector: @escaping (O1.Element, O2.Element, O3.Element, O4.Element) throws -> Element) + (_ source1: O1, _ source2: O2, _ source3: O3, _ source4: O4, resultSelector: @escaping @Sendable (O1.Element, O2.Element, O3.Element, O4.Element) throws -> Element) -> Observable { return CombineLatest4( source1: source1.asObservable(), source2: source2.asObservable(), source3: source3.asObservable(), source4: source4.asObservable(), @@ -297,7 +297,7 @@ final class CombineLatestSink4_ : Combin } final class CombineLatest4 : Producer { - typealias ResultSelector = (E1, E2, E3, E4) throws -> Result + typealias ResultSelector = @Sendable (E1, E2, E3, E4) throws -> Result let source1: Observable let source2: Observable @@ -336,7 +336,7 @@ extension ObservableType { - returns: An observable sequence containing the result of combining elements of the sources using the specified result selector function. */ public static func combineLatest - (_ source1: O1, _ source2: O2, _ source3: O3, _ source4: O4, _ source5: O5, resultSelector: @escaping (O1.Element, O2.Element, O3.Element, O4.Element, O5.Element) throws -> Element) + (_ source1: O1, _ source2: O2, _ source3: O3, _ source4: O4, _ source5: O5, resultSelector: @escaping @Sendable (O1.Element, O2.Element, O3.Element, O4.Element, O5.Element) throws -> Element) -> Observable { return CombineLatest5( source1: source1.asObservable(), source2: source2.asObservable(), source3: source3.asObservable(), source4: source4.asObservable(), source5: source5.asObservable(), @@ -414,7 +414,7 @@ final class CombineLatestSink5_ : Co } final class CombineLatest5 : Producer { - typealias ResultSelector = (E1, E2, E3, E4, E5) throws -> Result + typealias ResultSelector = @Sendable (E1, E2, E3, E4, E5) throws -> Result let source1: Observable let source2: Observable @@ -455,7 +455,7 @@ extension ObservableType { - returns: An observable sequence containing the result of combining elements of the sources using the specified result selector function. */ public static func combineLatest - (_ source1: O1, _ source2: O2, _ source3: O3, _ source4: O4, _ source5: O5, _ source6: O6, resultSelector: @escaping (O1.Element, O2.Element, O3.Element, O4.Element, O5.Element, O6.Element) throws -> Element) + (_ source1: O1, _ source2: O2, _ source3: O3, _ source4: O4, _ source5: O5, _ source6: O6, resultSelector: @escaping @Sendable (O1.Element, O2.Element, O3.Element, O4.Element, O5.Element, O6.Element) throws -> Element) -> Observable { return CombineLatest6( source1: source1.asObservable(), source2: source2.asObservable(), source3: source3.asObservable(), source4: source4.asObservable(), source5: source5.asObservable(), source6: source6.asObservable(), @@ -538,7 +538,7 @@ final class CombineLatestSink6_ } final class CombineLatest6 : Producer { - typealias ResultSelector = (E1, E2, E3, E4, E5, E6) throws -> Result + typealias ResultSelector = @Sendable (E1, E2, E3, E4, E5, E6) throws -> Result let source1: Observable let source2: Observable @@ -581,7 +581,7 @@ extension ObservableType { - returns: An observable sequence containing the result of combining elements of the sources using the specified result selector function. */ public static func combineLatest - (_ source1: O1, _ source2: O2, _ source3: O3, _ source4: O4, _ source5: O5, _ source6: O6, _ source7: O7, resultSelector: @escaping (O1.Element, O2.Element, O3.Element, O4.Element, O5.Element, O6.Element, O7.Element) throws -> Element) + (_ source1: O1, _ source2: O2, _ source3: O3, _ source4: O4, _ source5: O5, _ source6: O6, _ source7: O7, resultSelector: @escaping @Sendable (O1.Element, O2.Element, O3.Element, O4.Element, O5.Element, O6.Element, O7.Element) throws -> Element) -> Observable { return CombineLatest7( source1: source1.asObservable(), source2: source2.asObservable(), source3: source3.asObservable(), source4: source4.asObservable(), source5: source5.asObservable(), source6: source6.asObservable(), source7: source7.asObservable(), @@ -669,7 +669,7 @@ final class CombineLatestSink7_ : Producer { - typealias ResultSelector = (E1, E2, E3, E4, E5, E6, E7) throws -> Result + typealias ResultSelector = @Sendable (E1, E2, E3, E4, E5, E6, E7) throws -> Result let source1: Observable let source2: Observable @@ -714,7 +714,7 @@ extension ObservableType { - returns: An observable sequence containing the result of combining elements of the sources using the specified result selector function. */ public static func combineLatest - (_ source1: O1, _ source2: O2, _ source3: O3, _ source4: O4, _ source5: O5, _ source6: O6, _ source7: O7, _ source8: O8, resultSelector: @escaping (O1.Element, O2.Element, O3.Element, O4.Element, O5.Element, O6.Element, O7.Element, O8.Element) throws -> Element) + (_ source1: O1, _ source2: O2, _ source3: O3, _ source4: O4, _ source5: O5, _ source6: O6, _ source7: O7, _ source8: O8, resultSelector: @escaping @Sendable (O1.Element, O2.Element, O3.Element, O4.Element, O5.Element, O6.Element, O7.Element, O8.Element) throws -> Element) -> Observable { return CombineLatest8( source1: source1.asObservable(), source2: source2.asObservable(), source3: source3.asObservable(), source4: source4.asObservable(), source5: source5.asObservable(), source6: source6.asObservable(), source7: source7.asObservable(), source8: source8.asObservable(), @@ -807,7 +807,7 @@ final class CombineLatestSink8_ : Producer { - typealias ResultSelector = (E1, E2, E3, E4, E5, E6, E7, E8) throws -> Result + typealias ResultSelector = @Sendable (E1, E2, E3, E4, E5, E6, E7, E8) throws -> Result let source1: Observable let source2: Observable diff --git a/RxSwift/Observables/CombineLatest.swift b/RxSwift/Observables/CombineLatest.swift index caa025640..399688e8e 100644 --- a/RxSwift/Observables/CombineLatest.swift +++ b/RxSwift/Observables/CombineLatest.swift @@ -94,7 +94,7 @@ final class CombineLatestObserver : ObserverType , LockOwnerType , SynchronizedOnType { - typealias ValueSetter = (Element) -> Void + typealias ValueSetter = @Sendable (Element) -> Void private let parent: CombineLatestProtocol diff --git a/RxSwift/Observables/CompactMap.swift b/RxSwift/Observables/CompactMap.swift index 7dbcdfbe9..06b8d1d33 100644 --- a/RxSwift/Observables/CompactMap.swift +++ b/RxSwift/Observables/CompactMap.swift @@ -15,14 +15,14 @@ extension ObservableType { - returns: An observable sequence whose elements are the result of filtering the transform function for each element of the source. */ - public func compactMap(_ transform: @escaping (Element) throws -> Result?) + public func compactMap(_ transform: @escaping @Sendable (Element) throws -> Result?) -> Observable { CompactMap(source: self.asObservable(), transform: transform) } } final private class CompactMapSink: Sink, ObserverType { - typealias Transform = (SourceType) throws -> ResultType? + typealias Transform = @Sendable (SourceType) throws -> ResultType? typealias ResultType = Observer.Element typealias Element = SourceType @@ -57,7 +57,7 @@ final private class CompactMapSink: Sink: Producer { - typealias Transform = (SourceType) throws -> ResultType? + typealias Transform = @Sendable (SourceType) throws -> ResultType? private let source: Observable diff --git a/RxSwift/Observables/Create.swift b/RxSwift/Observables/Create.swift index ca81442ce..50be8ff00 100644 --- a/RxSwift/Observables/Create.swift +++ b/RxSwift/Observables/Create.swift @@ -17,7 +17,7 @@ extension ObservableType { - parameter subscribe: Implementation of the resulting observable sequence's `subscribe` method. - returns: The observable sequence with the specified implementation for the `subscribe` method. */ - public static func create(_ subscribe: @escaping (AnyObserver) -> Disposable) -> Observable { + public static func create(_ subscribe: @escaping @Sendable (AnyObserver) -> Disposable) -> Observable { AnonymousObservable(subscribe) } } @@ -62,7 +62,7 @@ final private class AnonymousObservableSink: Sink: Producer { - typealias SubscribeHandler = (AnyObserver) -> Disposable + typealias SubscribeHandler = @Sendable (AnyObserver) -> Disposable let subscribeHandler: SubscribeHandler diff --git a/RxSwift/Observables/Debounce.swift b/RxSwift/Observables/Debounce.swift index 581a5cc5e..e9ce18f29 100644 --- a/RxSwift/Observables/Debounce.swift +++ b/RxSwift/Observables/Debounce.swift @@ -87,6 +87,7 @@ final private class DebounceSink } } + @Sendable func propagate(_ currentId: UInt64) -> Disposable { self.lock.performLocked { let originalValue = self.value diff --git a/RxSwift/Observables/Deferred.swift b/RxSwift/Observables/Deferred.swift index 51e64d1c0..f5b6f0d48 100644 --- a/RxSwift/Observables/Deferred.swift +++ b/RxSwift/Observables/Deferred.swift @@ -15,7 +15,7 @@ extension ObservableType { - parameter observableFactory: Observable factory function to invoke for each observer that subscribes to the resulting sequence. - returns: An observable sequence whose observers trigger an invocation of the given observable factory function. */ - public static func deferred(_ observableFactory: @escaping () throws -> Observable) + public static func deferred(_ observableFactory: @escaping @Sendable () throws -> Observable) -> Observable { Deferred(observableFactory: observableFactory) } @@ -56,7 +56,7 @@ final private class DeferredSink } final private class Deferred: Producer { - typealias Factory = () throws -> Source + typealias Factory = @Sendable () throws -> Source let observableFactory : Factory diff --git a/RxSwift/Observables/Delay.swift b/RxSwift/Observables/Delay.swift index 9f71c32d0..5f5a90219 100644 --- a/RxSwift/Observables/Delay.swift +++ b/RxSwift/Observables/Delay.swift @@ -60,6 +60,7 @@ final private class DelaySink // scheduler so this process needs to be synchronized somehow. // // Another complication is that scheduler is potentially concurrent so internal queue is used. + @Sendable func drainQueue(state: (), scheduler: AnyRecursiveScheduler<()>) { self.lock.lock() let hasFailed = self.errorEvent != nil diff --git a/RxSwift/Observables/DistinctUntilChanged.swift b/RxSwift/Observables/DistinctUntilChanged.swift index c127b5aa5..470073144 100644 --- a/RxSwift/Observables/DistinctUntilChanged.swift +++ b/RxSwift/Observables/DistinctUntilChanged.swift @@ -30,7 +30,7 @@ extension ObservableType { - parameter keySelector: A function to compute the comparison key for each element. - returns: An observable sequence only containing the distinct contiguous elements, based on a computed key value, from the source sequence. */ - public func distinctUntilChanged(_ keySelector: @escaping (Element) throws -> Key) + public func distinctUntilChanged(_ keySelector: @escaping @Sendable (Element) throws -> Key) -> Observable { self.distinctUntilChanged(keySelector, comparer: { $0 == $1 }) } @@ -43,7 +43,7 @@ extension ObservableType { - parameter comparer: Equality comparer for computed key values. - returns: An observable sequence only containing the distinct contiguous elements, based on `comparer`, from the source sequence. */ - public func distinctUntilChanged(_ comparer: @escaping (Element, Element) throws -> Bool) + public func distinctUntilChanged(_ comparer: @escaping @Sendable (Element, Element) throws -> Bool) -> Observable { self.distinctUntilChanged({ $0 }, comparer: comparer) } @@ -57,7 +57,7 @@ extension ObservableType { - parameter comparer: Equality comparer for computed key values. - returns: An observable sequence only containing the distinct contiguous elements, based on a computed key value and the comparer, from the source sequence. */ - public func distinctUntilChanged(_ keySelector: @escaping (Element) throws -> K, comparer: @escaping (K, K) throws -> Bool) + public func distinctUntilChanged(_ keySelector: @escaping @Sendable (Element) throws -> K, comparer: @escaping @Sendable (K, K) throws -> Bool) -> Observable { return DistinctUntilChanged(source: self.asObservable(), selector: keySelector, comparer: comparer) } @@ -116,8 +116,8 @@ final private class DistinctUntilChangedSink: Sink< } final private class DistinctUntilChanged: Producer { - typealias KeySelector = (Element) throws -> Key - typealias EqualityComparer = (Key, Key) throws -> Bool + typealias KeySelector = @Sendable (Element) throws -> Key + typealias EqualityComparer = @Sendable (Key, Key) throws -> Bool private let source: Observable fileprivate let selector: KeySelector diff --git a/RxSwift/Observables/Do.swift b/RxSwift/Observables/Do.swift index 3c8c68b3d..093511b54 100644 --- a/RxSwift/Observables/Do.swift +++ b/RxSwift/Observables/Do.swift @@ -23,7 +23,7 @@ extension ObservableType { - parameter onDispose: Action to invoke after subscription to source observable has been disposed for any reason. It can be either because sequence terminates for some reason or observer subscription being disposed. - returns: The source sequence with the side-effecting behavior applied. */ - public func `do`(onNext: ((Element) throws -> Void)? = nil, afterNext: ((Element) throws -> Void)? = nil, onError: ((Swift.Error) throws -> Void)? = nil, afterError: ((Swift.Error) throws -> Void)? = nil, onCompleted: (() throws -> Void)? = nil, afterCompleted: (() throws -> Void)? = nil, onSubscribe: (() -> Void)? = nil, onSubscribed: (() -> Void)? = nil, onDispose: (() -> Void)? = nil) + public func `do`(onNext: (@Sendable (Element) throws -> Void)? = nil, afterNext: (@Sendable (Element) throws -> Void)? = nil, onError: (@Sendable (Swift.Error) throws -> Void)? = nil, afterError: (@Sendable (Swift.Error) throws -> Void)? = nil, onCompleted: (@Sendable () throws -> Void)? = nil, afterCompleted: (@Sendable () throws -> Void)? = nil, onSubscribe: (@Sendable () -> Void)? = nil, onSubscribed: (@Sendable () -> Void)? = nil, onDispose: (@Sendable () -> Void)? = nil) -> Observable { return Do(source: self.asObservable(), eventHandler: { e in switch e { @@ -49,8 +49,8 @@ extension ObservableType { final private class DoSink: Sink, ObserverType { typealias Element = Observer.Element - typealias EventHandler = (Event) throws -> Void - typealias AfterEventHandler = (Event) throws -> Void + typealias EventHandler = @Sendable (Event) throws -> Void + typealias AfterEventHandler = @Sendable (Event) throws -> Void private let eventHandler: EventHandler private let afterEventHandler: AfterEventHandler @@ -78,17 +78,17 @@ final private class DoSink: Sink, ObserverType } final private class Do: Producer { - typealias EventHandler = (Event) throws -> Void - typealias AfterEventHandler = (Event) throws -> Void + typealias EventHandler = @Sendable (Event) throws -> Void + typealias AfterEventHandler = @Sendable (Event) throws -> Void private let source: Observable private let eventHandler: EventHandler private let afterEventHandler: AfterEventHandler - private let onSubscribe: (() -> Void)? - private let onSubscribed: (() -> Void)? - private let onDispose: (() -> Void)? + private let onSubscribe: (@Sendable () -> Void)? + private let onSubscribed: (@Sendable () -> Void)? + private let onDispose: (@Sendable () -> Void)? - init(source: Observable, eventHandler: @escaping EventHandler, afterEventHandler: @escaping AfterEventHandler, onSubscribe: (() -> Void)?, onSubscribed: (() -> Void)?, onDispose: (() -> Void)?) { + init(source: Observable, eventHandler: @escaping EventHandler, afterEventHandler: @escaping AfterEventHandler, onSubscribe: (@Sendable () -> Void)?, onSubscribed: (@Sendable () -> Void)?, onDispose: (@Sendable () -> Void)?) { self.source = source self.eventHandler = eventHandler self.afterEventHandler = afterEventHandler diff --git a/RxSwift/Observables/Filter.swift b/RxSwift/Observables/Filter.swift index 61d3ce793..8819d921a 100644 --- a/RxSwift/Observables/Filter.swift +++ b/RxSwift/Observables/Filter.swift @@ -16,7 +16,7 @@ extension ObservableType { - parameter predicate: A function to test each source element for a condition. - returns: An observable sequence that contains elements from the input sequence that satisfy the condition. */ - public func filter(_ predicate: @escaping (Element) throws -> Bool) + public func filter(_ predicate: @escaping @Sendable (Element) throws -> Bool) -> Observable { Filter(source: self.asObservable(), predicate: predicate) } @@ -37,7 +37,7 @@ extension ObservableType { } final private class FilterSink: Sink, ObserverType { - typealias Predicate = (Element) throws -> Bool + typealias Predicate = @Sendable (Element) throws -> Bool typealias Element = Observer.Element private let predicate: Predicate @@ -68,7 +68,7 @@ final private class FilterSink: Sink, Observer } final private class Filter: Producer { - typealias Predicate = (Element) throws -> Bool + typealias Predicate = @Sendable (Element) throws -> Bool private let source: Observable private let predicate: Predicate diff --git a/RxSwift/Observables/GroupBy.swift b/RxSwift/Observables/GroupBy.swift index 88cbda767..4415d7841 100644 --- a/RxSwift/Observables/GroupBy.swift +++ b/RxSwift/Observables/GroupBy.swift @@ -15,7 +15,7 @@ extension ObservableType { - parameter keySelector: A function to extract the key for each element. - returns: A sequence of observable groups, each of which corresponds to a unique key value, containing all elements that share that same key value. */ - public func groupBy(keySelector: @escaping (Element) throws -> Key) + public func groupBy(keySelector: @escaping @Sendable (Element) throws -> Key) -> Observable> { GroupBy(source: self.asObservable(), selector: keySelector) } @@ -116,7 +116,7 @@ final private class GroupBySink } final private class GroupBy: Producer> { - typealias KeySelector = (Element) throws -> Key + typealias KeySelector = @Sendable (Element) throws -> Key fileprivate let source: Observable fileprivate let selector: KeySelector diff --git a/RxSwift/Observables/Map.swift b/RxSwift/Observables/Map.swift index 693794431..352f17438 100644 --- a/RxSwift/Observables/Map.swift +++ b/RxSwift/Observables/Map.swift @@ -17,14 +17,14 @@ extension ObservableType { - returns: An observable sequence whose elements are the result of invoking the transform function on each element of source. */ - public func map(_ transform: @escaping (Element) throws -> Result) + public func map(_ transform: @escaping @Sendable (Element) throws -> Result) -> Observable { Map(source: self.asObservable(), transform: transform) } } final private class MapSink: Sink, ObserverType { - typealias Transform = (SourceType) throws -> ResultType + typealias Transform = @Sendable (SourceType) throws -> ResultType typealias ResultType = Observer.Element @@ -57,7 +57,7 @@ final private class MapSink: Sink, } final private class Map: Producer { - typealias Transform = (SourceType) throws -> ResultType + typealias Transform = @Sendable (SourceType) throws -> ResultType private let source: Observable diff --git a/RxSwift/Observables/Merge.swift b/RxSwift/Observables/Merge.swift index 51a646291..03b88f5f8 100644 --- a/RxSwift/Observables/Merge.swift +++ b/RxSwift/Observables/Merge.swift @@ -16,7 +16,7 @@ extension ObservableType { - parameter selector: A transform function to apply to each element. - returns: An observable sequence whose elements are the result of invoking the one-to-many transform function on each element of the input sequence. */ - public func flatMap(_ selector: @escaping (Element) throws -> Source) + public func flatMap(_ selector: @escaping @Sendable (Element) throws -> Source) -> Observable { return FlatMap(source: self.asObservable(), selector: selector) } @@ -34,7 +34,7 @@ extension ObservableType { - parameter selector: A transform function to apply to element that was observed while no observable is executing in parallel. - returns: An observable sequence whose elements are the result of invoking the one-to-many transform function on each element of the input sequence that was received while no other sequence was being calculated. */ - public func flatMapFirst(_ selector: @escaping (Element) throws -> Source) + public func flatMapFirst(_ selector: @escaping @Sendable (Element) throws -> Source) -> Observable { return FlatMapFirst(source: self.asObservable(), selector: selector) } @@ -130,7 +130,7 @@ extension ObservableType { - returns: An observable sequence that contains the elements of each observed inner sequence, in sequential order. */ - public func concatMap(_ selector: @escaping (Element) throws -> Source) + public func concatMap(_ selector: @escaping @Sendable (Element) throws -> Source) -> Observable { return ConcatMap(source: self.asObservable(), selector: selector) } @@ -185,7 +185,7 @@ private final class MergeLimitedSinkIter: MergeLimitedSink where Observer.Element == SourceSequence.Element { - typealias Selector = (SourceElement) throws -> SourceSequence + typealias Selector = @Sendable (SourceElement) throws -> SourceSequence private let selector: Selector @@ -339,7 +339,7 @@ private final class MergeBasicSink : MergeSink where Observer.Element == SourceSequence.Element { - typealias Selector = (SourceElement) throws -> SourceSequence + typealias Selector = @Sendable (SourceElement) throws -> SourceSequence private let selector: Selector @@ -356,7 +356,7 @@ private final class FlatMapSink : MergeSink where Observer.Element == SourceSequence.Element { - typealias Selector = (SourceElement) throws -> SourceSequence + typealias Selector = @Sendable (SourceElement) throws -> SourceSequence private let selector: Selector @@ -516,7 +516,7 @@ private class MergeSink: Producer { - typealias Selector = (SourceElement) throws -> SourceSequence + typealias Selector = @Sendable (SourceElement) throws -> SourceSequence private let source: Observable @@ -535,7 +535,7 @@ final private class FlatMap: Producer { - typealias Selector = (SourceElement) throws -> SourceSequence + typealias Selector = @Sendable (SourceElement) throws -> SourceSequence private let source: Observable @@ -554,7 +554,7 @@ final private class FlatMapFirst: Producer { - typealias Selector = (SourceElement) throws -> SourceSequence + typealias Selector = @Sendable (SourceElement) throws -> SourceSequence private let source: Observable private let selector: Selector diff --git a/RxSwift/Observables/Multicast.swift b/RxSwift/Observables/Multicast.swift index 1ebcf0212..6786c4918 100644 --- a/RxSwift/Observables/Multicast.swift +++ b/RxSwift/Observables/Multicast.swift @@ -38,7 +38,7 @@ extension ObservableType { - parameter selector: Selector function which can use the multicasted source sequence subject to the policies enforced by the created subject. - returns: An observable sequence that contains the elements of a sequence produced by multicasting the source sequence within a selector function. */ - public func multicast(_ subjectSelector: @escaping () throws -> Subject, selector: @escaping (Observable) throws -> Observable) + public func multicast(_ subjectSelector: @escaping @Sendable () throws -> Subject, selector: @escaping @Sendable (Observable) throws -> Observable) -> Observable where Subject.Observer.Element == Element { return Multicast( source: self.asObservable(), @@ -384,8 +384,8 @@ final private class MulticastSink: } final private class Multicast: Producer { - typealias SubjectSelectorType = () throws -> Subject - typealias SelectorType = (Observable) throws -> Observable + typealias SubjectSelectorType = @Sendable () throws -> Subject + typealias SelectorType = @Sendable (Observable) throws -> Observable fileprivate let source: Observable fileprivate let subjectSelector: SubjectSelectorType diff --git a/RxSwift/Observables/ObserveOn.swift b/RxSwift/Observables/ObserveOn.swift index 6b8689e1e..8800de41b 100644 --- a/RxSwift/Observables/ObserveOn.swift +++ b/RxSwift/Observables/ObserveOn.swift @@ -118,6 +118,7 @@ final private class ObserveOnSink: ObserverBase Void) { let (nextEvent, observer) = self.lock.performLocked { () -> (Event?, Observer) in if !self.queue.isEmpty { diff --git a/RxSwift/Observables/Reduce.swift b/RxSwift/Observables/Reduce.swift index d5fab3478..947b76a34 100644 --- a/RxSwift/Observables/Reduce.swift +++ b/RxSwift/Observables/Reduce.swift @@ -20,7 +20,7 @@ extension ObservableType { - parameter mapResult: A function to transform the final accumulator value into the result value. - returns: An observable sequence containing a single element with the final accumulator value. */ - public func reduce(_ seed: A, accumulator: @escaping (A, Element) throws -> A, mapResult: @escaping (A) throws -> Result) + public func reduce(_ seed: A, accumulator: @escaping @Sendable (A, Element) throws -> A, mapResult: @escaping @Sendable (A) throws -> Result) -> Observable { Reduce(source: self.asObservable(), seed: seed, accumulator: accumulator, mapResult: mapResult) } @@ -36,7 +36,7 @@ extension ObservableType { - parameter accumulator: A accumulator function to be invoked on each element. - returns: An observable sequence containing a single element with the final accumulator value. */ - public func reduce(_ seed: A, accumulator: @escaping (A, Element) throws -> A) + public func reduce(_ seed: A, accumulator: @escaping @Sendable (A, Element) throws -> A) -> Observable { Reduce(source: self.asObservable(), seed: seed, accumulator: accumulator, mapResult: { $0 }) } @@ -85,8 +85,8 @@ final private class ReduceSink: Producer { - typealias AccumulatorType = (AccumulateType, SourceType) throws -> AccumulateType - typealias ResultSelectorType = (AccumulateType) throws -> ResultType + typealias AccumulatorType = @Sendable (AccumulateType, SourceType) throws -> AccumulateType + typealias ResultSelectorType = @Sendable (AccumulateType) throws -> ResultType private let source: Observable fileprivate let seed: AccumulateType diff --git a/RxSwift/Observables/Scan.swift b/RxSwift/Observables/Scan.swift index ecf69c80c..6cb92b9df 100644 --- a/RxSwift/Observables/Scan.swift +++ b/RxSwift/Observables/Scan.swift @@ -19,7 +19,7 @@ extension ObservableType { - parameter accumulator: An accumulator function to be invoked on each element. - returns: An observable sequence containing the accumulated values. */ - public func scan(into seed: A, accumulator: @escaping (inout A, Element) throws -> Void) + public func scan(into seed: A, accumulator: @escaping @Sendable (inout A, Element) throws -> Void) -> Observable { Scan(source: self.asObservable(), seed: seed, accumulator: accumulator) } @@ -80,7 +80,7 @@ final private class ScanSink: Sink, O } final private class Scan: Producer { - typealias Accumulator = (inout Accumulate, Element) throws -> Void + typealias Accumulator = @Sendable (inout Accumulate, Element) throws -> Void private let source: Observable fileprivate let seed: Accumulate diff --git a/RxSwift/Observables/SingleAsync.swift b/RxSwift/Observables/SingleAsync.swift index 04e221764..679c8da3a 100644 --- a/RxSwift/Observables/SingleAsync.swift +++ b/RxSwift/Observables/SingleAsync.swift @@ -30,7 +30,7 @@ extension ObservableType { - parameter predicate: A function to test each source element for a condition. - returns: An observable sequence that emits a single element or throws an exception if more (or none) of them are emitted. */ - public func single(_ predicate: @escaping (Element) throws -> Bool) + public func single(_ predicate: @escaping @Sendable (Element) throws -> Bool) -> Observable { SingleAsync(source: self.asObservable(), predicate: predicate) } @@ -86,7 +86,7 @@ private final class SingleAsyncSink : Sink, Ob } final class SingleAsync: Producer { - typealias Predicate = (Element) throws -> Bool + typealias Predicate = @Sendable (Element) throws -> Bool private let source: Observable fileprivate let predicate: Predicate? diff --git a/RxSwift/Observables/SkipWhile.swift b/RxSwift/Observables/SkipWhile.swift index a62f88ddd..79e60c0aa 100644 --- a/RxSwift/Observables/SkipWhile.swift +++ b/RxSwift/Observables/SkipWhile.swift @@ -15,7 +15,7 @@ extension ObservableType { - parameter predicate: A function to test each element for a condition. - returns: An observable sequence that contains the elements from the input sequence starting at the first element in the linear series that does not pass the test specified by predicate. */ - public func skip(while predicate: @escaping (Element) throws -> Bool) -> Observable { + public func skip(while predicate: @escaping @Sendable (Element) throws -> Bool) -> Observable { SkipWhile(source: self.asObservable(), predicate: predicate) } @@ -28,7 +28,7 @@ extension ObservableType { - returns: An observable sequence that contains the elements from the input sequence starting at the first element in the linear series that does not pass the test specified by predicate. */ @available(*, deprecated, renamed: "skip(while:)") - public func skipWhile(_ predicate: @escaping (Element) throws -> Bool) -> Observable { + public func skipWhile(_ predicate: @escaping @Sendable (Element) throws -> Bool) -> Observable { SkipWhile(source: self.asObservable(), predicate: predicate) } } @@ -69,7 +69,7 @@ final private class SkipWhileSink: Sink, Obser } final private class SkipWhile: Producer { - typealias Predicate = (Element) throws -> Bool + typealias Predicate = @Sendable (Element) throws -> Bool private let source: Observable fileprivate let predicate: Predicate diff --git a/RxSwift/Observables/Switch.swift b/RxSwift/Observables/Switch.swift index 5aa60b97a..150cc81f9 100644 --- a/RxSwift/Observables/Switch.swift +++ b/RxSwift/Observables/Switch.swift @@ -19,7 +19,7 @@ extension ObservableType { - returns: An observable sequence whose elements are the result of invoking the transform function on each element of source producing an Observable of Observable sequences and that at any point in time produces the elements of the most recent inner observable sequence that has been received. */ - public func flatMapLatest(_ selector: @escaping (Element) throws -> Source) + public func flatMapLatest(_ selector: @escaping @Sendable (Element) throws -> Source) -> Observable { return FlatMapLatest(source: self.asObservable(), selector: selector) } @@ -36,7 +36,7 @@ extension ObservableType { - returns: An observable sequence whose elements are the result of invoking the transform function on each element of source producing an Observable of Observable sequences and that at any point in time produces the elements of the most recent inner observable sequence that has been received. */ - public func flatMapLatest(_ selector: @escaping (Element) throws -> Source) + public func flatMapLatest(_ selector: @escaping @Sendable (Element) throws -> Source) -> Infallible { return Infallible(flatMapLatest(selector)) } @@ -202,7 +202,7 @@ final private class SwitchIdentitySink: SwitchSink where Observer.Element == Source.Element { - typealias Selector = (SourceType) throws -> Source + typealias Selector = @Sendable (SourceType) throws -> Source private let selector: Selector @@ -233,7 +233,7 @@ final private class Switch: Producer: Producer { - typealias Selector = (SourceType) throws -> Source + typealias Selector = @Sendable (SourceType) throws -> Source private let source: Observable private let selector: Selector diff --git a/RxSwift/Observables/TakeWithPredicate.swift b/RxSwift/Observables/TakeWithPredicate.swift index 6c28d19ba..09d46fee2 100644 --- a/RxSwift/Observables/TakeWithPredicate.swift +++ b/RxSwift/Observables/TakeWithPredicate.swift @@ -30,7 +30,7 @@ extension ObservableType { - returns: An observable sequence that contains the elements from the input sequence that occur before the element at which the test passes. */ - public func take(until predicate: @escaping (Element) throws -> Bool, + public func take(until predicate: @escaping @Sendable (Element) throws -> Bool, behavior: TakeBehavior = .exclusive) -> Observable { TakeUntilPredicate(source: self.asObservable(), @@ -77,7 +77,7 @@ extension ObservableType { */ @available(*, deprecated, renamed: "take(until:behavior:)") public func takeUntil(_ behavior: TakeBehavior, - predicate: @escaping (Element) throws -> Bool) + predicate: @escaping @Sendable (Element) throws -> Bool) -> Observable { take(until: predicate, behavior: behavior) } @@ -263,7 +263,7 @@ final private class TakeUntilPredicateSink } final private class TakeUntilPredicate: Producer { - typealias Predicate = (Element) throws -> Bool + typealias Predicate = @Sendable (Element) throws -> Bool private let source: Observable fileprivate let predicate: Predicate diff --git a/RxSwift/Observables/Throttle.swift b/RxSwift/Observables/Throttle.swift index 86152a837..b1068de85 100644 --- a/RxSwift/Observables/Throttle.swift +++ b/RxSwift/Observables/Throttle.swift @@ -122,6 +122,7 @@ final private class ThrottleSink self.lastSentTime = self.parent.scheduler.now } + @Sendable func propagate(_: Int) -> Disposable { self.lock.performLocked { if let lastUnsentElement = self.lastUnsentElement { diff --git a/RxSwift/Observables/Using.swift b/RxSwift/Observables/Using.swift index ca48d2fb8..08573f3cd 100644 --- a/RxSwift/Observables/Using.swift +++ b/RxSwift/Observables/Using.swift @@ -16,7 +16,7 @@ extension ObservableType { - parameter observableFactory: Factory function to obtain an observable sequence that depends on the obtained resource. - returns: An observable sequence whose lifetime controls the lifetime of the dependent resource object. */ - public static func using(_ resourceFactory: @escaping () throws -> Resource, observableFactory: @escaping (Resource) throws -> Observable) -> Observable { + public static func using(_ resourceFactory: @escaping @Sendable () throws -> Resource, observableFactory: @escaping @Sendable (Resource) throws -> Observable) -> Observable { Using(resourceFactory: resourceFactory, observableFactory: observableFactory) } } @@ -70,8 +70,8 @@ final private class Using: Producer ResourceType - typealias ObservableFactory = (ResourceType) throws -> Observable + typealias ResourceFactory = @Sendable () throws -> ResourceType + typealias ObservableFactory = @Sendable (ResourceType) throws -> Observable fileprivate let resourceFactory: ResourceFactory fileprivate let observableFactory: ObservableFactory diff --git a/RxSwift/Observables/WithLatestFrom.swift b/RxSwift/Observables/WithLatestFrom.swift index d2868121a..b1dc4e331 100644 --- a/RxSwift/Observables/WithLatestFrom.swift +++ b/RxSwift/Observables/WithLatestFrom.swift @@ -18,7 +18,7 @@ extension ObservableType { - parameter resultSelector: Function to invoke for each element from the self combined with the latest element from the second source, if any. - returns: An observable sequence containing the result of combining each element of the self with the latest element from the second source, if any, using the specified result selector function. */ - public func withLatestFrom(_ second: Source, resultSelector: @escaping (Element, Source.Element) throws -> ResultType) -> Observable { + public func withLatestFrom(_ second: Source, resultSelector: @escaping @Sendable (Element, Source.Element) throws -> ResultType) -> Observable { WithLatestFrom(first: self.asObservable(), second: second.asObservable(), resultSelector: resultSelector) } @@ -131,7 +131,7 @@ final private class WithLatestFromSecond: Producer { - typealias ResultSelector = (FirstType, SecondType) throws -> ResultType + typealias ResultSelector = @Sendable (FirstType, SecondType) throws -> ResultType fileprivate let first: Observable fileprivate let second: Observable diff --git a/RxSwift/Observables/Zip+Collection.swift b/RxSwift/Observables/Zip+Collection.swift index 2d7f8877c..9ac77316e 100644 --- a/RxSwift/Observables/Zip+Collection.swift +++ b/RxSwift/Observables/Zip+Collection.swift @@ -15,7 +15,7 @@ extension ObservableType { - parameter resultSelector: Function to invoke for each series of elements at corresponding indexes in the sources. - returns: An observable sequence containing the result of combining elements of the sources using the specified result selector function. */ - public static func zip(_ collection: Collection, resultSelector: @escaping ([Collection.Element.Element]) throws -> Element) -> Observable + public static func zip(_ collection: Collection, resultSelector: @escaping @Sendable ([Collection.Element.Element]) throws -> Element) -> Observable where Collection.Element: ObservableType { ZipCollectionType(sources: collection, resultSelector: resultSelector) } @@ -148,7 +148,7 @@ final private class ZipCollectionTypeSink: Producer where Collection.Element: ObservableConvertibleType { - typealias ResultSelector = ([Collection.Element.Element]) throws -> Result + typealias ResultSelector = @Sendable ([Collection.Element.Element]) throws -> Result let sources: Collection let resultSelector: ResultSelector diff --git a/RxSwift/Observables/Zip+arity.swift b/RxSwift/Observables/Zip+arity.swift index b6d876d1d..cbf52e399 100644 --- a/RxSwift/Observables/Zip+arity.swift +++ b/RxSwift/Observables/Zip+arity.swift @@ -21,7 +21,7 @@ extension ObservableType { - returns: An observable sequence containing the result of combining elements of the sources using the specified result selector function. */ public static func zip - (_ source1: O1, _ source2: O2, resultSelector: @escaping (O1.Element, O2.Element) throws -> Element) + (_ source1: O1, _ source2: O2, resultSelector: @escaping @Sendable (O1.Element, O2.Element) throws -> Element) -> Observable { return Zip2( source1: source1.asObservable(), source2: source2.asObservable(), @@ -94,7 +94,7 @@ final class ZipSink2_ : ZipSink { } final class Zip2 : Producer { - typealias ResultSelector = (E1, E2) throws -> Result + typealias ResultSelector = @Sendable (E1, E2) throws -> Result let source1: Observable let source2: Observable @@ -129,7 +129,7 @@ extension ObservableType { - returns: An observable sequence containing the result of combining elements of the sources using the specified result selector function. */ public static func zip - (_ source1: O1, _ source2: O2, _ source3: O3, resultSelector: @escaping (O1.Element, O2.Element, O3.Element) throws -> Element) + (_ source1: O1, _ source2: O2, _ source3: O3, resultSelector: @escaping @Sendable (O1.Element, O2.Element, O3.Element) throws -> Element) -> Observable { return Zip3( source1: source1.asObservable(), source2: source2.asObservable(), source3: source3.asObservable(), @@ -208,7 +208,7 @@ final class ZipSink3_ : ZipSink { } final class Zip3 : Producer { - typealias ResultSelector = (E1, E2, E3) throws -> Result + typealias ResultSelector = @Sendable (E1, E2, E3) throws -> Result let source1: Observable let source2: Observable @@ -245,7 +245,7 @@ extension ObservableType { - returns: An observable sequence containing the result of combining elements of the sources using the specified result selector function. */ public static func zip - (_ source1: O1, _ source2: O2, _ source3: O3, _ source4: O4, resultSelector: @escaping (O1.Element, O2.Element, O3.Element, O4.Element) throws -> Element) + (_ source1: O1, _ source2: O2, _ source3: O3, _ source4: O4, resultSelector: @escaping @Sendable (O1.Element, O2.Element, O3.Element, O4.Element) throws -> Element) -> Observable { return Zip4( source1: source1.asObservable(), source2: source2.asObservable(), source3: source3.asObservable(), source4: source4.asObservable(), @@ -330,7 +330,7 @@ final class ZipSink4_ : ZipSink : Producer { - typealias ResultSelector = (E1, E2, E3, E4) throws -> Result + typealias ResultSelector = @Sendable (E1, E2, E3, E4) throws -> Result let source1: Observable let source2: Observable @@ -369,7 +369,7 @@ extension ObservableType { - returns: An observable sequence containing the result of combining elements of the sources using the specified result selector function. */ public static func zip - (_ source1: O1, _ source2: O2, _ source3: O3, _ source4: O4, _ source5: O5, resultSelector: @escaping (O1.Element, O2.Element, O3.Element, O4.Element, O5.Element) throws -> Element) + (_ source1: O1, _ source2: O2, _ source3: O3, _ source4: O4, _ source5: O5, resultSelector: @escaping @Sendable (O1.Element, O2.Element, O3.Element, O4.Element, O5.Element) throws -> Element) -> Observable { return Zip5( source1: source1.asObservable(), source2: source2.asObservable(), source3: source3.asObservable(), source4: source4.asObservable(), source5: source5.asObservable(), @@ -460,7 +460,7 @@ final class ZipSink5_ : ZipSink : Producer { - typealias ResultSelector = (E1, E2, E3, E4, E5) throws -> Result + typealias ResultSelector = @Sendable (E1, E2, E3, E4, E5) throws -> Result let source1: Observable let source2: Observable @@ -501,7 +501,7 @@ extension ObservableType { - returns: An observable sequence containing the result of combining elements of the sources using the specified result selector function. */ public static func zip - (_ source1: O1, _ source2: O2, _ source3: O3, _ source4: O4, _ source5: O5, _ source6: O6, resultSelector: @escaping (O1.Element, O2.Element, O3.Element, O4.Element, O5.Element, O6.Element) throws -> Element) + (_ source1: O1, _ source2: O2, _ source3: O3, _ source4: O4, _ source5: O5, _ source6: O6, resultSelector: @escaping @Sendable (O1.Element, O2.Element, O3.Element, O4.Element, O5.Element, O6.Element) throws -> Element) -> Observable { return Zip6( source1: source1.asObservable(), source2: source2.asObservable(), source3: source3.asObservable(), source4: source4.asObservable(), source5: source5.asObservable(), source6: source6.asObservable(), @@ -598,7 +598,7 @@ final class ZipSink6_ : ZipSink< } final class Zip6 : Producer { - typealias ResultSelector = (E1, E2, E3, E4, E5, E6) throws -> Result + typealias ResultSelector = @Sendable (E1, E2, E3, E4, E5, E6) throws -> Result let source1: Observable let source2: Observable @@ -641,7 +641,7 @@ extension ObservableType { - returns: An observable sequence containing the result of combining elements of the sources using the specified result selector function. */ public static func zip - (_ source1: O1, _ source2: O2, _ source3: O3, _ source4: O4, _ source5: O5, _ source6: O6, _ source7: O7, resultSelector: @escaping (O1.Element, O2.Element, O3.Element, O4.Element, O5.Element, O6.Element, O7.Element) throws -> Element) + (_ source1: O1, _ source2: O2, _ source3: O3, _ source4: O4, _ source5: O5, _ source6: O6, _ source7: O7, resultSelector: @escaping @Sendable (O1.Element, O2.Element, O3.Element, O4.Element, O5.Element, O6.Element, O7.Element) throws -> Element) -> Observable { return Zip7( source1: source1.asObservable(), source2: source2.asObservable(), source3: source3.asObservable(), source4: source4.asObservable(), source5: source5.asObservable(), source6: source6.asObservable(), source7: source7.asObservable(), @@ -744,7 +744,7 @@ final class ZipSink7_ : ZipS } final class Zip7 : Producer { - typealias ResultSelector = (E1, E2, E3, E4, E5, E6, E7) throws -> Result + typealias ResultSelector = @Sendable (E1, E2, E3, E4, E5, E6, E7) throws -> Result let source1: Observable let source2: Observable @@ -789,7 +789,7 @@ extension ObservableType { - returns: An observable sequence containing the result of combining elements of the sources using the specified result selector function. */ public static func zip - (_ source1: O1, _ source2: O2, _ source3: O3, _ source4: O4, _ source5: O5, _ source6: O6, _ source7: O7, _ source8: O8, resultSelector: @escaping (O1.Element, O2.Element, O3.Element, O4.Element, O5.Element, O6.Element, O7.Element, O8.Element) throws -> Element) + (_ source1: O1, _ source2: O2, _ source3: O3, _ source4: O4, _ source5: O5, _ source6: O6, _ source7: O7, _ source8: O8, resultSelector: @escaping @Sendable (O1.Element, O2.Element, O3.Element, O4.Element, O5.Element, O6.Element, O7.Element, O8.Element) throws -> Element) -> Observable { return Zip8( source1: source1.asObservable(), source2: source2.asObservable(), source3: source3.asObservable(), source4: source4.asObservable(), source5: source5.asObservable(), source6: source6.asObservable(), source7: source7.asObservable(), source8: source8.asObservable(), @@ -898,7 +898,7 @@ final class ZipSink8_ : } final class Zip8 : Producer { - typealias ResultSelector = (E1, E2, E3, E4, E5, E6, E7, E8) throws -> Result + typealias ResultSelector = @Sendable (E1, E2, E3, E4, E5, E6, E7, E8) throws -> Result let source1: Observable let source2: Observable diff --git a/RxSwift/Observables/Zip.swift b/RxSwift/Observables/Zip.swift index 328a40ef7..cb198651c 100644 --- a/RxSwift/Observables/Zip.swift +++ b/RxSwift/Observables/Zip.swift @@ -85,7 +85,7 @@ final class ZipObserver : ObserverType , LockOwnerType , SynchronizedOnType { - typealias ValueSetter = (Element) -> Void + typealias ValueSetter = @Sendable (Element) -> Void private var parent: ZipSinkProtocol? diff --git a/RxSwift/ObserverType.swift b/RxSwift/ObserverType.swift index b7a66480e..db2db2a27 100644 --- a/RxSwift/ObserverType.swift +++ b/RxSwift/ObserverType.swift @@ -14,6 +14,7 @@ public protocol ObserverType { /// Notify observer about sequence event. /// /// - parameter event: Event that occurred. + @Sendable func on(_ event: Event) } diff --git a/RxSwift/Observers/AnonymousObserver.swift b/RxSwift/Observers/AnonymousObserver.swift index cbb42dc82..72892a63e 100644 --- a/RxSwift/Observers/AnonymousObserver.swift +++ b/RxSwift/Observers/AnonymousObserver.swift @@ -7,7 +7,7 @@ // final class AnonymousObserver: ObserverBase { - typealias EventHandler = (Event) -> Void + typealias EventHandler = @Sendable (Event) -> Void private let eventHandler : EventHandler diff --git a/RxSwift/SchedulerType.swift b/RxSwift/SchedulerType.swift index 6c8fe4a38..478b62bff 100644 --- a/RxSwift/SchedulerType.swift +++ b/RxSwift/SchedulerType.swift @@ -31,7 +31,7 @@ public protocol SchedulerType: ImmediateSchedulerType { - parameter action: Action to be executed. - returns: The disposable object used to cancel the scheduled action (best effort). */ - func scheduleRelative(_ state: StateType, dueTime: RxTimeInterval, action: @escaping (StateType) -> Disposable) -> Disposable + func scheduleRelative(_ state: StateType, dueTime: RxTimeInterval, action: @escaping @Sendable (StateType) -> Disposable) -> Disposable /** Schedules a periodic piece of work. @@ -42,7 +42,7 @@ public protocol SchedulerType: ImmediateSchedulerType { - parameter action: Action to be executed. - returns: The disposable object used to cancel the scheduled action (best effort). */ - func schedulePeriodic(_ state: StateType, startAfter: RxTimeInterval, period: RxTimeInterval, action: @escaping (StateType) -> StateType) -> Disposable + func schedulePeriodic(_ state: StateType, startAfter: RxTimeInterval, period: RxTimeInterval, action: @escaping @Sendable (StateType) -> StateType) -> Disposable } extension SchedulerType { @@ -55,13 +55,13 @@ extension SchedulerType { - parameter period: Period for running the work periodically. - returns: The disposable object used to cancel the scheduled recurring action (best effort). */ - public func schedulePeriodic(_ state: StateType, startAfter: RxTimeInterval, period: RxTimeInterval, action: @escaping (StateType) -> StateType) -> Disposable { + public func schedulePeriodic(_ state: StateType, startAfter: RxTimeInterval, period: RxTimeInterval, action: @escaping @Sendable (StateType) -> StateType) -> Disposable { let schedule = SchedulePeriodicRecursive(scheduler: self, startAfter: startAfter, period: period, action: action, state: state) return schedule.start() } - func scheduleRecursive(_ state: State, dueTime: RxTimeInterval, action: @escaping (State, AnyRecursiveScheduler) -> Void) -> Disposable { + func scheduleRecursive(_ state: State, dueTime: RxTimeInterval, action: @escaping @Sendable (State, AnyRecursiveScheduler) -> Void) -> Disposable { let scheduler = AnyRecursiveScheduler(scheduler: self, action: action) scheduler.schedule(state, dueTime: dueTime) diff --git a/RxSwift/Schedulers/CurrentThreadScheduler.swift b/RxSwift/Schedulers/CurrentThreadScheduler.swift index 16a7dd328..98b2adad8 100644 --- a/RxSwift/Schedulers/CurrentThreadScheduler.swift +++ b/RxSwift/Schedulers/CurrentThreadScheduler.swift @@ -87,7 +87,7 @@ public class CurrentThreadScheduler : ImmediateSchedulerType { - parameter action: Action to be executed. - returns: The disposable object used to cancel the scheduled action (best effort). */ - public func schedule(_ state: StateType, action: @escaping (StateType) -> Disposable) -> Disposable { + public func schedule(_ state: StateType, action: @escaping @Sendable (StateType) -> Disposable) -> Disposable { if CurrentThreadScheduler.isScheduleRequired { CurrentThreadScheduler.isScheduleRequired = false diff --git a/RxSwift/Schedulers/Internal/DispatchQueueConfiguration.swift b/RxSwift/Schedulers/Internal/DispatchQueueConfiguration.swift index 53f148dc4..a49814581 100644 --- a/RxSwift/Schedulers/Internal/DispatchQueueConfiguration.swift +++ b/RxSwift/Schedulers/Internal/DispatchQueueConfiguration.swift @@ -44,7 +44,7 @@ extension DispatchQueueConfiguration { // Need more info on this. // It looks like just setting timer to fire and not holding a reference to it // until deadline causes timer cancellation. - var timerReference: DispatchSourceTimer? = timer + nonisolated(unsafe) var timerReference: DispatchSourceTimer? = timer let cancelTimer = Disposables.create { timerReference?.cancel() timerReference = nil @@ -78,7 +78,7 @@ extension DispatchQueueConfiguration { // Need more info on this. // It looks like just setting timer to fire and not holding a reference to it // until deadline causes timer cancellation. - var timerReference: DispatchSourceTimer? = timer + nonisolated(unsafe) var timerReference: DispatchSourceTimer? = timer let cancelTimer = Disposables.create { timerReference?.cancel() timerReference = nil diff --git a/RxSwift/Schedulers/Internal/ScheduledItem.swift b/RxSwift/Schedulers/Internal/ScheduledItem.swift index 3d790d7af..a1de958d9 100644 --- a/RxSwift/Schedulers/Internal/ScheduledItem.swift +++ b/RxSwift/Schedulers/Internal/ScheduledItem.swift @@ -9,7 +9,7 @@ struct ScheduledItem : ScheduledItemType , InvocableType { - typealias Action = (T) -> Disposable + typealias Action = @Sendable (T) -> Disposable private let action: Action private let state: T diff --git a/RxSwift/Schedulers/RecursiveScheduler.swift b/RxSwift/Schedulers/RecursiveScheduler.swift index 0ee78cd18..a017fc4ef 100644 --- a/RxSwift/Schedulers/RecursiveScheduler.swift +++ b/RxSwift/Schedulers/RecursiveScheduler.swift @@ -37,7 +37,7 @@ final class AnyRecursiveScheduler { - parameter dueTime: Relative time after which to execute the recursive action. */ func schedule(_ state: State, dueTime: RxTimeInterval) { - var scheduleState: ScheduleState = .initial + nonisolated(unsafe) var scheduleState: ScheduleState = .initial let d = self.scheduler.scheduleRelative(state, dueTime: dueTime) { state -> Disposable in // best effort @@ -88,7 +88,7 @@ final class AnyRecursiveScheduler { /// /// - parameter state: State passed to the action to be executed. func schedule(_ state: State) { - var scheduleState: ScheduleState = .initial + nonisolated(unsafe) var scheduleState: ScheduleState = .initial let d = self.scheduler.schedule(state) { state -> Disposable in // best effort @@ -135,6 +135,7 @@ final class AnyRecursiveScheduler { } } + @Sendable func dispose() { self.lock.performLocked { self.action = nil @@ -144,7 +145,7 @@ final class AnyRecursiveScheduler { } /// Type erased recursive scheduler. -final class RecursiveImmediateScheduler { +final class RecursiveImmediateScheduler: @unchecked Sendable { typealias Action = (_ state: State, _ recurse: (State) -> Void) -> Void private var lock = SpinLock() @@ -164,7 +165,7 @@ final class RecursiveImmediateScheduler { /// /// - parameter state: State passed to the action to be executed. func schedule(_ state: State) { - var scheduleState: ScheduleState = .initial + nonisolated(unsafe) var scheduleState: ScheduleState = .initial let d = self.scheduler.schedule(state) { state -> Disposable in // best effort @@ -211,6 +212,7 @@ final class RecursiveImmediateScheduler { } } + @Sendable func dispose() { self.lock.performLocked { self.action = nil diff --git a/RxSwift/Schedulers/SchedulerServices+Emulation.swift b/RxSwift/Schedulers/SchedulerServices+Emulation.swift index cab2bc8b3..81ae5ad93 100644 --- a/RxSwift/Schedulers/SchedulerServices+Emulation.swift +++ b/RxSwift/Schedulers/SchedulerServices+Emulation.swift @@ -12,7 +12,7 @@ enum SchedulePeriodicRecursiveCommand { } final class SchedulePeriodicRecursive { - typealias RecursiveAction = (State) -> State + typealias RecursiveAction = @Sendable (State) -> State typealias RecursiveScheduler = AnyRecursiveScheduler private let scheduler: SchedulerType @@ -34,7 +34,8 @@ final class SchedulePeriodicRecursive { func start() -> Disposable { self.scheduler.scheduleRecursive(SchedulePeriodicRecursiveCommand.tick, dueTime: self.startAfter, action: self.tick) } - + + @Sendable func tick(_ command: SchedulePeriodicRecursiveCommand, scheduler: RecursiveScheduler) { // Tries to emulate periodic scheduling as best as possible. // The problem that could arise is if handling periodic ticks take too long, or diff --git a/RxSwift/Schedulers/VirtualTimeScheduler.swift b/RxSwift/Schedulers/VirtualTimeScheduler.swift index 4f55d29d7..0af5d340f 100644 --- a/RxSwift/Schedulers/VirtualTimeScheduler.swift +++ b/RxSwift/Schedulers/VirtualTimeScheduler.swift @@ -63,7 +63,7 @@ open class VirtualTimeScheduler - parameter action: Action to be executed. - returns: The disposable object used to cancel the scheduled action (best effort). */ - public func schedule(_ state: StateType, action: @escaping (StateType) -> Disposable) -> Disposable { + public func schedule(_ state: StateType, action: @escaping @Sendable (StateType) -> Disposable) -> Disposable { return self.scheduleRelative(state, dueTime: .microseconds(0)) { a in return action(a) } @@ -77,7 +77,7 @@ open class VirtualTimeScheduler - parameter action: Action to be executed. - returns: The disposable object used to cancel the scheduled action (best effort). */ - public func scheduleRelative(_ state: StateType, dueTime: RxTimeInterval, action: @escaping (StateType) -> Disposable) -> Disposable { + public func scheduleRelative(_ state: StateType, dueTime: RxTimeInterval, action: @escaping @Sendable (StateType) -> Disposable) -> Disposable { let time = self.now.addingDispatchInterval(dueTime) let absoluteTime = self.converter.convertToVirtualTime(time) let adjustedTime = self.adjustScheduledTime(absoluteTime) @@ -92,7 +92,7 @@ open class VirtualTimeScheduler - parameter action: Action to be executed. - returns: The disposable object used to cancel the scheduled action (best effort). */ - public func scheduleRelativeVirtual(_ state: StateType, dueTime: VirtualTimeInterval, action: @escaping (StateType) -> Disposable) -> Disposable { + public func scheduleRelativeVirtual(_ state: StateType, dueTime: VirtualTimeInterval, action: @escaping @Sendable (StateType) -> Disposable) -> Disposable { let time = self.converter.offsetVirtualTime(self.clock, offset: dueTime) return self.scheduleAbsoluteVirtual(state, time: time, action: action) } @@ -105,7 +105,7 @@ open class VirtualTimeScheduler - parameter action: Action to be executed. - returns: The disposable object used to cancel the scheduled action (best effort). */ - public func scheduleAbsoluteVirtual(_ state: StateType, time: VirtualTime, action: @escaping (StateType) -> Disposable) -> Disposable { + public func scheduleAbsoluteVirtual(_ state: StateType, time: VirtualTime, action: @escaping @Sendable (StateType) -> Disposable) -> Disposable { MainScheduler.ensureExecutingOnScheduler() let compositeDisposable = CompositeDisposable() @@ -234,7 +234,7 @@ extension VirtualTimeScheduler: CustomDebugStringConvertible { final class VirtualSchedulerItem(_ seed: A, accumulator: @escaping (A, Element) throws -> A) + public func scan(_ seed: A, accumulator: @escaping @Sendable (A, Element) throws -> A) -> Observable { return Scan(source: self.asObservable(), seed: seed) { acc, element in let currentAcc = acc diff --git a/RxSwift/Observables/TakeWithPredicate.swift b/RxSwift/Observables/TakeWithPredicate.swift index 09d46fee2..2ef69a6d4 100644 --- a/RxSwift/Observables/TakeWithPredicate.swift +++ b/RxSwift/Observables/TakeWithPredicate.swift @@ -46,7 +46,7 @@ extension ObservableType { - parameter predicate: A function to test each element for a condition. - returns: An observable sequence that contains the elements from the input sequence that occur before the element at which the test no longer passes. */ - public func take(while predicate: @escaping (Element) throws -> Bool, + public func take(while predicate: @escaping @Sendable (Element) throws -> Bool, behavior: TakeBehavior = .exclusive) -> Observable { take(until: { try !predicate($0) }, behavior: behavior) @@ -91,7 +91,7 @@ extension ObservableType { - returns: An observable sequence that contains the elements from the input sequence that occur before the element at which the test no longer passes. */ @available(*, deprecated, renamed: "take(while:)") - public func takeWhile(_ predicate: @escaping (Element) throws -> Bool) + public func takeWhile(_ predicate: @escaping @Sendable (Element) throws -> Bool) -> Observable { take(until: { try !predicate($0) }, behavior: .exclusive) } diff --git a/RxSwift/Observables/WithUnretained.swift b/RxSwift/Observables/WithUnretained.swift index 8466e89c5..2201ad635 100644 --- a/RxSwift/Observables/WithUnretained.swift +++ b/RxSwift/Observables/WithUnretained.swift @@ -20,7 +20,7 @@ extension ObservableType { */ public func withUnretained( _ obj: Object, - resultSelector: @escaping (Object, Element) -> Out + resultSelector: @escaping @Sendable (Object, Element) -> Out ) -> Observable { map { [weak obj] element -> Out in guard let obj = obj else { throw UnretainedError.failedRetaining } diff --git a/RxSwift/Schedulers/ConcurrentDispatchQueueScheduler.swift b/RxSwift/Schedulers/ConcurrentDispatchQueueScheduler.swift index 02c47c917..ac2cde22f 100644 --- a/RxSwift/Schedulers/ConcurrentDispatchQueueScheduler.swift +++ b/RxSwift/Schedulers/ConcurrentDispatchQueueScheduler.swift @@ -51,7 +51,7 @@ public class ConcurrentDispatchQueueScheduler: SchedulerType { - parameter action: Action to be executed. - returns: The disposable object used to cancel the scheduled action (best effort). */ - public final func schedule(_ state: StateType, action: @escaping (StateType) -> Disposable) -> Disposable { + public final func schedule(_ state: StateType, action: @escaping @Sendable (StateType) -> Disposable) -> Disposable { self.configuration.schedule(state, action: action) } @@ -63,7 +63,7 @@ public class ConcurrentDispatchQueueScheduler: SchedulerType { - parameter action: Action to be executed. - returns: The disposable object used to cancel the scheduled action (best effort). */ - public final func scheduleRelative(_ state: StateType, dueTime: RxTimeInterval, action: @escaping (StateType) -> Disposable) -> Disposable { + public final func scheduleRelative(_ state: StateType, dueTime: RxTimeInterval, action: @escaping @Sendable (StateType) -> Disposable) -> Disposable { self.configuration.scheduleRelative(state, dueTime: dueTime, action: action) } @@ -76,7 +76,7 @@ public class ConcurrentDispatchQueueScheduler: SchedulerType { - parameter action: Action to be executed. - returns: The disposable object used to cancel the scheduled action (best effort). */ - public func schedulePeriodic(_ state: StateType, startAfter: RxTimeInterval, period: RxTimeInterval, action: @escaping (StateType) -> StateType) -> Disposable { + public func schedulePeriodic(_ state: StateType, startAfter: RxTimeInterval, period: RxTimeInterval, action: @escaping @Sendable (StateType) -> StateType) -> Disposable { self.configuration.schedulePeriodic(state, startAfter: startAfter, period: period, action: action) } } diff --git a/RxSwift/Schedulers/ConcurrentMainScheduler.swift b/RxSwift/Schedulers/ConcurrentMainScheduler.swift index c438d7d4d..8d1e5a11b 100644 --- a/RxSwift/Schedulers/ConcurrentMainScheduler.swift +++ b/RxSwift/Schedulers/ConcurrentMainScheduler.swift @@ -42,14 +42,14 @@ public final class ConcurrentMainScheduler : SchedulerType { - parameter action: Action to be executed. - returns: The disposable object used to cancel the scheduled action (best effort). */ - public func schedule(_ state: StateType, action: @escaping (StateType) -> Disposable) -> Disposable { + public func schedule(_ state: StateType, action: @escaping @Sendable (StateType) -> Disposable) -> Disposable { if DispatchQueue.isMain { return action(state) } let cancel = SingleAssignmentDisposable() - self.mainQueue.async { + self.mainQueue.async { @Sendable () in if cancel.isDisposed { return } @@ -68,7 +68,7 @@ public final class ConcurrentMainScheduler : SchedulerType { - parameter action: Action to be executed. - returns: The disposable object used to cancel the scheduled action (best effort). */ - public final func scheduleRelative(_ state: StateType, dueTime: RxTimeInterval, action: @escaping (StateType) -> Disposable) -> Disposable { + public final func scheduleRelative(_ state: StateType, dueTime: RxTimeInterval, action: @escaping @Sendable (StateType) -> Disposable) -> Disposable { self.mainScheduler.scheduleRelative(state, dueTime: dueTime, action: action) } @@ -81,7 +81,7 @@ public final class ConcurrentMainScheduler : SchedulerType { - parameter action: Action to be executed. - returns: The disposable object used to cancel the scheduled action (best effort). */ - public func schedulePeriodic(_ state: StateType, startAfter: RxTimeInterval, period: RxTimeInterval, action: @escaping (StateType) -> StateType) -> Disposable { + public func schedulePeriodic(_ state: StateType, startAfter: RxTimeInterval, period: RxTimeInterval, action: @escaping @Sendable (StateType) -> StateType) -> Disposable { self.mainScheduler.schedulePeriodic(state, startAfter: startAfter, period: period, action: action) } } diff --git a/RxSwift/Schedulers/Internal/DispatchQueueConfiguration.swift b/RxSwift/Schedulers/Internal/DispatchQueueConfiguration.swift index a49814581..779257a73 100644 --- a/RxSwift/Schedulers/Internal/DispatchQueueConfiguration.swift +++ b/RxSwift/Schedulers/Internal/DispatchQueueConfiguration.swift @@ -15,10 +15,10 @@ struct DispatchQueueConfiguration { } extension DispatchQueueConfiguration { - func schedule(_ state: StateType, action: @escaping (StateType) -> Disposable) -> Disposable { + func schedule(_ state: StateType, action: @escaping @Sendable (StateType) -> Disposable) -> Disposable { let cancel = SingleAssignmentDisposable() - self.queue.async { + self.queue.async { @Sendable () in if cancel.isDisposed { return } @@ -30,7 +30,7 @@ extension DispatchQueueConfiguration { return cancel } - func scheduleRelative(_ state: StateType, dueTime: RxTimeInterval, action: @escaping (StateType) -> Disposable) -> Disposable { + func scheduleRelative(_ state: StateType, dueTime: RxTimeInterval, action: @escaping @Sendable (StateType) -> Disposable) -> Disposable { let deadline = DispatchTime.now() + dueTime let compositeDisposable = CompositeDisposable() @@ -50,7 +50,7 @@ extension DispatchQueueConfiguration { timerReference = nil } - timer.setEventHandler(handler: { + timer.setEventHandler(handler: { @Sendable () in if compositeDisposable.isDisposed { return } @@ -64,10 +64,10 @@ extension DispatchQueueConfiguration { return compositeDisposable } - func schedulePeriodic(_ state: StateType, startAfter: RxTimeInterval, period: RxTimeInterval, action: @escaping (StateType) -> StateType) -> Disposable { + func schedulePeriodic(_ state: StateType, startAfter: RxTimeInterval, period: RxTimeInterval, action: @escaping @Sendable (StateType) -> StateType) -> Disposable { let initial = DispatchTime.now() + startAfter - var timerState = state + nonisolated(unsafe) var timerState = state let timer = DispatchSource.makeTimerSource(queue: self.queue) timer.schedule(deadline: initial, repeating: period, leeway: self.leeway) @@ -84,7 +84,7 @@ extension DispatchQueueConfiguration { timerReference = nil } - timer.setEventHandler(handler: { + timer.setEventHandler(handler: { @Sendable () in if cancelTimer.isDisposed { return } diff --git a/RxSwift/Schedulers/MainScheduler.swift b/RxSwift/Schedulers/MainScheduler.swift index f6a507f3f..1622693d6 100644 --- a/RxSwift/Schedulers/MainScheduler.swift +++ b/RxSwift/Schedulers/MainScheduler.swift @@ -56,7 +56,7 @@ public final class MainScheduler : SerialDispatchQueueScheduler { #endif } - override func scheduleInternal(_ state: StateType, action: @escaping (StateType) -> Disposable) -> Disposable { + override func scheduleInternal(_ state: StateType, action: @escaping @Sendable (StateType) -> Disposable) -> Disposable { let previousNumberEnqueued = increment(self.numberEnqueued) if DispatchQueue.isMain && previousNumberEnqueued == 0 { diff --git a/RxSwift/Schedulers/OperationQueueScheduler.swift b/RxSwift/Schedulers/OperationQueueScheduler.swift index f0ad3d3ce..cef2b82d2 100644 --- a/RxSwift/Schedulers/OperationQueueScheduler.swift +++ b/RxSwift/Schedulers/OperationQueueScheduler.swift @@ -32,7 +32,7 @@ public class OperationQueueScheduler: ImmediateSchedulerType { - parameter action: Action to execute recursively. The last parameter passed to the action is used to trigger recursive scheduling of the action, passing in recursive invocation state. - returns: The disposable object used to cancel the scheduled action (best effort). */ - public func schedule(_ state: StateType, action: @escaping (StateType) -> Disposable) -> Disposable { + public func schedule(_ state: StateType, action: @escaping @Sendable (StateType) -> Disposable) -> Disposable { let cancel = SingleAssignmentDisposable() let operation = BlockOperation { diff --git a/RxSwift/Schedulers/SerialDispatchQueueScheduler.swift b/RxSwift/Schedulers/SerialDispatchQueueScheduler.swift index bb0013c8f..a6586f0a0 100644 --- a/RxSwift/Schedulers/SerialDispatchQueueScheduler.swift +++ b/RxSwift/Schedulers/SerialDispatchQueueScheduler.swift @@ -96,11 +96,11 @@ public class SerialDispatchQueueScheduler : SchedulerType { - parameter action: Action to be executed. - returns: The disposable object used to cancel the scheduled action (best effort). */ - public final func schedule(_ state: StateType, action: @escaping (StateType) -> Disposable) -> Disposable { + public final func schedule(_ state: StateType, action: @escaping @Sendable (StateType) -> Disposable) -> Disposable { self.scheduleInternal(state, action: action) } - func scheduleInternal(_ state: StateType, action: @escaping (StateType) -> Disposable) -> Disposable { + func scheduleInternal(_ state: StateType, action: @escaping @Sendable (StateType) -> Disposable) -> Disposable { self.configuration.schedule(state, action: action) } @@ -112,7 +112,7 @@ public class SerialDispatchQueueScheduler : SchedulerType { - parameter action: Action to be executed. - returns: The disposable object used to cancel the scheduled action (best effort). */ - public final func scheduleRelative(_ state: StateType, dueTime: RxTimeInterval, action: @escaping (StateType) -> Disposable) -> Disposable { + public final func scheduleRelative(_ state: StateType, dueTime: RxTimeInterval, action: @escaping @Sendable (StateType) -> Disposable) -> Disposable { self.configuration.scheduleRelative(state, dueTime: dueTime, action: action) } @@ -125,7 +125,7 @@ public class SerialDispatchQueueScheduler : SchedulerType { - parameter action: Action to be executed. - returns: The disposable object used to cancel the scheduled action (best effort). */ - public func schedulePeriodic(_ state: StateType, startAfter: RxTimeInterval, period: RxTimeInterval, action: @escaping (StateType) -> StateType) -> Disposable { + public func schedulePeriodic(_ state: StateType, startAfter: RxTimeInterval, period: RxTimeInterval, action: @escaping @Sendable (StateType) -> StateType) -> Disposable { self.configuration.schedulePeriodic(state, startAfter: startAfter, period: period, action: action) } } diff --git a/RxSwift/Traits/Infallible/Infallible+Create.swift b/RxSwift/Traits/Infallible/Infallible+Create.swift index e71e42a06..a40076561 100644 --- a/RxSwift/Traits/Infallible/Infallible+Create.swift +++ b/RxSwift/Traits/Infallible/Infallible+Create.swift @@ -27,9 +27,9 @@ extension Infallible { - parameter subscribe: Implementation of the resulting observable sequence's `subscribe` method. - returns: The observable sequence with the specified implementation for the `subscribe` method. */ - public static func create(subscribe: @escaping (@escaping InfallibleObserver) -> Disposable) -> Infallible { - let source = Observable.create { observer in - subscribe { event in + public static func create(subscribe: @escaping @Sendable (@escaping InfallibleObserver) -> Disposable) -> Infallible { + let source = Observable.create { @Sendable observer in + subscribe { @Sendable event in switch event { case .next(let element): observer.onNext(element) diff --git a/RxSwift/Traits/Infallible/Infallible+Operators.swift b/RxSwift/Traits/Infallible/Infallible+Operators.swift index cbdd2bdb9..d970bc228 100644 --- a/RxSwift/Traits/Infallible/Infallible+Operators.swift +++ b/RxSwift/Traits/Infallible/Infallible+Operators.swift @@ -66,7 +66,7 @@ extension InfallibleType { - parameter observableFactory: Observable factory function to invoke for each observer that subscribes to the resulting sequence. - returns: An observable sequence whose observers trigger an invocation of the given observable factory function. */ - public static func deferred(_ observableFactory: @escaping () throws -> Infallible) + public static func deferred(_ observableFactory: @escaping @Sendable () throws -> Infallible) -> Infallible { Infallible(.deferred { try observableFactory().asObservable() }) } @@ -479,7 +479,7 @@ extension InfallibleType { - parameter accumulator: An accumulator function to be invoked on each element. - returns: An observable sequence containing the accumulated values. */ - public func scan(_ seed: Seed, accumulator: @escaping (Seed, Element) -> Seed) + public func scan(_ seed: Seed, accumulator: @escaping @Sendable (Seed, Element) -> Seed) -> Infallible { Infallible(asObservable().scan(seed, accumulator: accumulator)) } @@ -555,7 +555,7 @@ extension InfallibleType { - parameter predicate: A function to test each element for a condition. - returns: An observable sequence that contains the elements from the input sequence that occur before the element at which the test no longer passes. */ - public func take(while predicate: @escaping (Element) throws -> Bool, + public func take(while predicate: @escaping @Sendable (Element) throws -> Bool, behavior: TakeBehavior = .exclusive) -> Infallible { Infallible(asObservable().take(while: predicate, behavior: behavior)) @@ -662,7 +662,7 @@ extension InfallibleType { */ public func withUnretained( _ obj: Object, - resultSelector: @escaping (Object, Element) -> Out + resultSelector: @escaping @Sendable (Object, Element) -> Out ) -> Infallible { Infallible(self.asObservable().withUnretained(obj, resultSelector: resultSelector)) } diff --git a/RxSwift/Traits/Infallible/ObservableConvertibleType+Infallible.swift b/RxSwift/Traits/Infallible/ObservableConvertibleType+Infallible.swift index d0f111c94..a84bad631 100644 --- a/RxSwift/Traits/Infallible/ObservableConvertibleType+Infallible.swift +++ b/RxSwift/Traits/Infallible/ObservableConvertibleType+Infallible.swift @@ -29,7 +29,7 @@ public extension ObservableConvertibleType { /// - parameter onErrorRecover: Recover with the this infallible closure /// /// - returns: `Infallible` - func asInfallible(onErrorRecover: @escaping (Swift.Error) -> Infallible) -> Infallible { + func asInfallible(onErrorRecover: @escaping @Sendable (Swift.Error) -> Infallible) -> Infallible { Infallible(asObservable().catch { onErrorRecover($0).asObservable() }) } } diff --git a/RxSwift/Traits/PrimitiveSequence/Maybe.swift b/RxSwift/Traits/PrimitiveSequence/Maybe.swift index ef153ae04..eac57e0b1 100644 --- a/RxSwift/Traits/PrimitiveSequence/Maybe.swift +++ b/RxSwift/Traits/PrimitiveSequence/Maybe.swift @@ -37,7 +37,7 @@ extension PrimitiveSequenceType where Trait == MaybeTrait { - parameter subscribe: Implementation of the resulting observable sequence's `subscribe` method. - returns: The observable sequence with the specified implementation for the `subscribe` method. */ - public static func create(subscribe: @escaping (@escaping MaybeObserver) -> Disposable) -> PrimitiveSequence { + public static func create(subscribe: @escaping @Sendable (@escaping MaybeObserver) -> Disposable) -> PrimitiveSequence { let source = Observable.create { observer in return subscribe { event in switch event { @@ -60,7 +60,7 @@ extension PrimitiveSequenceType where Trait == MaybeTrait { - returns: Subscription for `observer` that can be used to cancel production of sequence elements and free resources. */ - public func subscribe(_ observer: @escaping (MaybeEvent) -> Void) -> Disposable { + public func subscribe(_ observer: @escaping @Sendable (MaybeEvent) -> Void) -> Disposable { nonisolated(unsafe) var stopped = false return self.primitiveSequence.asObservable().subscribe { event in if stopped { return } diff --git a/RxSwift/Traits/PrimitiveSequence/PrimitiveSequence.swift b/RxSwift/Traits/PrimitiveSequence/PrimitiveSequence.swift index 3837b47b8..8bbd7a4bf 100644 --- a/RxSwift/Traits/PrimitiveSequence/PrimitiveSequence.swift +++ b/RxSwift/Traits/PrimitiveSequence/PrimitiveSequence.swift @@ -58,7 +58,7 @@ extension PrimitiveSequence { - parameter observableFactory: Observable factory function to invoke for each observer that subscribes to the resulting sequence. - returns: An observable sequence whose observers trigger an invocation of the given observable factory function. */ - public static func deferred(_ observableFactory: @escaping () throws -> PrimitiveSequence) + public static func deferred(_ observableFactory: @escaping @Sendable () throws -> PrimitiveSequence) -> PrimitiveSequence { return PrimitiveSequence(raw: Observable.deferred { try observableFactory().asObservable() @@ -176,7 +176,7 @@ extension PrimitiveSequence { - returns: An observable sequence containing the source sequence's elements, followed by the elements produced by the handler's resulting observable sequence in case an error occurred. */ @available(*, deprecated, renamed: "catch(_:)") - public func catchError(_ handler: @escaping (Swift.Error) throws -> PrimitiveSequence) + public func catchError(_ handler: @escaping @Sendable (Swift.Error) throws -> PrimitiveSequence) -> PrimitiveSequence { `catch`(handler) } @@ -189,7 +189,7 @@ extension PrimitiveSequence { - parameter handler: Error handler function, producing another observable sequence. - returns: An observable sequence containing the source sequence's elements, followed by the elements produced by the handler's resulting observable sequence in case an error occurred. */ - public func `catch`(_ handler: @escaping (Swift.Error) throws -> PrimitiveSequence) + public func `catch`(_ handler: @escaping @Sendable (Swift.Error) throws -> PrimitiveSequence) -> PrimitiveSequence { PrimitiveSequence(raw: self.source.catch { try handler($0).asObservable() }) } @@ -216,7 +216,7 @@ extension PrimitiveSequence { - parameter notificationHandler: A handler that is passed an observable sequence of errors raised by the source observable and returns and observable that either continues, completes or errors. This behavior is then applied to the source observable. - returns: An observable sequence producing the elements of the given sequence repeatedly until it terminates successfully or is notified to error or complete. */ - public func retry(when notificationHandler: @escaping (Observable) -> TriggerObservable) + public func retry(when notificationHandler: @escaping @Sendable (Observable) -> TriggerObservable) -> PrimitiveSequence { PrimitiveSequence(raw: self.source.retry(when: notificationHandler)) } @@ -231,7 +231,7 @@ extension PrimitiveSequence { - returns: An observable sequence producing the elements of the given sequence repeatedly until it terminates successfully or is notified to error or complete. */ @available(*, deprecated, renamed: "retry(when:)") - public func retryWhen(_ notificationHandler: @escaping (Observable) -> TriggerObservable) + public func retryWhen(_ notificationHandler: @escaping @Sendable (Observable) -> TriggerObservable) -> PrimitiveSequence { retry(when: notificationHandler) } @@ -245,7 +245,7 @@ extension PrimitiveSequence { - parameter notificationHandler: A handler that is passed an observable sequence of errors raised by the source observable and returns and observable that either continues, completes or errors. This behavior is then applied to the source observable. - returns: An observable sequence producing the elements of the given sequence repeatedly until it terminates successfully or is notified to error or complete. */ - public func retry(when notificationHandler: @escaping (Observable) -> TriggerObservable) + public func retry(when notificationHandler: @escaping @Sendable (Observable) -> TriggerObservable) -> PrimitiveSequence { PrimitiveSequence(raw: self.source.retry(when: notificationHandler)) } @@ -260,7 +260,7 @@ extension PrimitiveSequence { - returns: An observable sequence producing the elements of the given sequence repeatedly until it terminates successfully or is notified to error or complete. */ @available(*, deprecated, renamed: "retry(when:)") - public func retryWhen(_ notificationHandler: @escaping (Observable) -> TriggerObservable) + public func retryWhen(_ notificationHandler: @escaping @Sendable (Observable) -> TriggerObservable) -> PrimitiveSequence { retry(when: notificationHandler) } @@ -288,7 +288,7 @@ extension PrimitiveSequence { - parameter primitiveSequenceFactory: Factory function to obtain an observable sequence that depends on the obtained resource. - returns: An observable sequence whose lifetime controls the lifetime of the dependent resource object. */ - public static func using(_ resourceFactory: @escaping @Sendable () throws -> Resource, primitiveSequenceFactory: @escaping (Resource) throws -> PrimitiveSequence) + public static func using(_ resourceFactory: @escaping @Sendable () throws -> Resource, primitiveSequenceFactory: @escaping @Sendable (Resource) throws -> PrimitiveSequence) -> PrimitiveSequence { PrimitiveSequence(raw: Observable.using(resourceFactory, observableFactory: { (resource: Resource) throws -> Observable in return try primitiveSequenceFactory(resource).asObservable() From 347531848d04c1096bf90c30704f086846cae5e2 Mon Sep 17 00:00:00 2001 From: Andrei Ardelean <> Date: Mon, 21 Oct 2024 13:21:07 +0300 Subject: [PATCH 05/11] Add @MainActor to closures that should be called on main thread. Fix introduced warnings --- RxCocoa/Common/ControlTarget.swift | 4 +- RxCocoa/Common/DelegateProxyType.swift | 15 +- .../NSObject+Rx+KVORepresentable.swift | 4 +- .../NSObject+Rx+RawRepresentable.swift | 4 +- RxCocoa/Foundation/NSObject+Rx.swift | 2 +- RxCocoa/Foundation/URLSession+Rx.swift | 2 +- .../Traits/Driver/Driver+Subscription.swift | 12 +- .../ObservableConvertibleType+Driver.swift | 2 +- ...rvableConvertibleType+SharedSequence.swift | 2 +- .../SchedulerType+SharedSequence.swift | 2 +- .../SharedSequence+Operators+arity.swift | 2 +- .../SharedSequence+Operators.swift | 6 +- .../SharedSequence/SharedSequence.swift | 2 +- .../ObservableConvertibleType+Signal.swift | 2 +- ...ollectionViewReactiveArrayDataSource.swift | 6 +- .../iOS/DataSources/RxPickerViewAdapter.swift | 12 +- .../RxTableViewReactiveArrayDataSource.swift | 6 +- .../RxCollectionViewDelegateProxy.swift | 1 + .../Proxies/RxTableViewDelegateProxy.swift | 1 + .../iOS/Proxies/RxTextViewDelegateProxy.swift | 1 + RxCocoa/iOS/UIActivityIndicatorView+Rx.swift | 16 +- RxCocoa/iOS/UIApplication+Rx.swift | 2 +- RxCocoa/iOS/UIBarButtonItem+Rx.swift | 2 +- RxCocoa/iOS/UIButton+Rx.swift | 16 +- RxCocoa/iOS/UICollectionView+Rx.swift | 4 +- RxCocoa/iOS/UIControl+Rx.swift | 16 +- RxCocoa/iOS/UIPickerView+Rx.swift | 21 +- RxCocoa/iOS/UIRefreshControl+Rx.swift | 12 +- RxCocoa/iOS/UIScrollView+Rx.swift | 4 +- RxCocoa/iOS/UISearchBar+Rx.swift | 28 +- RxCocoa/iOS/UISegmentedControl+Rx.swift | 12 +- RxCocoa/iOS/UITableView+Rx.swift | 4 +- RxCocoa/iOS/UITextView+Rx.swift | 68 +++-- RxCocoa/macOS/NSControl+Rx.swift | 4 +- .../RxCLLocationManagerDelegateProxy.swift | 2 +- .../RxImagePickerDelegateProxy.swift | 1 + .../TableViewSectionedDataSource.swift | 34 +-- .../Mocks/MockGitHubAPI.swift | 8 +- .../Mocks/MockWireframe.swift | 8 +- .../Mocks/NotImplementedStubs.swift | 8 +- .../TestScheduler+MarbleTests.swift | 6 +- .../GitHubSearchRepositories.swift | 11 +- .../UIImagePickerController+RxCreate.swift | 58 +++-- RxExample/RxExample/Feedbacks.swift | 53 ++-- .../RxExample/Observable+Extensions.swift | 8 +- .../Services/ActivityIndicator.swift | 8 +- .../Services/GeolocationService.swift | 4 +- .../UIImageView+DownloadableImage.swift | 28 +- RxSwift/Schedulers/MainScheduler.swift | 39 +++ RxTest/Schedulers/TestScheduler.swift | 12 +- Tests/RxCocoaTests/DelegateProxyTest.swift | 44 ++-- Tests/RxCocoaTests/KVOObservableTests.swift | 244 +++++++++--------- Tests/RxCocoaTests/RxTest+Controls.swift | 12 +- Tests/RxCocoaTests/SentMessageTest.swift | 88 +++---- Tests/RxCocoaTests/SharedSequence+Test.swift | 6 +- Tests/RxSwiftTests/RecursiveLockTest.swift | 6 +- .../RxSwiftTests/SharingSchedulerTests.swift | 12 +- Tests/XCTest+AllTests.swift | 4 +- 58 files changed, 553 insertions(+), 448 deletions(-) diff --git a/RxCocoa/Common/ControlTarget.swift b/RxCocoa/Common/ControlTarget.swift index f6421deb5..1cb06d40d 100644 --- a/RxCocoa/Common/ControlTarget.swift +++ b/RxCocoa/Common/ControlTarget.swift @@ -77,7 +77,9 @@ final class ControlTarget: RxTarget { override func dispose() { super.dispose() #if os(iOS) || os(tvOS) || os(visionOS) - self.control?.removeTarget(self, action: self.selector, for: self.controlEvents) + MainScheduler.assumeMainActor(execute: { + self.control?.removeTarget(self, action: self.selector, for: self.controlEvents) + }) #elseif os(macOS) self.control?.target = nil self.control?.action = nil diff --git a/RxCocoa/Common/DelegateProxyType.swift b/RxCocoa/Common/DelegateProxyType.swift index 594172971..32eecca9f 100644 --- a/RxCocoa/Common/DelegateProxyType.swift +++ b/RxCocoa/Common/DelegateProxyType.swift @@ -151,7 +151,7 @@ extension DelegateProxyType { /// When make 'Rx*DelegateProxy' subclass, call 'Rx*DelegateProxySubclass.register(for:_)' 1 time, or use it in DelegateProxyFactory /// 'Rx*DelegateProxy' can have one subclass implementation per concrete ParentObject type. /// Should call it from concrete DelegateProxy type, not generic. - public static func register(make: @escaping (Parent) -> Self) { + public static func register(make: @escaping @Sendable (Parent) -> Self) { self.factory.extend(make: make) } @@ -317,7 +317,7 @@ extension DelegateProxyType where ParentObject: HasPrefetchDataSource, Self.Dele import UIKit extension ObservableType { - func subscribeProxyDataSource(ofObject object: DelegateProxy.ParentObject, dataSource: DelegateProxy.Delegate, retainDataSource: Bool, binding: @escaping (DelegateProxy, Event) -> Void) + func subscribeProxyDataSource(ofObject object: DelegateProxy.ParentObject, dataSource: DelegateProxy.Delegate, retainDataSource: Bool, binding: @escaping @Sendable (DelegateProxy, Event) -> Void) -> Disposable where DelegateProxy.ParentObject: UIView , DelegateProxy.Delegate: AnyObject { @@ -360,10 +360,11 @@ extension DelegateProxyType where ParentObject: HasPrefetchDataSource, Self.Dele return Disposables.create { [weak object] in subscription.dispose() - - if object?.window != nil { - object?.layoutIfNeeded() - } + MainScheduler.assumeMainActor(execute: { + if object?.window != nil { + object?.layoutIfNeeded() + } + }) unregisterDelegate.dispose() } @@ -410,7 +411,7 @@ extension DelegateProxyType where ParentObject: HasPrefetchDataSource, Self.Dele self._identifier = proxyType.identifier } - fileprivate func extend(make: @escaping (ParentObject) -> DelegateProxy) { + fileprivate func extend(make: @escaping @Sendable (ParentObject) -> DelegateProxy) { MainScheduler.ensureRunningOnMainThread() precondition(self._identifier == DelegateProxy.identifier, "Delegate proxy has inconsistent identifier") guard self._factories[ObjectIdentifier(ParentObject.self)] == nil else { diff --git a/RxCocoa/Foundation/NSObject+Rx+KVORepresentable.swift b/RxCocoa/Foundation/NSObject+Rx+KVORepresentable.swift index 1be5a212d..96fe0862f 100644 --- a/RxCocoa/Foundation/NSObject+Rx+KVORepresentable.swift +++ b/RxCocoa/Foundation/NSObject+Rx+KVORepresentable.swift @@ -38,7 +38,7 @@ extension Reactive where Base: NSObject { */ public func observe(_ type: Element.Type, _ keyPath: String, options: KeyValueObservingOptions = [.new, .initial], retainSelf: Bool = true) -> Observable { return self.observe(Element.KVOType.self, keyPath, options: options, retainSelf: retainSelf) - .map(Element.init) + .map({ Element(KVOValue: $0) }) } } @@ -52,7 +52,7 @@ extension Reactive where Base: NSObject { */ public func observeWeakly(_ type: Element.Type, _ keyPath: String, options: KeyValueObservingOptions = [.new, .initial]) -> Observable { return self.observeWeakly(Element.KVOType.self, keyPath, options: options) - .map(Element.init) + .map({ Element(KVOValue: $0) }) } } #endif diff --git a/RxCocoa/Foundation/NSObject+Rx+RawRepresentable.swift b/RxCocoa/Foundation/NSObject+Rx+RawRepresentable.swift index 6e47cb243..40dc9c31b 100644 --- a/RxCocoa/Foundation/NSObject+Rx+RawRepresentable.swift +++ b/RxCocoa/Foundation/NSObject+Rx+RawRepresentable.swift @@ -24,7 +24,7 @@ extension Reactive where Base: NSObject { */ public func observe(_ type: Element.Type, _ keyPath: String, options: KeyValueObservingOptions = [.new, .initial], retainSelf: Bool = true) -> Observable where Element.RawValue: KVORepresentable { return self.observe(Element.RawValue.KVOType.self, keyPath, options: options, retainSelf: retainSelf) - .map(Element.init) + .map({ Element(KVOValue: $0) }) } } @@ -44,7 +44,7 @@ extension Reactive where Base: NSObject { */ public func observeWeakly(_ type: Element.Type, _ keyPath: String, options: KeyValueObservingOptions = [.new, .initial]) -> Observable where Element.RawValue: KVORepresentable { return self.observeWeakly(Element.RawValue.KVOType.self, keyPath, options: options) - .map(Element.init) + .map({ Element(KVOValue: $0) }) } } #endif diff --git a/RxCocoa/Foundation/NSObject+Rx.swift b/RxCocoa/Foundation/NSObject+Rx.swift index d0ac0eeab..2362f7268 100644 --- a/RxCocoa/Foundation/NSObject+Rx.swift +++ b/RxCocoa/Foundation/NSObject+Rx.swift @@ -484,7 +484,7 @@ private extension KeyValueObservingOptions { options: KeyValueObservingOptions ) -> Observable { - weak var weakTarget: AnyObject? = target + nonisolated(unsafe) weak var weakTarget: AnyObject? = target let propertyName = keyPathSections[0] let remainingPaths = Array(keyPathSections[1..( with object: Object, - onNext: (@Sendable (Object, Element) -> Void)? = nil, - onCompleted: (@Sendable (Object) -> Void)? = nil, + onNext: (@Sendable @MainActor (Object, Element) -> Void)? = nil, + onCompleted: (@Sendable @MainActor (Object) -> Void)? = nil, onDisposed: (@Sendable (Object) -> Void)? = nil ) -> Disposable { MainScheduler.ensureRunningOnMainThread(errorMessage: errorMessage) - return self.asObservable().subscribe(with: object, onNext: onNext, onCompleted: onCompleted, onDisposed: onDisposed) + return self.asObservable().subscribe(with: object, onNext: onNext.flatMap({ MainScheduler.assumeMainActor($0) }), onCompleted: onCompleted.flatMap({ MainScheduler.assumeMainActor($0) }), onDisposed: onDisposed) } /** @@ -179,12 +179,12 @@ extension SharedSequenceConvertibleType where SharingStrategy == DriverSharingSt - returns: Subscription object used to unsubscribe from the observable sequence. */ public func drive( - onNext: (@Sendable (Element) -> Void)? = nil, - onCompleted: (@Sendable () -> Void)? = nil, + onNext: (@Sendable @MainActor (Element) -> Void)? = nil, + onCompleted: (@Sendable @MainActor () -> Void)? = nil, onDisposed: (@Sendable () -> Void)? = nil ) -> Disposable { MainScheduler.ensureRunningOnMainThread(errorMessage: errorMessage) - return self.asObservable().subscribe(onNext: onNext, onCompleted: onCompleted, onDisposed: onDisposed) + return self.asObservable().subscribe(onNext: onNext.flatMap({ MainScheduler.assumeMainActor($0) }), onCompleted: onCompleted.flatMap({ MainScheduler.assumeMainActor($0) }), onDisposed: onDisposed) } /** diff --git a/RxCocoa/Traits/Driver/ObservableConvertibleType+Driver.swift b/RxCocoa/Traits/Driver/ObservableConvertibleType+Driver.swift index bcac66b66..6b2f30980 100644 --- a/RxCocoa/Traits/Driver/ObservableConvertibleType+Driver.swift +++ b/RxCocoa/Traits/Driver/ObservableConvertibleType+Driver.swift @@ -45,7 +45,7 @@ extension ObservableConvertibleType { - parameter onErrorRecover: Calculates driver that continues to drive the sequence in case of error. - returns: Driver trait. */ - public func asDriver(onErrorRecover: @escaping (_ error: Swift.Error) -> Driver) -> Driver { + public func asDriver(onErrorRecover: @escaping @Sendable (_ error: Swift.Error) -> Driver) -> Driver { let source = self .asObservable() .observe(on:DriverSharingStrategy.scheduler) diff --git a/RxCocoa/Traits/SharedSequence/ObservableConvertibleType+SharedSequence.swift b/RxCocoa/Traits/SharedSequence/ObservableConvertibleType+SharedSequence.swift index 20ddf868f..5f6f6ada1 100644 --- a/RxCocoa/Traits/SharedSequence/ObservableConvertibleType+SharedSequence.swift +++ b/RxCocoa/Traits/SharedSequence/ObservableConvertibleType+SharedSequence.swift @@ -45,7 +45,7 @@ extension ObservableConvertibleType { - parameter onErrorRecover: Calculates driver that continues to drive the sequence in case of error. - returns: Driving observable sequence. */ - public func asSharedSequence(sharingStrategy: S.Type = S.self, onErrorRecover: @escaping (_ error: Swift.Error) -> SharedSequence) -> SharedSequence { + public func asSharedSequence(sharingStrategy: S.Type = S.self, onErrorRecover: @escaping @Sendable (_ error: Swift.Error) -> SharedSequence) -> SharedSequence { let source = self .asObservable() .observe(on:S.scheduler) diff --git a/RxCocoa/Traits/SharedSequence/SchedulerType+SharedSequence.swift b/RxCocoa/Traits/SharedSequence/SchedulerType+SharedSequence.swift index 5111e06d8..d4d63016f 100644 --- a/RxCocoa/Traits/SharedSequence/SchedulerType+SharedSequence.swift +++ b/RxCocoa/Traits/SharedSequence/SchedulerType+SharedSequence.swift @@ -28,7 +28,7 @@ public enum SharingScheduler { **This shouldn't be used in normal release builds.** */ - static public func mock(makeScheduler: @escaping () -> SchedulerType, action: () throws -> Void) rethrows { + static public func mock(makeScheduler: @escaping @Sendable () -> SchedulerType, action: () throws -> Void) rethrows { let originalMake = make make = makeScheduler defer { diff --git a/RxCocoa/Traits/SharedSequence/SharedSequence+Operators+arity.swift b/RxCocoa/Traits/SharedSequence/SharedSequence+Operators+arity.swift index 0ffc6eaa9..df6b5e478 100644 --- a/RxCocoa/Traits/SharedSequence/SharedSequence+Operators+arity.swift +++ b/RxCocoa/Traits/SharedSequence/SharedSequence+Operators+arity.swift @@ -273,7 +273,7 @@ extension SharedSequence { - returns: An observable sequence containing the result of combining elements of the sources using the specified result selector function. */ public static func zip - (_ source1: O1, _ source2: O2, _ source3: O3, _ source4: O4, _ source5: O5, resultSelector: @escaping (O1.Element, O2.Element, O3.Element, O4.Element, O5.Element) throws -> Element) + (_ source1: O1, _ source2: O2, _ source3: O3, _ source4: O4, _ source5: O5, resultSelector: @escaping @Sendable (O1.Element, O2.Element, O3.Element, O4.Element, O5.Element) throws -> Element) -> SharedSequence where SharingStrategy == O1.SharingStrategy, SharingStrategy == O2.SharingStrategy, SharingStrategy == O3.SharingStrategy, diff --git a/RxCocoa/Traits/SharedSequence/SharedSequence+Operators.swift b/RxCocoa/Traits/SharedSequence/SharedSequence+Operators.swift index cc832b0c7..e5180e444 100644 --- a/RxCocoa/Traits/SharedSequence/SharedSequence+Operators.swift +++ b/RxCocoa/Traits/SharedSequence/SharedSequence+Operators.swift @@ -355,7 +355,7 @@ extension SharedSequenceConvertibleType { - parameter accumulator: An accumulator function to be invoked on each element. - returns: An observable sequence containing the accumulated values. */ - public func scan(_ seed: A, accumulator: @escaping (A, Element) -> A) + public func scan(_ seed: A, accumulator: @escaping @Sendable (A, Element) -> A) -> SharedSequence { let source = self.asObservable() .scan(seed, accumulator: accumulator) @@ -458,7 +458,7 @@ extension SharedSequenceConvertibleType where SharingStrategy == SignalSharingSt */ public func withUnretained( _ obj: Object, - resultSelector: @escaping (Object, Element) -> Out + resultSelector: @escaping @Sendable (Object, Element) -> Out ) -> SharedSequence { SharedSequence(self.asObservable().withUnretained(obj, resultSelector: resultSelector)) } @@ -482,7 +482,7 @@ extension SharedSequenceConvertibleType where SharingStrategy == DriverSharingSt @available(*, message: "withUnretained has been deprecated for Driver. Consider using `drive(with:onNext:onCompleted:onDisposed:)`, instead", unavailable) public func withUnretained( _ obj: Object, - resultSelector: @escaping (Object, Element) -> Out + resultSelector: @escaping @Sendable (Object, Element) -> Out ) -> SharedSequence { SharedSequence(self.asObservable().withUnretained(obj, resultSelector: resultSelector)) } diff --git a/RxCocoa/Traits/SharedSequence/SharedSequence.swift b/RxCocoa/Traits/SharedSequence/SharedSequence.swift index 4596c8ec0..328d9085e 100644 --- a/RxCocoa/Traits/SharedSequence/SharedSequence.swift +++ b/RxCocoa/Traits/SharedSequence/SharedSequence.swift @@ -136,7 +136,7 @@ extension SharedSequence { - parameter observableFactory: Observable factory function to invoke for each observer that subscribes to the resulting sequence. - returns: An observable sequence whose observers trigger an invocation of the given observable factory function. */ - public static func deferred(_ observableFactory: @escaping () -> SharedSequence) + public static func deferred(_ observableFactory: @escaping @Sendable () -> SharedSequence) -> SharedSequence { SharedSequence(Observable.deferred { observableFactory().asObservable() }) } diff --git a/RxCocoa/Traits/Signal/ObservableConvertibleType+Signal.swift b/RxCocoa/Traits/Signal/ObservableConvertibleType+Signal.swift index b962d4ed0..82423289d 100644 --- a/RxCocoa/Traits/Signal/ObservableConvertibleType+Signal.swift +++ b/RxCocoa/Traits/Signal/ObservableConvertibleType+Signal.swift @@ -45,7 +45,7 @@ extension ObservableConvertibleType { - parameter onErrorRecover: Calculates signal that continues to emit the sequence in case of error. - returns: Signal trait. */ - public func asSignal(onErrorRecover: @escaping (_ error: Swift.Error) -> Signal) -> Signal { + public func asSignal(onErrorRecover: @escaping @Sendable (_ error: Swift.Error) -> Signal) -> Signal { let source = self .asObservable() .observe(on: SignalSharingStrategy.scheduler) diff --git a/RxCocoa/iOS/DataSources/RxCollectionViewReactiveArrayDataSource.swift b/RxCocoa/iOS/DataSources/RxCollectionViewReactiveArrayDataSource.swift index a5fcfd1b1..89c30690b 100644 --- a/RxCocoa/iOS/DataSources/RxCollectionViewReactiveArrayDataSource.swift +++ b/RxCocoa/iOS/DataSources/RxCollectionViewReactiveArrayDataSource.swift @@ -50,7 +50,9 @@ class RxCollectionViewReactiveArrayDataSourceSequenceWrapper) { Binder(self) { collectionViewDataSource, sectionModels in let sections = Array(sectionModels) - collectionViewDataSource.collectionView(collectionView, observedElements: sections) + MainScheduler.assumeMainActor(execute: { + collectionViewDataSource.collectionView(collectionView, observedElements: sections) + }) }.on(observedEvent) } } @@ -61,7 +63,7 @@ class RxCollectionViewReactiveArrayDataSource : _RxCollectionViewReactiveArrayDataSource , SectionedViewDataSourceType { - typealias CellFactory = (UICollectionView, Int, Element) -> UICollectionViewCell + typealias CellFactory = @MainActor (UICollectionView, Int, Element) -> UICollectionViewCell var itemModels: [Element]? diff --git a/RxCocoa/iOS/DataSources/RxPickerViewAdapter.swift b/RxCocoa/iOS/DataSources/RxPickerViewAdapter.swift index 9142e96da..67b7afa65 100644 --- a/RxCocoa/iOS/DataSources/RxPickerViewAdapter.swift +++ b/RxCocoa/iOS/DataSources/RxPickerViewAdapter.swift @@ -12,7 +12,7 @@ import UIKit import RxSwift class RxPickerViewArrayDataSource: NSObject, UIPickerViewDataSource, SectionedViewDataSourceType { - fileprivate var items: [T] = [] + nonisolated(unsafe) fileprivate var items: [T] = [] func model(at indexPath: IndexPath) throws -> Any { guard items.indices ~= indexPath.row else { @@ -38,7 +38,9 @@ class RxPickerViewSequenceDataSource func pickerView(_ pickerView: UIPickerView, observedEvent: Event) { Binder(self) { dataSource, items in dataSource.items = items - pickerView.reloadAllComponents() + MainScheduler.assumeMainActor(execute: { + pickerView.reloadAllComponents() + }) } .on(observedEvent.map(Array.init)) } @@ -48,7 +50,7 @@ final class RxStringPickerViewAdapter : RxPickerViewSequenceDataSource , UIPickerViewDelegate { - typealias TitleForRow = (Int, Sequence.Element) -> String? + typealias TitleForRow = @MainActor (Int, Sequence.Element) -> String? private let titleForRow: TitleForRow init(titleForRow: @escaping TitleForRow) { @@ -62,7 +64,7 @@ final class RxStringPickerViewAdapter } final class RxAttributedStringPickerViewAdapter: RxPickerViewSequenceDataSource, UIPickerViewDelegate { - typealias AttributedTitleForRow = (Int, Sequence.Element) -> NSAttributedString? + typealias AttributedTitleForRow = @MainActor (Int, Sequence.Element) -> NSAttributedString? private let attributedTitleForRow: AttributedTitleForRow init(attributedTitleForRow: @escaping AttributedTitleForRow) { @@ -76,7 +78,7 @@ final class RxAttributedStringPickerViewAdapter: RxPic } final class RxPickerViewAdapter: RxPickerViewSequenceDataSource, UIPickerViewDelegate { - typealias ViewForRow = (Int, Sequence.Element, UIView?) -> UIView + typealias ViewForRow = @MainActor (Int, Sequence.Element, UIView?) -> UIView private let viewForRow: ViewForRow init(viewForRow: @escaping ViewForRow) { diff --git a/RxCocoa/iOS/DataSources/RxTableViewReactiveArrayDataSource.swift b/RxCocoa/iOS/DataSources/RxTableViewReactiveArrayDataSource.swift index f77eec8f8..8699dfc32 100644 --- a/RxCocoa/iOS/DataSources/RxTableViewReactiveArrayDataSource.swift +++ b/RxCocoa/iOS/DataSources/RxTableViewReactiveArrayDataSource.swift @@ -50,7 +50,9 @@ class RxTableViewReactiveArrayDataSourceSequenceWrapper) { Binder(self) { tableViewDataSource, sectionModels in let sections = Array(sectionModels) - tableViewDataSource.tableView(tableView, observedElements: sections) + MainScheduler.assumeMainActor(execute: { + tableViewDataSource.tableView(tableView, observedElements: sections) + }) }.on(observedEvent) } } @@ -59,7 +61,7 @@ class RxTableViewReactiveArrayDataSourceSequenceWrapper : _RxTableViewReactiveArrayDataSource , SectionedViewDataSourceType { - typealias CellFactory = (UITableView, Int, Element) -> UITableViewCell + typealias CellFactory = @MainActor (UITableView, Int, Element) -> UITableViewCell var itemModels: [Element]? diff --git a/RxCocoa/iOS/Proxies/RxCollectionViewDelegateProxy.swift b/RxCocoa/iOS/Proxies/RxCollectionViewDelegateProxy.swift index 687e3b61b..c4967a9d0 100644 --- a/RxCocoa/iOS/Proxies/RxCollectionViewDelegateProxy.swift +++ b/RxCocoa/iOS/Proxies/RxCollectionViewDelegateProxy.swift @@ -21,6 +21,7 @@ open class RxCollectionViewDelegateProxy /// Initializes `RxCollectionViewDelegateProxy` /// /// - parameter collectionView: Parent object for delegate proxy. + nonisolated public init(collectionView: UICollectionView) { self.collectionView = collectionView super.init(scrollView: collectionView) diff --git a/RxCocoa/iOS/Proxies/RxTableViewDelegateProxy.swift b/RxCocoa/iOS/Proxies/RxTableViewDelegateProxy.swift index 51094e4cf..d7e42b412 100644 --- a/RxCocoa/iOS/Proxies/RxTableViewDelegateProxy.swift +++ b/RxCocoa/iOS/Proxies/RxTableViewDelegateProxy.swift @@ -19,6 +19,7 @@ open class RxTableViewDelegateProxy public weak private(set) var tableView: UITableView? /// - parameter tableView: Parent object for delegate proxy. + nonisolated public init(tableView: UITableView) { self.tableView = tableView super.init(scrollView: tableView) diff --git a/RxCocoa/iOS/Proxies/RxTextViewDelegateProxy.swift b/RxCocoa/iOS/Proxies/RxTextViewDelegateProxy.swift index 22b574ce1..8f3f4484a 100644 --- a/RxCocoa/iOS/Proxies/RxTextViewDelegateProxy.swift +++ b/RxCocoa/iOS/Proxies/RxTextViewDelegateProxy.swift @@ -19,6 +19,7 @@ open class RxTextViewDelegateProxy public weak private(set) var textView: UITextView? /// - parameter textview: Parent object for delegate proxy. + nonisolated public init(textView: UITextView) { self.textView = textView super.init(scrollView: textView) diff --git a/RxCocoa/iOS/UIActivityIndicatorView+Rx.swift b/RxCocoa/iOS/UIActivityIndicatorView+Rx.swift index 5f1876b8f..5e049abf7 100644 --- a/RxCocoa/iOS/UIActivityIndicatorView+Rx.swift +++ b/RxCocoa/iOS/UIActivityIndicatorView+Rx.swift @@ -14,13 +14,17 @@ import RxSwift extension Reactive where Base: UIActivityIndicatorView { /// Bindable sink for `startAnimating()`, `stopAnimating()` methods. public var isAnimating: Binder { - Binder(self.base) { activityIndicator, active in - if active { - activityIndicator.startAnimating() - } else { - activityIndicator.stopAnimating() + MainScheduler.assumeMainActor(execute: { + Binder(self.base) { activityIndicator, active in + MainScheduler.assumeMainActor(execute: { + if active { + activityIndicator.startAnimating() + } else { + activityIndicator.stopAnimating() + } + }) } - } + }) } } diff --git a/RxCocoa/iOS/UIApplication+Rx.swift b/RxCocoa/iOS/UIApplication+Rx.swift index a8a623e77..35e594aaf 100644 --- a/RxCocoa/iOS/UIApplication+Rx.swift +++ b/RxCocoa/iOS/UIApplication+Rx.swift @@ -17,7 +17,7 @@ extension Reactive where Base: UIApplication { /// Bindable sink for `isNetworkActivityIndicatorVisible`. public var isNetworkActivityIndicatorVisible: Binder { return Binder(self.base) { application, active in - application.isNetworkActivityIndicatorVisible = active + MainScheduler.assumeMainActor(execute: { application.isNetworkActivityIndicatorVisible = active }) } } } diff --git a/RxCocoa/iOS/UIBarButtonItem+Rx.swift b/RxCocoa/iOS/UIBarButtonItem+Rx.swift index 1c79390e9..c45efe512 100644 --- a/RxCocoa/iOS/UIBarButtonItem+Rx.swift +++ b/RxCocoa/iOS/UIBarButtonItem+Rx.swift @@ -43,7 +43,7 @@ final class BarButtonItemTarget: RxTarget { weak var barButtonItem: UIBarButtonItem? var callback: Callback! - init(barButtonItem: UIBarButtonItem, callback: @escaping () -> Void) { + init(barButtonItem: UIBarButtonItem, callback: @escaping @Sendable () -> Void) { self.barButtonItem = barButtonItem self.callback = callback super.init() diff --git a/RxCocoa/iOS/UIButton+Rx.swift b/RxCocoa/iOS/UIButton+Rx.swift index d525ec088..49df2fc2d 100644 --- a/RxCocoa/iOS/UIButton+Rx.swift +++ b/RxCocoa/iOS/UIButton+Rx.swift @@ -46,21 +46,27 @@ extension Reactive where Base: UIButton { /// Reactive wrapper for `setTitle(_:for:)` public func title(for controlState: UIControl.State = []) -> Binder { Binder(self.base) { button, title in - button.setTitle(title, for: controlState) + MainScheduler.assumeMainActor(execute: { + button.setTitle(title, for: controlState) + }) } } /// Reactive wrapper for `setImage(_:for:)` public func image(for controlState: UIControl.State = []) -> Binder { Binder(self.base) { button, image in - button.setImage(image, for: controlState) + MainScheduler.assumeMainActor(execute: { + button.setImage(image, for: controlState) + }) } } /// Reactive wrapper for `setBackgroundImage(_:for:)` public func backgroundImage(for controlState: UIControl.State = []) -> Binder { Binder(self.base) { button, image in - button.setBackgroundImage(image, for: controlState) + MainScheduler.assumeMainActor(execute: { + button.setBackgroundImage(image, for: controlState) + }) } } @@ -75,7 +81,9 @@ extension Reactive where Base: UIButton { /// Reactive wrapper for `setAttributedTitle(_:controlState:)` public func attributedTitle(for controlState: UIControl.State = []) -> Binder { return Binder(self.base) { button, attributedTitle -> Void in - button.setAttributedTitle(attributedTitle, for: controlState) + MainScheduler.assumeMainActor(execute: { + button.setAttributedTitle(attributedTitle, for: controlState) + }) } } } diff --git a/RxCocoa/iOS/UICollectionView+Rx.swift b/RxCocoa/iOS/UICollectionView+Rx.swift index 96d69c5bb..748fa14b0 100644 --- a/RxCocoa/iOS/UICollectionView+Rx.swift +++ b/RxCocoa/iOS/UICollectionView+Rx.swift @@ -41,7 +41,7 @@ extension Reactive where Base: UICollectionView { */ public func items (_ source: Source) - -> (_ cellFactory: @escaping (UICollectionView, Int, Sequence.Element) -> UICollectionViewCell) + -> (_ cellFactory: @escaping @Sendable (UICollectionView, Int, Sequence.Element) -> UICollectionViewCell) -> Disposable where Source.Element == Sequence { return { cellFactory in let dataSource = RxCollectionViewReactiveArrayDataSourceSequenceWrapper(cellFactory: cellFactory) @@ -76,7 +76,7 @@ extension Reactive where Base: UICollectionView { public func items (cellIdentifier: String, cellType: Cell.Type = Cell.self) -> (_ source: Source) - -> (_ configureCell: @escaping (Int, Sequence.Element, Cell) -> Void) + -> (_ configureCell: @escaping @Sendable (Int, Sequence.Element, Cell) -> Void) -> Disposable where Source.Element == Sequence { return { source in return { configureCell in diff --git a/RxCocoa/iOS/UIControl+Rx.swift b/RxCocoa/iOS/UIControl+Rx.swift index bf4d96882..fed9bb44d 100644 --- a/RxCocoa/iOS/UIControl+Rx.swift +++ b/RxCocoa/iOS/UIControl+Rx.swift @@ -42,8 +42,8 @@ extension Reactive where Base: UIControl { /// - parameter setter: Property value setter. public func controlProperty( editingEvents: UIControl.Event, - getter: @escaping (Base) -> T, - setter: @escaping (Base, T) -> Void + getter: @escaping @Sendable @MainActor (Base) -> T, + setter: @escaping @Sendable @MainActor (Base, T) -> Void ) -> ControlProperty { let source: Observable = Observable.create { [weak weakControl = base] observer in guard let control = weakControl else { @@ -51,11 +51,11 @@ extension Reactive where Base: UIControl { return Disposables.create() } - observer.on(.next(getter(control))) + observer.on(.next(MainScheduler.assumeMainActor(execute: { getter(control) }))) - let controlTarget = ControlTarget(control: control, controlEvents: editingEvents) { _ in + let controlTarget = ControlTarget(control: control, controlEvents: editingEvents) { [weak weakControl] _ in if let control = weakControl { - observer.on(.next(getter(control))) + observer.on(.next(MainScheduler.assumeMainActor(execute: { getter(control) }))) } } @@ -63,7 +63,7 @@ extension Reactive where Base: UIControl { } .take(until: deallocated) - let bindingObserver = Binder(base, binding: setter) + let bindingObserver = Binder(base, binding: MainScheduler.assumeMainActor(setter)) return ControlProperty(values: source, valueSink: bindingObserver) } @@ -72,8 +72,8 @@ extension Reactive where Base: UIControl { /// an `editingEvent` needs to fire for control property to be updated. internal func controlPropertyWithDefaultEvents( editingEvents: UIControl.Event = [.allEditingEvents, .valueChanged], - getter: @escaping (Base) -> T, - setter: @escaping (Base, T) -> Void + getter: @escaping @Sendable @MainActor (Base) -> T, + setter: @escaping @Sendable @MainActor (Base, T) -> Void ) -> ControlProperty { return controlProperty( editingEvents: editingEvents, diff --git a/RxCocoa/iOS/UIPickerView+Rx.swift b/RxCocoa/iOS/UIPickerView+Rx.swift index 92f998cf1..4704ca2cc 100644 --- a/RxCocoa/iOS/UIPickerView+Rx.swift +++ b/RxCocoa/iOS/UIPickerView+Rx.swift @@ -69,13 +69,14 @@ guard let view = view else { return Observable.empty() } - - let model: [T] = try (0 ..< view.numberOfComponents).map { component in - let row = view.selectedRow(inComponent: component) - return try view.rx.model(at: IndexPath(row: row, section: component)) - } - - return Observable.just(model) + return try MainScheduler.assumeMainActor(execute: { + let model: [T] = try (0 ..< view.numberOfComponents).map { component in + let row = view.selectedRow(inComponent: component) + return try view.rx.model(at: IndexPath(row: row, section: component)) + } + + return Observable.just(model) + }) } return ControlEvent(events: source) @@ -106,7 +107,7 @@ public func itemTitles (_ source: Source) - -> (_ titleForRow: @escaping (Int, Sequence.Element) -> String?) + -> (_ titleForRow: @escaping @Sendable (Int, Sequence.Element) -> String?) -> Disposable where Source.Element == Sequence { return { titleForRow in let adapter = RxStringPickerViewAdapter(titleForRow: titleForRow) @@ -139,7 +140,7 @@ public func itemAttributedTitles (_ source: Source) - -> (_ attributedTitleForRow: @escaping (Int, Sequence.Element) -> NSAttributedString?) + -> (_ attributedTitleForRow: @escaping @Sendable (Int, Sequence.Element) -> NSAttributedString?) -> Disposable where Source.Element == Sequence { return { attributedTitleForRow in let adapter = RxAttributedStringPickerViewAdapter(attributedTitleForRow: attributedTitleForRow) @@ -178,7 +179,7 @@ public func items (_ source: Source) - -> (_ viewForRow: @escaping (Int, Sequence.Element, UIView?) -> UIView) + -> (_ viewForRow: @escaping @Sendable (Int, Sequence.Element, UIView?) -> UIView) -> Disposable where Source.Element == Sequence { return { viewForRow in let adapter = RxPickerViewAdapter(viewForRow: viewForRow) diff --git a/RxCocoa/iOS/UIRefreshControl+Rx.swift b/RxCocoa/iOS/UIRefreshControl+Rx.swift index adb484f13..eff23021c 100644 --- a/RxCocoa/iOS/UIRefreshControl+Rx.swift +++ b/RxCocoa/iOS/UIRefreshControl+Rx.swift @@ -15,11 +15,13 @@ extension Reactive where Base: UIRefreshControl { /// Bindable sink for `beginRefreshing()`, `endRefreshing()` methods. public var isRefreshing: Binder { return Binder(self.base) { refreshControl, refresh in - if refresh { - refreshControl.beginRefreshing() - } else { - refreshControl.endRefreshing() - } + MainScheduler.assumeMainActor(execute: { + if refresh { + refreshControl.beginRefreshing() + } else { + refreshControl.endRefreshing() + } + }) } } diff --git a/RxCocoa/iOS/UIScrollView+Rx.swift b/RxCocoa/iOS/UIScrollView+Rx.swift index dc53c02fd..e7b400299 100644 --- a/RxCocoa/iOS/UIScrollView+Rx.swift +++ b/RxCocoa/iOS/UIScrollView+Rx.swift @@ -27,7 +27,9 @@ let proxy = RxScrollViewDelegateProxy.proxy(for: base) let bindingObserver = Binder(self.base) { scrollView, contentOffset in - scrollView.contentOffset = contentOffset + MainScheduler.assumeMainActor(execute: { + scrollView.contentOffset = contentOffset + }) } return ControlProperty(values: proxy.contentOffsetBehaviorSubject, valueSink: bindingObserver) diff --git a/RxCocoa/iOS/UISearchBar+Rx.swift b/RxCocoa/iOS/UISearchBar+Rx.swift index 1d0229677..6b614e726 100644 --- a/RxCocoa/iOS/UISearchBar+Rx.swift +++ b/RxCocoa/iOS/UISearchBar+Rx.swift @@ -28,18 +28,26 @@ extension Reactive where Base: UISearchBar { /// Reactive wrapper for `text` property. public var value: ControlProperty { let source: Observable = Observable.deferred { [weak searchBar = self.base as UISearchBar] () -> Observable in - let text = searchBar?.text - - let textDidChange = (searchBar?.rx.delegate.methodInvoked(#selector(UISearchBarDelegate.searchBar(_:textDidChange:))) ?? Observable.empty()) - let didEndEditing = (searchBar?.rx.delegate.methodInvoked(#selector(UISearchBarDelegate.searchBarTextDidEndEditing(_:))) ?? Observable.empty()) - - return Observable.merge(textDidChange, didEndEditing) - .map { _ in searchBar?.text ?? "" } + return MainScheduler.assumeMainActor(execute: { + let text = searchBar?.text + + let textDidChange = (searchBar?.rx.delegate.methodInvoked(#selector(UISearchBarDelegate.searchBar(_:textDidChange:))) ?? Observable.empty()) + let didEndEditing = (searchBar?.rx.delegate.methodInvoked(#selector(UISearchBarDelegate.searchBarTextDidEndEditing(_:))) ?? Observable.empty()) + + return Observable.merge(textDidChange, didEndEditing) + .map { [weak searchBar] _ in + MainScheduler.assumeMainActor(execute: { [weak searchBar] in + searchBar?.text ?? "" + }) + } .startWith(text) + }) } let bindingObserver = Binder(self.base) { (searchBar, text: String?) in - searchBar.text = text + MainScheduler.assumeMainActor(execute: { + searchBar.text = text + }) } return ControlProperty(values: source, valueSink: bindingObserver) @@ -48,7 +56,7 @@ extension Reactive where Base: UISearchBar { /// Reactive wrapper for `selectedScopeButtonIndex` property. public var selectedScopeButtonIndex: ControlProperty { let source: Observable = Observable.deferred { [weak source = self.base as UISearchBar] () -> Observable in - let index = source?.selectedScopeButtonIndex ?? 0 + let index = MainScheduler.assumeMainActor(execute: { source?.selectedScopeButtonIndex ?? 0 }) return (source?.rx.delegate.methodInvoked(#selector(UISearchBarDelegate.searchBar(_:selectedScopeButtonIndexDidChange:))) ?? Observable.empty()) .map { a in @@ -58,7 +66,7 @@ extension Reactive where Base: UISearchBar { } let bindingObserver = Binder(self.base) { (searchBar, index: Int) in - searchBar.selectedScopeButtonIndex = index + MainScheduler.assumeMainActor(execute: { searchBar.selectedScopeButtonIndex = index }) } return ControlProperty(values: source, valueSink: bindingObserver) diff --git a/RxCocoa/iOS/UISegmentedControl+Rx.swift b/RxCocoa/iOS/UISegmentedControl+Rx.swift index 613d2e179..d28bbb40c 100644 --- a/RxCocoa/iOS/UISegmentedControl+Rx.swift +++ b/RxCocoa/iOS/UISegmentedControl+Rx.swift @@ -31,21 +31,27 @@ extension Reactive where Base: UISegmentedControl { /// Reactive wrapper for `setEnabled(_:forSegmentAt:)` public func enabledForSegment(at index: Int) -> Binder { return Binder(self.base) { segmentedControl, segmentEnabled -> Void in - segmentedControl.setEnabled(segmentEnabled, forSegmentAt: index) + MainScheduler.assumeMainActor(execute: { + segmentedControl.setEnabled(segmentEnabled, forSegmentAt: index) + }) } } /// Reactive wrapper for `setTitle(_:forSegmentAt:)` public func titleForSegment(at index: Int) -> Binder { return Binder(self.base) { segmentedControl, title -> Void in - segmentedControl.setTitle(title, forSegmentAt: index) + MainScheduler.assumeMainActor(execute: { + segmentedControl.setTitle(title, forSegmentAt: index) + }) } } /// Reactive wrapper for `setImage(_:forSegmentAt:)` public func imageForSegment(at index: Int) -> Binder { return Binder(self.base) { segmentedControl, image -> Void in - segmentedControl.setImage(image, forSegmentAt: index) + MainScheduler.assumeMainActor(execute: { + segmentedControl.setImage(image, forSegmentAt: index) + }) } } diff --git a/RxCocoa/iOS/UITableView+Rx.swift b/RxCocoa/iOS/UITableView+Rx.swift index deae7ffe4..7ad6f68bf 100644 --- a/RxCocoa/iOS/UITableView+Rx.swift +++ b/RxCocoa/iOS/UITableView+Rx.swift @@ -41,7 +41,7 @@ extension Reactive where Base: UITableView { */ public func items (_ source: Source) - -> (_ cellFactory: @escaping (UITableView, Int, Sequence.Element) -> UITableViewCell) + -> (_ cellFactory: @escaping @Sendable (UITableView, Int, Sequence.Element) -> UITableViewCell) -> Disposable where Source.Element == Sequence { return { cellFactory in @@ -76,7 +76,7 @@ extension Reactive where Base: UITableView { public func items (cellIdentifier: String, cellType: Cell.Type = Cell.self) -> (_ source: Source) - -> (_ configureCell: @escaping (Int, Sequence.Element, Cell) -> Void) + -> (_ configureCell: @escaping @Sendable (Int, Sequence.Element, Cell) -> Void) -> Disposable where Source.Element == Sequence { return { source in diff --git a/RxCocoa/iOS/UITextView+Rx.swift b/RxCocoa/iOS/UITextView+Rx.swift index 35e219425..c0be60819 100644 --- a/RxCocoa/iOS/UITextView+Rx.swift +++ b/RxCocoa/iOS/UITextView+Rx.swift @@ -20,33 +20,39 @@ extension Reactive where Base: UITextView { /// Reactive wrapper for `text` property. public var value: ControlProperty { let source: Observable = Observable.deferred { [weak textView = self.base] in - let text = textView?.text - - let textChanged = textView?.textStorage + MainScheduler.assumeMainActor(execute: { [weak textView] in + let text = textView?.text + + let textChanged = textView?.textStorage // This project uses text storage notifications because // that's the only way to catch autocorrect changes // in all cases. Other suggestions are welcome. - .rx.didProcessEditingRangeChangeInLength + .rx.didProcessEditingRangeChangeInLength // This observe on is here because text storage // will emit event while process is not completely done, // so rebinding a value will cause an exception to be thrown. - .observe(on:MainScheduler.asyncInstance) - .map { _ in - return textView?.textStorage.string - } + .observe(on:MainScheduler.asyncInstance) + .map { [weak textView] _ in + MainScheduler.assumeMainActor(execute: { [weak textView] in + return textView?.textStorage.string + }) + } ?? Observable.empty() - - return textChanged - .startWith(text) + + return textChanged + .startWith(text) + }) } let bindingObserver = Binder(self.base) { (textView, text: String?) in // This check is important because setting text value always clears control state // including marked text selection which is important for proper input // when IME input method is used. - if textView.text != text { - textView.text = text - } + MainScheduler.assumeMainActor(execute: { + if textView.text != text { + textView.text = text + } + }) } return ControlProperty(values: source, valueSink: bindingObserver) @@ -56,33 +62,39 @@ extension Reactive where Base: UITextView { /// Reactive wrapper for `attributedText` property. public var attributedText: ControlProperty { let source: Observable = Observable.deferred { [weak textView = self.base] in - let attributedText = textView?.attributedText - - let textChanged: Observable = textView?.textStorage + return MainScheduler.assumeMainActor(execute: { + let attributedText = textView?.attributedText + + let textChanged: Observable = textView?.textStorage // This project uses text storage notifications because // that's the only way to catch autocorrect changes // in all cases. Other suggestions are welcome. - .rx.didProcessEditingRangeChangeInLength + .rx.didProcessEditingRangeChangeInLength // This observe on is here because attributedText storage // will emit event while process is not completely done, // so rebinding a value will cause an exception to be thrown. - .observe(on:MainScheduler.asyncInstance) - .map { _ in - return textView?.attributedText - } + .observe(on:MainScheduler.asyncInstance) + .map { [weak textView] _ in + MainScheduler.assumeMainActor(execute: { + return textView?.attributedText + }) + } ?? Observable.empty() - - return textChanged - .startWith(attributedText) + + return textChanged + .startWith(attributedText) + }) } let bindingObserver = Binder(self.base) { (textView, attributedText: NSAttributedString?) in // This check is important because setting text value always clears control state // including marked text selection which is important for proper input // when IME input method is used. - if textView.attributedText != attributedText { - textView.attributedText = attributedText - } + MainScheduler.assumeMainActor(execute: { + if textView.attributedText != attributedText { + textView.attributedText = attributedText + } + }) } return ControlProperty(values: source, valueSink: bindingObserver) diff --git a/RxCocoa/macOS/NSControl+Rx.swift b/RxCocoa/macOS/NSControl+Rx.swift index 534f40cab..fe3142a3f 100644 --- a/RxCocoa/macOS/NSControl+Rx.swift +++ b/RxCocoa/macOS/NSControl+Rx.swift @@ -47,8 +47,8 @@ extension Reactive where Base: NSControl { /// - parameter getter: Property value getter. /// - parameter setter: Property value setter. public func controlProperty( - getter: @escaping (Base) -> T, - setter: @escaping (Base, T) -> Void + getter: @escaping @Sendable (Base) -> T, + setter: @escaping @Sendable (Base, T) -> Void ) -> ControlProperty { MainScheduler.ensureRunningOnMainThread() diff --git a/RxExample/Extensions/RxCLLocationManagerDelegateProxy.swift b/RxExample/Extensions/RxCLLocationManagerDelegateProxy.swift index 3efa0940d..9607ea367 100644 --- a/RxExample/Extensions/RxCLLocationManagerDelegateProxy.swift +++ b/RxExample/Extensions/RxCLLocationManagerDelegateProxy.swift @@ -10,7 +10,7 @@ import CoreLocation import RxSwift import RxCocoa -extension CLLocationManager: HasDelegate { +extension CLLocationManager: @retroactive HasDelegate { public typealias Delegate = CLLocationManagerDelegate } diff --git a/RxExample/Extensions/RxImagePickerDelegateProxy.swift b/RxExample/Extensions/RxImagePickerDelegateProxy.swift index ebaab6ff0..5329602c3 100644 --- a/RxExample/Extensions/RxImagePickerDelegateProxy.swift +++ b/RxExample/Extensions/RxImagePickerDelegateProxy.swift @@ -15,6 +15,7 @@ import UIKit open class RxImagePickerDelegateProxy : RxNavigationControllerDelegateProxy, UIImagePickerControllerDelegate { + nonisolated public init(imagePicker: UIImagePickerController) { super.init(navigationController: imagePicker) } diff --git a/RxExample/RxDataSources/RxDataSources/TableViewSectionedDataSource.swift b/RxExample/RxDataSources/RxDataSources/TableViewSectionedDataSource.swift index e92da0bdd..91d0abe9d 100644 --- a/RxExample/RxDataSources/RxDataSources/TableViewSectionedDataSource.swift +++ b/RxExample/RxDataSources/RxDataSources/TableViewSectionedDataSource.swift @@ -19,21 +19,21 @@ open class TableViewSectionedDataSource public typealias Item = Section.Item - public typealias ConfigureCell = (TableViewSectionedDataSource
, UITableView, IndexPath, Item) -> UITableViewCell - public typealias TitleForHeaderInSection = (TableViewSectionedDataSource
, Int) -> String? - public typealias TitleForFooterInSection = (TableViewSectionedDataSource
, Int) -> String? - public typealias CanEditRowAtIndexPath = (TableViewSectionedDataSource
, IndexPath) -> Bool - public typealias CanMoveRowAtIndexPath = (TableViewSectionedDataSource
, IndexPath) -> Bool + public typealias ConfigureCell = @Sendable @MainActor (TableViewSectionedDataSource
, UITableView, IndexPath, Item) -> UITableViewCell + public typealias TitleForHeaderInSection = @Sendable @MainActor (TableViewSectionedDataSource
, Int) -> String? + public typealias TitleForFooterInSection = @Sendable @MainActor (TableViewSectionedDataSource
, Int) -> String? + public typealias CanEditRowAtIndexPath = @Sendable @MainActor (TableViewSectionedDataSource
, IndexPath) -> Bool + public typealias CanMoveRowAtIndexPath = @Sendable @MainActor (TableViewSectionedDataSource
, IndexPath) -> Bool #if os(iOS) - public typealias SectionIndexTitles = (TableViewSectionedDataSource
) -> [String]? - public typealias SectionForSectionIndexTitle = (TableViewSectionedDataSource
, _ title: String, _ index: Int) -> Int + public typealias SectionIndexTitles = @Sendable @MainActor (TableViewSectionedDataSource
) -> [String]? + public typealias SectionForSectionIndexTitle = @Sendable @MainActor (TableViewSectionedDataSource
, _ title: String, _ index: Int) -> Int #endif #if os(iOS) public init( configureCell: @escaping ConfigureCell, - titleForHeaderInSection: @escaping TitleForHeaderInSection = { _, _ in nil }, + titleForHeaderInSection: @escaping TitleForHeaderInSection = { _, _ in nil }, titleForFooterInSection: @escaping TitleForFooterInSection = { _, _ in nil }, canEditRowAtIndexPath: @escaping CanEditRowAtIndexPath = { _, _ in false }, canMoveRowAtIndexPath: @escaping CanMoveRowAtIndexPath = { _, _ in false }, @@ -173,47 +173,49 @@ open class TableViewSectionedDataSource // UITableViewDataSource - + @MainActor open func numberOfSections(in tableView: UITableView) -> Int { _sectionModels.count } - + @MainActor open func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { guard _sectionModels.count > section else { return 0 } return _sectionModels[section].items.count } - + @MainActor open func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { precondition(indexPath.item < _sectionModels[indexPath.section].items.count) return configureCell(self, tableView, indexPath, self[indexPath]) } - + @MainActor open func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { titleForHeaderInSection(self, section) } - + @MainActor open func tableView(_ tableView: UITableView, titleForFooterInSection section: Int) -> String? { titleForFooterInSection(self, section) } - + @MainActor open func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool { canEditRowAtIndexPath(self, indexPath) } - + @MainActor open func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool { canMoveRowAtIndexPath(self, indexPath) } - + @MainActor open func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) { self._sectionModels.moveFromSourceIndexPath(sourceIndexPath, destinationIndexPath: destinationIndexPath) } #if os(iOS) + @MainActor open func sectionIndexTitles(for tableView: UITableView) -> [String]? { sectionIndexTitles(self) } + @MainActor open func tableView(_ tableView: UITableView, sectionForSectionIndexTitle title: String, at index: Int) -> Int { sectionForSectionIndexTitle(self, title, index) } diff --git a/RxExample/RxExample-iOSTests/Mocks/MockGitHubAPI.swift b/RxExample/RxExample-iOSTests/Mocks/MockGitHubAPI.swift index 0bbafc354..69ddf7aa4 100644 --- a/RxExample/RxExample-iOSTests/Mocks/MockGitHubAPI.swift +++ b/RxExample/RxExample-iOSTests/Mocks/MockGitHubAPI.swift @@ -9,12 +9,12 @@ import RxSwift class MockGitHubAPI : GitHubAPI { - let _usernameAvailable: (String) -> Observable - let _signup: ((String, String)) -> Observable + let _usernameAvailable: @Sendable (String) -> Observable + let _signup: @Sendable ((String, String)) -> Observable init( - usernameAvailable: @escaping (String) -> Observable = notImplemented(), - signup: @escaping ((String, String)) -> Observable = notImplemented() + usernameAvailable: @escaping @Sendable (String) -> Observable = notImplemented(), + signup: @escaping @Sendable ((String, String)) -> Observable = notImplemented() ) { _usernameAvailable = usernameAvailable _signup = signup diff --git a/RxExample/RxExample-iOSTests/Mocks/MockWireframe.swift b/RxExample/RxExample-iOSTests/Mocks/MockWireframe.swift index 6696a3c21..089e622df 100644 --- a/RxExample/RxExample-iOSTests/Mocks/MockWireframe.swift +++ b/RxExample/RxExample-iOSTests/Mocks/MockWireframe.swift @@ -10,11 +10,11 @@ import RxSwift import Foundation class MockWireframe: Wireframe { - let _openURL: (URL) -> Void - let _promptFor: (String, Any, [Any]) -> Observable + let _openURL: @Sendable (URL) -> Void + let _promptFor: @Sendable (String, Any, [Any]) -> Observable - init(openURL: @escaping (URL) -> Void = notImplementedSync(), - promptFor: @escaping (String, Any, [Any]) -> Observable = notImplemented()) { + init(openURL: @escaping @Sendable (URL) -> Void = notImplementedSync(), + promptFor: @escaping @Sendable (String, Any, [Any]) -> Observable = notImplemented()) { _openURL = openURL _promptFor = promptFor } diff --git a/RxExample/RxExample-iOSTests/Mocks/NotImplementedStubs.swift b/RxExample/RxExample-iOSTests/Mocks/NotImplementedStubs.swift index 7d81e6cc0..557819200 100644 --- a/RxExample/RxExample-iOSTests/Mocks/NotImplementedStubs.swift +++ b/RxExample/RxExample-iOSTests/Mocks/NotImplementedStubs.swift @@ -22,25 +22,25 @@ func genericFatal(_ message: String) -> T { // MARK: Not implemented stubs -func notImplemented() -> (T1) -> Observable { +func notImplemented() -> @Sendable (T1) -> Observable { return { _ -> Observable in return genericFatal("Not implemented") } } -func notImplemented() -> (T1, T2) -> Observable { +func notImplemented() -> @Sendable (T1, T2) -> Observable { return { _, _ -> Observable in return genericFatal("Not implemented") } } -func notImplemented() -> (T1, T2, T3) -> Observable { +func notImplemented() -> @Sendable (T1, T2, T3) -> Observable { return { _, _, _ -> Observable in return genericFatal("Not implemented") } } -func notImplementedSync() -> (T1) -> Void { +func notImplementedSync() -> @Sendable (T1) -> Void { return { _ in genericFatal("Not implemented") } diff --git a/RxExample/RxExample-iOSTests/TestScheduler+MarbleTests.swift b/RxExample/RxExample-iOSTests/TestScheduler+MarbleTests.swift index 41a1539a3..3ee35c9cc 100644 --- a/RxExample/RxExample-iOSTests/TestScheduler+MarbleTests.swift +++ b/RxExample/RxExample-iOSTests/TestScheduler+MarbleTests.swift @@ -137,10 +137,10 @@ extension TestScheduler { - returns: Observable sequence specified by timeline and values. */ func createObservable(_ events: [[Recorded>]]) -> Observable { - var attemptCount = 0 + nonisolated(unsafe) var attemptCount = 0 print("created for \(events)") - return Observable.create { observer in + return Observable.create { @Sendable observer in if attemptCount >= events.count { fatalError("This is attempt # \(attemptCount + 1), but timeline only allows \(events.count).\n\(events)") } @@ -172,7 +172,7 @@ extension TestScheduler { - returns: Implementation of method that accepts arguments with parameter `Arg` and returns observable sequence with parameter `Ret`. */ - func mock(values: [String: Ret], errors: [String: Swift.Error] = [:], timelineSelector: @escaping (Arg) -> String) -> (Arg) -> Observable { + func mock(values: [String: Ret], errors: [String: Swift.Error] = [:], timelineSelector: @escaping @Sendable (Arg) -> String) -> (Arg) -> Observable { return { (parameters: Arg) -> Observable in let timeline = timelineSelector(parameters) diff --git a/RxExample/RxExample/Examples/GitHubSearchRepositories/GitHubSearchRepositories.swift b/RxExample/RxExample/Examples/GitHubSearchRepositories/GitHubSearchRepositories.swift index 1f6b1339d..34ecc998f 100644 --- a/RxExample/RxExample/Examples/GitHubSearchRepositories/GitHubSearchRepositories.swift +++ b/RxExample/RxExample/Examples/GitHubSearchRepositories/GitHubSearchRepositories.swift @@ -31,7 +31,8 @@ struct GitHubSearchRepositoriesState { extension GitHubSearchRepositoriesState { static let initial = GitHubSearchRepositoriesState(searchText: "") - + + @Sendable static func reduce(state: GitHubSearchRepositoriesState, command: GitHubCommand) -> GitHubSearchRepositoriesState { switch command { case .changeSearch(let text): @@ -73,8 +74,8 @@ struct GithubQuery: Equatable { */ func githubSearchRepositories( searchText: Signal, - loadNextPageTrigger: @escaping (Driver) -> Signal<()>, - performSearch: @escaping (URL) -> Observable + loadNextPageTrigger: @escaping @Sendable (Driver) -> Signal<()>, + performSearch: @escaping @Sendable (URL) -> Observable ) -> Driver { @@ -98,14 +99,14 @@ func githubSearchRepositories( return performSearch(nextURL) .asSignal(onErrorJustReturn: .failure(GitHubServiceError.networkError)) - .map(GitHubCommand.gitHubResponseReceived) + .map({ GitHubCommand.gitHubResponseReceived($0) }) } ) // this is degenerated feedback loop that doesn't depend on output state let inputFeedbackLoop: (Driver) -> Signal = { state in let loadNextPage = loadNextPageTrigger(state).map { _ in GitHubCommand.loadMoreItems } - let searchText = searchText.map(GitHubCommand.changeSearch) + let searchText = searchText.map({ GitHubCommand.changeSearch(text: $0) }) return Signal.merge(loadNextPage, searchText) } diff --git a/RxExample/RxExample/Examples/ImagePicker/UIImagePickerController+RxCreate.swift b/RxExample/RxExample/Examples/ImagePicker/UIImagePickerController+RxCreate.swift index 3839bd0a9..1ee5151a2 100644 --- a/RxExample/RxExample/Examples/ImagePicker/UIImagePickerController+RxCreate.swift +++ b/RxExample/RxExample/Examples/ImagePicker/UIImagePickerController+RxCreate.swift @@ -25,37 +25,39 @@ func dismissViewController(_ viewController: UIViewController, animated: Bool) { } extension Reactive where Base: UIImagePickerController { - static func createWithParent(_ parent: UIViewController?, animated: Bool = true, configureImagePicker: @escaping (UIImagePickerController) throws -> Void = { x in }) -> Observable { + static func createWithParent(_ parent: UIViewController?, animated: Bool = true, configureImagePicker: @escaping @Sendable (UIImagePickerController) throws -> Void = { x in }) -> Observable { return Observable.create { [weak parent] observer in - let imagePicker = UIImagePickerController() - let dismissDisposable = imagePicker.rx - .didCancel - .subscribe(onNext: { [weak imagePicker] _ in - guard let imagePicker = imagePicker else { - return - } - dismissViewController(imagePicker, animated: animated) - }) - - do { - try configureImagePicker(imagePicker) - } - catch let error { - observer.on(.error(error)) - return Disposables.create() - } - - guard let parent = parent else { - observer.on(.completed) - return Disposables.create() - } - - parent.present(imagePicker, animated: animated, completion: nil) - observer.on(.next(imagePicker)) - - return Disposables.create(dismissDisposable, Disposables.create { + MainScheduler.assumeMainActor(execute: { + let imagePicker = UIImagePickerController() + let dismissDisposable = imagePicker.rx + .didCancel + .subscribe(onNext: { [weak imagePicker] _ in + guard let imagePicker = imagePicker else { + return + } + dismissViewController(imagePicker, animated: animated) + }) + + do { + try configureImagePicker(imagePicker) + } + catch let error { + observer.on(.error(error)) + return Disposables.create() + } + + guard let parent = parent else { + observer.on(.completed) + return Disposables.create() + } + + parent.present(imagePicker, animated: animated, completion: nil) + observer.on(.next(imagePicker)) + + return Disposables.create(dismissDisposable, Disposables.create { dismissViewController(imagePicker, animated: animated) }) + }) } } } diff --git a/RxExample/RxExample/Feedbacks.swift b/RxExample/RxExample/Feedbacks.swift index 8dba562a6..b38c2b344 100644 --- a/RxExample/RxExample/Feedbacks.swift +++ b/RxExample/RxExample/Feedbacks.swift @@ -6,8 +6,8 @@ // Copyright © 2017 Krunoslav Zaher. All rights reserved. // -import RxSwift -import RxCocoa +@preconcurrency import RxSwift +@preconcurrency import RxCocoa // Taken from RxFeedback repo @@ -26,9 +26,9 @@ import RxCocoa - returns: Feedback loop performing the effects. */ public func react( - query: @escaping (State) -> Query?, - areEqual: @escaping (Query, Query) -> Bool, - effects: @escaping (Query) -> Observable + query: @escaping @Sendable (State) -> Query?, + areEqual: @escaping @Sendable (Query, Query) -> Bool, + effects: @escaping @Sendable (Query) -> Observable ) -> (ObservableSchedulerContext) -> Observable { return { state in return state.map(query) @@ -65,8 +65,8 @@ public func react( - returns: Feedback loop performing the effects. */ public func react( - query: @escaping (State) -> Query?, - effects: @escaping (Query) -> Observable + query: @escaping @Sendable (State) -> Query?, + effects: @escaping @Sendable (Query) -> Observable ) -> (ObservableSchedulerContext) -> Observable { return react(query: query, areEqual: { $0 == $1 }, effects: effects) } @@ -86,9 +86,9 @@ public func react( - returns: Feedback loop performing the effects. */ public func react( - query: @escaping (State) -> Query?, - areEqual: @escaping (Query, Query) -> Bool, - effects: @escaping (Query) -> Signal + query: @escaping @Sendable (State) -> Query?, + areEqual: @escaping @Sendable (Query, Query) -> Bool, + effects: @escaping @Sendable (Query) -> Signal ) -> (Driver) -> Signal { return { state in let observableSchedulerContext = ObservableSchedulerContext( @@ -114,8 +114,8 @@ public func react( - returns: Feedback loop performing the effects. */ public func react( - query: @escaping (State) -> Query?, - effects: @escaping (Query) -> Signal + query: @escaping @Sendable (State) -> Query?, + effects: @escaping @Sendable (Query) -> Signal ) -> (Driver) -> Signal { return { state in let observableSchedulerContext = ObservableSchedulerContext( @@ -141,8 +141,8 @@ public func react( - returns: Feedback loop performing the effects. */ public func react( - query: @escaping (State) -> Query?, - effects: @escaping (Query) -> Observable + query: @escaping @Sendable (State) -> Query?, + effects: @escaping @Sendable (Query) -> Observable ) -> (ObservableSchedulerContext) -> Observable { return { state in return state.map(query) @@ -172,8 +172,8 @@ public func react( - returns: Feedback loop performing the effects. */ public func react( - query: @escaping (State) -> Query?, - effects: @escaping (Query) -> Signal + query: @escaping @Sendable (State) -> Query?, + effects: @escaping @Sendable (Query) -> Signal ) -> (Driver) -> Signal { return { state in let observableSchedulerContext = ObservableSchedulerContext( @@ -200,8 +200,8 @@ public func react( - returns: Feedback loop performing the effects. */ public func react( - query: @escaping (State) -> Set, - effects: @escaping (Query) -> Observable + query: @escaping @Sendable (State) -> Set, + effects: @escaping @Sendable (Query) -> Observable ) -> (ObservableSchedulerContext) -> Observable { return { state in let query = state.map(query) @@ -250,8 +250,8 @@ extension ObservableType { - returns: Feedback loop performing the effects. */ public func react( - query: @escaping (State) -> Set, - effects: @escaping (Query) -> Signal + query: @escaping @Sendable (State) -> Set, + effects: @escaping @Sendable (Query) -> Signal ) -> (Driver) -> Signal { return { (state: Driver) -> Signal in let observableSchedulerContext = ObservableSchedulerContext( @@ -314,7 +314,7 @@ public class Bindings: Disposable { /** Bi-directional binding of a system State to external state machine and events from it. */ -public func bind(_ bindings: @escaping (ObservableSchedulerContext) -> (Bindings)) -> (ObservableSchedulerContext) -> Observable { +public func bind(_ bindings: @escaping @Sendable (ObservableSchedulerContext) -> (Bindings)) -> @Sendable (ObservableSchedulerContext) -> Observable { return { (state: ObservableSchedulerContext) -> Observable in return Observable.using({ () -> Bindings in return bindings(state) @@ -329,7 +329,7 @@ public func bind(_ bindings: @escaping (ObservableSchedulerContext Bi-directional binding of a system State to external state machine and events from it. Strongify owner. */ -public func bind(_ owner: WeakOwner, _ bindings: @escaping (WeakOwner, ObservableSchedulerContext) -> (Bindings)) +public func bind(_ owner: WeakOwner, _ bindings: @escaping @Sendable (WeakOwner, ObservableSchedulerContext) -> (Bindings)) -> (ObservableSchedulerContext) -> Observable where WeakOwner: AnyObject { return bind(bindingsStrongify(owner, bindings)) } @@ -337,7 +337,7 @@ public func bind(_ owner: WeakOwner, _ bindings: @escap /** Bi-directional binding of a system State to external state machine and events from it. */ -public func bind(_ bindings: @escaping (Driver) -> (Bindings)) -> (Driver) -> Signal { +public func bind(_ bindings: @escaping @Sendable (Driver) -> (Bindings)) -> @Sendable (Driver) -> Signal { return { (state: Driver) -> Signal in return Observable.using({ () -> Bindings in return bindings(state) @@ -354,12 +354,13 @@ public func bind(_ bindings: @escaping (Driver) -> (Binding Bi-directional binding of a system State to external state machine and events from it. Strongify owner. */ -public func bind(_ owner: WeakOwner, _ bindings: @escaping (WeakOwner, Driver) -> (Bindings)) - -> (Driver) -> Signal where WeakOwner: AnyObject { +public func bind(_ owner: WeakOwner, _ bindings: @escaping @Sendable (WeakOwner, Driver) -> (Bindings)) + -> @Sendable (Driver) -> Signal where WeakOwner: AnyObject { return bind(bindingsStrongify(owner, bindings)) } -private func bindingsStrongify(_ owner: WeakOwner, _ bindings: @escaping (WeakOwner, O) -> (Bindings)) +@Sendable +private func bindingsStrongify(_ owner: WeakOwner, _ bindings: @escaping @Sendable (WeakOwner, O) -> (Bindings)) -> (O) -> (Bindings) where WeakOwner: AnyObject { return { [weak owner] state -> Bindings in guard let strongOwner = owner else { diff --git a/RxExample/RxExample/Observable+Extensions.swift b/RxExample/RxExample/Observable+Extensions.swift index 035702166..c0fe651e5 100644 --- a/RxExample/RxExample/Observable+Extensions.swift +++ b/RxExample/RxExample/Observable+Extensions.swift @@ -30,7 +30,7 @@ extension ObservableType where Element == Any { */ public static func system( initialState: State, - reduce: @escaping (State, Event) -> State, + reduce: @escaping @Sendable (State, Event) -> State, scheduler: ImmediateSchedulerType, scheduledFeedback: [Feedback] ) -> Observable { @@ -61,7 +61,7 @@ extension ObservableType where Element == Any { public static func system( initialState: State, - reduce: @escaping (State, Event) -> State, + reduce: @escaping @Sendable (State, Event) -> State, scheduler: ImmediateSchedulerType, scheduledFeedback: Feedback... ) -> Observable { @@ -86,7 +86,7 @@ extension SharedSequenceConvertibleType where Element == Any, SharingStrategy == */ public static func system( initialState: State, - reduce: @escaping (State, Event) -> State, + reduce: @escaping @Sendable (State, Event) -> State, feedback: [Feedback] ) -> Driver { let observableFeedbacks: [(ObservableSchedulerContext) -> Observable] = feedback.map { feedback in @@ -107,7 +107,7 @@ extension SharedSequenceConvertibleType where Element == Any, SharingStrategy == public static func system( initialState: State, - reduce: @escaping (State, Event) -> State, + reduce: @escaping @Sendable (State, Event) -> State, feedback: Feedback... ) -> Driver { system(initialState: initialState, reduce: reduce, feedback: feedback) diff --git a/RxExample/RxExample/Services/ActivityIndicator.swift b/RxExample/RxExample/Services/ActivityIndicator.swift index 54e47ff95..1b27fb80c 100644 --- a/RxExample/RxExample/Services/ActivityIndicator.swift +++ b/RxExample/RxExample/Services/ActivityIndicator.swift @@ -13,7 +13,7 @@ private struct ActivityToken : ObservableConvertibleType, Disposable { private let _source: Observable private let _dispose: Cancelable - init(source: Observable, disposeAction: @escaping () -> Void) { + init(source: Observable, disposeAction: @escaping @Sendable () -> Void) { _source = source _dispose = Disposables.create(with: disposeAction) } @@ -55,13 +55,15 @@ public class ActivityIndicator : SharedSequenceConvertibleType { return t.asObservable() } } - + + @Sendable private func increment() { _lock.lock() _relay.accept(_relay.value + 1) _lock.unlock() } - + + @Sendable private func decrement() { _lock.lock() _relay.accept(_relay.value - 1) diff --git a/RxExample/RxExample/Services/GeolocationService.swift b/RxExample/RxExample/Services/GeolocationService.swift index 18ebea627..cf0c5b607 100644 --- a/RxExample/RxExample/Services/GeolocationService.swift +++ b/RxExample/RxExample/Services/GeolocationService.swift @@ -13,8 +13,8 @@ import RxCocoa class GeolocationService { static let instance = GeolocationService() - private (set) var authorized: Driver - private (set) var location: Driver + private(set) var authorized: Driver + private(set) var location: Driver private let locationManager = CLLocationManager() diff --git a/RxExample/RxExample/Services/UIImageView+DownloadableImage.swift b/RxExample/RxExample/Services/UIImageView+DownloadableImage.swift index c800eba08..a92a56a1b 100644 --- a/RxExample/RxExample/Services/UIImageView+DownloadableImage.swift +++ b/RxExample/RxExample/Services/UIImageView+DownloadableImage.swift @@ -20,19 +20,21 @@ extension Reactive where Base: UIImageView { func downloadableImageAnimated(_ transitionType: String?) -> Binder { return Binder(base) { imageView, image in - for subview in imageView.subviews { - subview.removeFromSuperview() - } - switch image { - case .content(let image): - (imageView as UIImageView).rx.image.on(.next(image)) - case .offlinePlaceholder: - let label = UILabel(frame: imageView.bounds) - label.textAlignment = .center - label.font = UIFont.systemFont(ofSize: 35) - label.text = "⚠️" - imageView.addSubview(label) - } + MainScheduler.assumeMainActor(execute: { + for subview in imageView.subviews { + subview.removeFromSuperview() + } + switch image { + case .content(let image): + (imageView as UIImageView).rx.image.on(.next(image)) + case .offlinePlaceholder: + let label = UILabel(frame: imageView.bounds) + label.textAlignment = .center + label.font = UIFont.systemFont(ofSize: 35) + label.text = "⚠️" + imageView.addSubview(label) + } + }) } } } diff --git a/RxSwift/Schedulers/MainScheduler.swift b/RxSwift/Schedulers/MainScheduler.swift index 1622693d6..4aa8736c9 100644 --- a/RxSwift/Schedulers/MainScheduler.swift +++ b/RxSwift/Schedulers/MainScheduler.swift @@ -78,3 +78,42 @@ public final class MainScheduler : SerialDispatchQueueScheduler { return cancel } } + +extension MainScheduler { + // implementation copied from from assumeIsolated. This is copied because assumeIsolated has @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *). This implementation also remove the check that the closure is executed on the main actor. + @preconcurrency nonisolated + static private func _assumeMainActor(execute operation: @MainActor(unsafe) () throws -> T) rethrows -> T { + typealias YesActor = @MainActor () throws -> T + typealias NoActor = () throws -> T + + // To do the unsafe cast, we have to pretend it's @escaping. + return try withoutActuallyEscaping(operation) { (_ fn: @escaping YesActor) throws -> T in + let rawFn = unsafeBitCast(fn, to: NoActor.self) + return try rawFn() + } + } + + @preconcurrency nonisolated + static public func assumeMainActor(execute operation: @MainActor(unsafe) () throws -> T) rethrows -> T { + ensureRunningOnMainThread() + return try _assumeMainActor(execute: operation) + } + + public static func assumeMainActor(_ work: @escaping @Sendable @MainActor(assumed) () -> T) -> (@Sendable () -> T) { + return { @Sendable () -> T in + return MainScheduler.assumeMainActor(execute: { return work() }) + } + } + + public static func assumeMainActor(_ work: @escaping @Sendable @MainActor(assumed) (Value) -> T) -> (@Sendable (Value) -> T) { + return { @Sendable (value: Value) -> T in + return MainScheduler.assumeMainActor(execute: { return work(value) }) + } + } + + public static func assumeMainActor(_ work: @escaping @Sendable @MainActor(assumed) (Value1, Value2) -> T) -> (@Sendable (Value1, Value2) -> T) { + return { @Sendable (value1: Value1, value2: Value2) -> T in + return MainScheduler.assumeMainActor(execute: { return work(value1, value2) }) + } + } +} diff --git a/RxTest/Schedulers/TestScheduler.swift b/RxTest/Schedulers/TestScheduler.swift index af15d1fee..4ec3ce05f 100644 --- a/RxTest/Schedulers/TestScheduler.swift +++ b/RxTest/Schedulers/TestScheduler.swift @@ -70,7 +70,7 @@ public class TestScheduler : VirtualTimeScheduler Void) { + public func scheduleAt(_ time: TestTime, action: @escaping @Sendable () -> Void) { _ = self.scheduleAbsoluteVirtual((), time: time, action: { _ -> Disposable in action() return Disposables.create() @@ -93,10 +93,10 @@ public class TestScheduler : VirtualTimeScheduler(created: TestTime, subscribed: TestTime, disposed: TestTime, create: @escaping () -> OutputSequence) + public func start(created: TestTime, subscribed: TestTime, disposed: TestTime, create: @escaping @Sendable () -> OutputSequence) -> TestableObserver where OutputSequence.Element == Element { - var source: Observable? - var subscription: Disposable? + nonisolated(unsafe) var source: Observable? + nonisolated(unsafe) var subscription: Disposable? let observer = self.createObserver(Element.self) _ = self.scheduleAbsoluteVirtual((), time: created) { _ in @@ -130,7 +130,7 @@ public class TestScheduler : VirtualTimeScheduler(disposed: TestTime, create: @escaping () -> OutputSequence) + public func start(disposed: TestTime, create: @escaping @Sendable () -> OutputSequence) -> TestableObserver where OutputSequence.Element == Element { self.start(created: Defaults.created, subscribed: Defaults.subscribed, disposed: disposed, create: create) } @@ -146,7 +146,7 @@ public class TestScheduler : VirtualTimeScheduler(_ create: @escaping () -> OutputSequence) + public func start(_ create: @escaping @Sendable () -> OutputSequence) -> TestableObserver where OutputSequence.Element == Element { self.start(created: Defaults.created, subscribed: Defaults.subscribed, disposed: Defaults.disposed, create: create) } diff --git a/Tests/RxCocoaTests/DelegateProxyTest.swift b/Tests/RxCocoaTests/DelegateProxyTest.swift index b0f930f03..23d632ffd 100644 --- a/Tests/RxCocoaTests/DelegateProxyTest.swift +++ b/Tests/RxCocoaTests/DelegateProxyTest.swift @@ -97,12 +97,12 @@ final class DelegateProxyTest : RxTest { view.delegate = mock - var observedFeedRequestSentMessage = false - var observedMessageInvoked = false - var events: [MessageProcessingStage] = [] + nonisolated(unsafe) var observedFeedRequestSentMessage = false + nonisolated(unsafe) var observedMessageInvoked = false + nonisolated(unsafe) var events: [MessageProcessingStage] = [] - var delegates: [NSObject?] = [] - var responds: [Bool] = [] + nonisolated(unsafe) var delegates: [NSObject?] = [] + nonisolated(unsafe) var responds: [Bool] = [] _ = view.rx.observeWeakly(NSObject.self, "delegate").skip(1).subscribe(onNext: { delegate in delegates.append(delegate) @@ -155,8 +155,8 @@ final class DelegateProxyTest : RxTest { view.delegate = mock - var nMessages = 0 - var invoked = false + nonisolated(unsafe) var nMessages = 0 + nonisolated(unsafe) var invoked = false let d = view.rx.proxy.sentMessage(#selector(ThreeDSectionedViewProtocol.threeDView(_:didLearnSomething:))) .subscribe(onNext: { n in @@ -209,13 +209,13 @@ final class DelegateProxyTest : RxTest { let sentArgument = IndexPath(index: 0) - var receivedArgumentSentMessage: IndexPath? = nil - var receivedArgumentMethodInvoked: IndexPath? = nil + nonisolated(unsafe) var receivedArgumentSentMessage: IndexPath? = nil + nonisolated(unsafe) var receivedArgumentMethodInvoked: IndexPath? = nil - var events: [MessageProcessingStage] = [] + nonisolated(unsafe) var events: [MessageProcessingStage] = [] - var delegates: [NSObject?] = [] - var responds: [Bool] = [] + nonisolated(unsafe) var delegates: [NSObject?] = [] + nonisolated(unsafe) var responds: [Bool] = [] _ = view.rx.observeWeakly(NSObject.self, "delegate").skip(1).subscribe(onNext: { delegate in delegates.append(delegate) @@ -278,8 +278,8 @@ final class DelegateProxyTest : RxTest { view.delegate = mock - var completedSentMessage = false - var completedMethodInvoked = false + nonisolated(unsafe) var completedSentMessage = false + nonisolated(unsafe) var completedMethodInvoked = false autoreleasepool { XCTAssertTrue(!mock.responds(to: NSSelectorFromString("threeDView:threeDView:didGetXXX:"))) @@ -359,7 +359,7 @@ extension DelegateProxyTest { XCTAssertTrue(view.delegate === proxy) XCTAssertTrue(view.rx.proxy.forwardToDelegate() === mock) - var latestValue: Int? = nil + nonisolated(unsafe) var latestValue: Int? = nil _ = view.rx.testIt.subscribe(onNext: { latestValue = $0 }) @@ -383,7 +383,7 @@ extension DelegateProxyTest { // MARK: Testing extensions extension DelegateProxyTest { - func performDelegateTest( _ createControl: @autoclosure() -> Control, make: @escaping (Control) -> ExtendedProxy) { + func performDelegateTest( _ createControl: @autoclosure() -> Control, make: @escaping @Sendable (Control) -> ExtendedProxy) { ExtendedProxy.register(make: make) var control: Control! @@ -391,12 +391,12 @@ extension DelegateProxyTest { control = createControl() } - var receivedValueSentMessage: Int! - var receivedValueMethodInvoked: Int! - var completedSentMessage = false - var completedMethodInvoked = false - var deallocated = false - var stages: [MessageProcessingStage] = [] + nonisolated(unsafe) var receivedValueSentMessage: Int! + nonisolated(unsafe) var receivedValueMethodInvoked: Int! + nonisolated(unsafe) var completedSentMessage = false + nonisolated(unsafe) var completedMethodInvoked = false + nonisolated(unsafe) var deallocated = false + nonisolated(unsafe) var stages: [MessageProcessingStage] = [] let expectation = self.expectation(description: "dealloc") autoreleasepool { _ = control.testSentMessage.subscribe(onNext: { value in diff --git a/Tests/RxCocoaTests/KVOObservableTests.swift b/Tests/RxCocoaTests/KVOObservableTests.swift index 3a19248eb..35e4c433f 100644 --- a/Tests/RxCocoaTests/KVOObservableTests.swift +++ b/Tests/RxCocoaTests/KVOObservableTests.swift @@ -34,7 +34,7 @@ final class Parent : NSObject { @objc dynamic var val: String = "" - init(callback: @escaping (String?) -> Void) { + init(callback: @escaping @Sendable (String?) -> Void) { super.init() self.rx.observe(String.self, "val", options: [.initial, .new], retainSelf: false) @@ -50,7 +50,7 @@ final class Parent : NSObject { final class Child : NSObject { let disposeBag = DisposeBag() - init(parent: ParentWithChild, callback: @escaping (String?) -> Void) { + init(parent: ParentWithChild, callback: @escaping @Sendable (String?) -> Void) { super.init() parent.rx.observe(String.self, "val", options: [.initial, .new], retainSelf: false) .subscribe(onNext: callback) @@ -67,7 +67,7 @@ final class ParentWithChild : NSObject { var child: Child? = nil - init(callback: @escaping (String?) -> Void) { + init(callback: @escaping @Sendable (String?) -> Void) { super.init() child = Child(parent: self, callback: callback) } @@ -143,8 +143,8 @@ extension KVOObservableTests { func testKeyPathObservation_DefaultOptions() { testClass = TestClass() let os = testClass.rx.observe(\.pr) - var latest: String? - var completed = false + nonisolated(unsafe) var latest: String? + nonisolated(unsafe) var completed = false _ = os.subscribe(onNext: { latest = $0 }, onCompleted: { completed = true }) @@ -171,7 +171,7 @@ extension KVOObservableTests { func testKeyPathObservation_NewAndInitialOptions() { let testClass = TestClass() let os = testClass.rx.observe(\.pr, options: [.new, .initial]) - var latest: String? + nonisolated(unsafe) var latest: String? let d = os.subscribe(onNext: { latest = $0 }) testClass.pr = "1" @@ -195,8 +195,8 @@ extension KVOObservableTests { func testKeyPathObservation_NewOptions() { testClass = TestClass() let os = testClass.rx.observe(\.pr, options: [.new]) - var latest: String? - var completed = false + nonisolated(unsafe) var latest: String? + nonisolated(unsafe) var completed = false _ = os.subscribe(onNext: { latest = $0 }, onCompleted: { completed = true }) @@ -230,7 +230,7 @@ extension KVOObservableTests { let os = testClass.rx.observe(String.self, "pr", options: .new) - var latest: String? + nonisolated(unsafe) var latest: String? let d = os.subscribe(onNext: { latest = $0 }) @@ -264,7 +264,7 @@ extension KVOObservableTests { let os = testClass.rx.observe(String.self, "pr", options: [.initial, .new]) - var latest: String? + nonisolated(unsafe) var latest: String? let d = os.subscribe(onNext: { latest = $0 }) @@ -298,7 +298,7 @@ extension KVOObservableTests { let os = testClass.rx.observe(String.self, "pr") - var latest: String? + nonisolated(unsafe) var latest: String? let d = os.subscribe(onNext: { latest = $0 }) @@ -328,8 +328,8 @@ extension KVOObservableTests { } func test_ObserveAndDontRetainWorks() { - var latest: String? - var isDisposed = false + nonisolated(unsafe) var latest: String? + nonisolated(unsafe) var isDisposed = false parent = Parent { n in latest = n @@ -355,8 +355,8 @@ extension KVOObservableTests { } func test_ObserveAndDontRetainWorks2() { - var latest: String? - var isDisposed = false + nonisolated(unsafe) var latest: String? + nonisolated(unsafe) var isDisposed = false parentWithChild = ParentWithChild { n in latest = n @@ -388,8 +388,8 @@ extension KVOObservableTests { extension KVOObservableTests { func testObserveWeak_SimpleStrongProperty() { - var latest: String? - var isDisposed = false + nonisolated(unsafe) var latest: String? + nonisolated(unsafe) var isDisposed = false hasStrongProperty = HasStrongProperty() @@ -418,8 +418,8 @@ extension KVOObservableTests { } func testObserveWeak_SimpleWeakProperty() { - var latest: String? - var isDisposed = false + nonisolated(unsafe) var latest: String? + nonisolated(unsafe) var isDisposed = false hasWeakProperty = HasWeakProperty() @@ -450,8 +450,8 @@ extension KVOObservableTests { } func testObserveWeak_ObserveFirst_Weak_Strong_Basic() { - var latest: String? - var isDisposed = false + nonisolated(unsafe) var latest: String? + nonisolated(unsafe) var isDisposed = false hasStrongProperty = HasStrongProperty() hasWeakProperty = HasWeakProperty() @@ -489,8 +489,8 @@ extension KVOObservableTests { } func testObserveWeak_Weak_Strong_Observe_Basic() { - var latest: String? - var isDisposed = false + nonisolated(unsafe) var latest: String? + nonisolated(unsafe) var isDisposed = false hasStrongProperty = HasStrongProperty() hasWeakProperty = HasWeakProperty() @@ -525,8 +525,8 @@ extension KVOObservableTests { } func testObserveWeak_ObserveFirst_Strong_Weak_Basic() { - var latest: String? - var isDisposed = false + nonisolated(unsafe) var latest: String? + nonisolated(unsafe) var isDisposed = false hasWeakProperty = HasWeakProperty() hasStrongProperty = HasStrongProperty() @@ -564,8 +564,8 @@ extension KVOObservableTests { } func testObserveWeak_Strong_Weak_Observe_Basic() { - var latest: String? - var isDisposed = false + nonisolated(unsafe) var latest: String? + nonisolated(unsafe) var isDisposed = false hasWeakProperty = HasWeakProperty() hasStrongProperty = HasStrongProperty() @@ -601,16 +601,16 @@ extension KVOObservableTests { // compiler won't release weak references otherwise :( func _testObserveWeak_Strong_Weak_Observe_NilLastPropertyBecauseOfWeak() -> (HasWeakProperty, NSObject?, Observable) { - var dealloc: Observable! = nil + nonisolated(unsafe) var dealloc: Observable! = nil let child: HasWeakProperty! = HasWeakProperty() - var latest: NSObject? = nil + nonisolated(unsafe) var latest: NSObject? = nil autoreleasepool { let root: HasStrongProperty! = HasStrongProperty() root.property = child - var one: NSObject! = nil + nonisolated(unsafe) var one: NSObject! = nil one = NSObject() @@ -634,7 +634,7 @@ extension KVOObservableTests { } func testObserveWeak_Strong_Weak_Observe_NilLastPropertyBecauseOfWeak() { - var gone = false + nonisolated(unsafe) var gone = false let (child, latest, dealloc) = _testObserveWeak_Strong_Weak_Observe_NilLastPropertyBecauseOfWeak() _ = dealloc .subscribe(onNext: { n in @@ -647,9 +647,9 @@ extension KVOObservableTests { } func _testObserveWeak_Weak_Weak_Weak_middle_NilifyCorrectly() -> (HasWeakProperty, NSObject?, Observable) { - var dealloc: Observable! = nil - var middle: HasWeakProperty! = HasWeakProperty() - var latest: NSObject? = nil + nonisolated(unsafe) var dealloc: Observable! = nil + nonisolated(unsafe) var middle: HasWeakProperty! = HasWeakProperty() + nonisolated(unsafe) var latest: NSObject? = nil let root: HasWeakProperty! = HasWeakProperty() autoreleasepool { @@ -683,7 +683,7 @@ extension KVOObservableTests { func testObserveWeak_Weak_Weak_Weak_middle_NilifyCorrectly() { let (root, latest, deallocatedMiddle) = _testObserveWeak_Weak_Weak_Weak_middle_NilifyCorrectly() - var gone = false + nonisolated(unsafe) var gone = false _ = deallocatedMiddle .subscribe(onCompleted: { @@ -696,9 +696,9 @@ extension KVOObservableTests { } func testObserveWeak_TargetDeallocated() { - var root: HasStrongProperty! = HasStrongProperty() + nonisolated(unsafe) var root: HasStrongProperty! = HasStrongProperty() - var latest: String? = nil + nonisolated(unsafe) var latest: String? = nil root.property = "a".duplicate() @@ -712,7 +712,7 @@ extension KVOObservableTests { XCTAssertTrue(latest == "a") - var rootDeallocated = false + nonisolated(unsafe) var rootDeallocated = false _ = root .rx.deallocated @@ -727,9 +727,9 @@ extension KVOObservableTests { } func testObserveWeakWithOptions_ObserveNotInitialValue() { - var root: HasStrongProperty! = HasStrongProperty() + nonisolated(unsafe) var root: HasStrongProperty! = HasStrongProperty() - var latest: String? = nil + nonisolated(unsafe) var latest: String? = nil root.property = "a".duplicate() @@ -747,7 +747,7 @@ extension KVOObservableTests { XCTAssertTrue(latest == "b") - var rootDeallocated = false + nonisolated(unsafe) var rootDeallocated = false _ = root .rx.deallocated @@ -764,9 +764,9 @@ extension KVOObservableTests { #if os(macOS) // just making sure it's all the same for NS extensions func testObserve_ObserveNSRect() { - var root: HasStrongProperty! = HasStrongProperty() + nonisolated(unsafe) var root: HasStrongProperty! = HasStrongProperty() - var latest: NSRect? = nil + nonisolated(unsafe) var latest: NSRect? = nil XCTAssertTrue(latest == nil) @@ -780,7 +780,7 @@ extension KVOObservableTests { XCTAssertTrue(latest == NSRect(x: -2, y: 0, width: 0, height: 1)) - var rootDeallocated = false + nonisolated(unsafe) var rootDeallocated = false _ = root .rx.deallocated @@ -800,9 +800,9 @@ extension KVOObservableTests { // let's just check for one, other ones should have the same check func testObserve_ObserveCGRectForBiggerStructureDoesntCrashPropertyTypeReturnsNil() { - var root: HasStrongProperty! = HasStrongProperty() + nonisolated(unsafe) var root: HasStrongProperty! = HasStrongProperty() - var latest: CGSize? = nil + nonisolated(unsafe) var latest: CGSize? = nil XCTAssertTrue(latest == nil) @@ -821,7 +821,7 @@ extension KVOObservableTests { XCTAssertTrue(latest == nil) - var rootDeallocated = false + nonisolated(unsafe) var rootDeallocated = false _ = root .rx.deallocated @@ -836,9 +836,9 @@ extension KVOObservableTests { } func testObserve_ObserveCGRect() { - var root: HasStrongProperty! = HasStrongProperty() + nonisolated(unsafe) var root: HasStrongProperty! = HasStrongProperty() - var latest: CGRect? = nil + nonisolated(unsafe) var latest: CGRect? = nil XCTAssertTrue(latest == nil) @@ -857,7 +857,7 @@ extension KVOObservableTests { XCTAssertTrue(latest == CGRect(x: -2, y: 0, width: 0, height: 1)) - var rootDeallocated = false + nonisolated(unsafe) var rootDeallocated = false _ = root .rx.deallocated @@ -872,9 +872,9 @@ extension KVOObservableTests { } func testObserve_ObserveCGSize() { - var root: HasStrongProperty! = HasStrongProperty() + nonisolated(unsafe) var root: HasStrongProperty! = HasStrongProperty() - var latest: CGSize? = nil + nonisolated(unsafe) var latest: CGSize? = nil XCTAssertTrue(latest == nil) @@ -893,7 +893,7 @@ extension KVOObservableTests { XCTAssertTrue(latest == CGSize(width: 56, height: 1)) - var rootDeallocated = false + nonisolated(unsafe) var rootDeallocated = false _ = root .rx.deallocated @@ -908,9 +908,9 @@ extension KVOObservableTests { } func testObserve_ObserveCGPoint() { - var root: HasStrongProperty! = HasStrongProperty() + nonisolated(unsafe) var root: HasStrongProperty! = HasStrongProperty() - var latest: CGPoint? = nil + nonisolated(unsafe) var latest: CGPoint? = nil XCTAssertTrue(latest == nil) @@ -928,7 +928,7 @@ extension KVOObservableTests { XCTAssertTrue(latest == CGPoint(x: -100, y: 1)) - var rootDeallocated = false + nonisolated(unsafe) var rootDeallocated = false _ = root .rx.deallocated @@ -944,9 +944,9 @@ extension KVOObservableTests { func testObserveWeak_ObserveCGRect() { - var root: HasStrongProperty! = HasStrongProperty() + nonisolated(unsafe) var root: HasStrongProperty! = HasStrongProperty() - var latest: CGRect? = nil + nonisolated(unsafe) var latest: CGRect? = nil XCTAssertTrue(latest == nil) @@ -961,7 +961,7 @@ extension KVOObservableTests { XCTAssertTrue(latest == CGRect(x: -2, y: 0, width: 0, height: 1)) - var rootDeallocated = false + nonisolated(unsafe) var rootDeallocated = false _ = root .rx.deallocated @@ -976,9 +976,9 @@ extension KVOObservableTests { } func testObserveWeak_ObserveCGSize() { - var root: HasStrongProperty! = HasStrongProperty() + nonisolated(unsafe) var root: HasStrongProperty! = HasStrongProperty() - var latest: CGSize? = nil + nonisolated(unsafe) var latest: CGSize? = nil XCTAssertTrue(latest == nil) @@ -993,7 +993,7 @@ extension KVOObservableTests { XCTAssertTrue(latest == CGSize(width: 56, height: 1)) - var rootDeallocated = false + nonisolated(unsafe) var rootDeallocated = false _ = root .rx.deallocated @@ -1008,9 +1008,9 @@ extension KVOObservableTests { } func testObserveWeak_ObserveCGPoint() { - var root: HasStrongProperty! = HasStrongProperty() + nonisolated(unsafe) var root: HasStrongProperty! = HasStrongProperty() - var latest: CGPoint? = nil + nonisolated(unsafe) var latest: CGPoint? = nil XCTAssertTrue(latest == nil) @@ -1026,7 +1026,7 @@ extension KVOObservableTests { XCTAssertTrue(latest == CGPoint(x: -100, y: 1)) - var rootDeallocated = false + nonisolated(unsafe) var rootDeallocated = false _ = root .rx.deallocated @@ -1041,9 +1041,9 @@ extension KVOObservableTests { } func testObserveWeak_ObserveInt() { - var root: HasStrongProperty! = HasStrongProperty() + nonisolated(unsafe) var root: HasStrongProperty! = HasStrongProperty() - var latest: Int? = nil + nonisolated(unsafe) var latest: Int? = nil XCTAssertTrue(latest == nil) @@ -1058,7 +1058,7 @@ extension KVOObservableTests { XCTAssertTrue(latest == 10) - var rootDeallocated = false + nonisolated(unsafe) var rootDeallocated = false _ = root .rx.deallocated @@ -1073,9 +1073,9 @@ extension KVOObservableTests { } func testObserveWeak_PropertyDoesntExist() { - var root: HasStrongProperty! = HasStrongProperty() + nonisolated(unsafe) var root: HasStrongProperty! = HasStrongProperty() - var lastError: Swift.Error? = nil + nonisolated(unsafe) var lastError: Swift.Error? = nil _ = root.rx.observeWeakly(NSNumber.self, "notExist") .subscribe(onError: { error in @@ -1085,7 +1085,7 @@ extension KVOObservableTests { XCTAssertTrue(lastError != nil) lastError = nil - var rootDeallocated = false + nonisolated(unsafe) var rootDeallocated = false _ = root .rx.deallocated @@ -1099,9 +1099,9 @@ extension KVOObservableTests { } func testObserveWeak_HierarchyPropertyDoesntExist() { - var root: HasStrongProperty! = HasStrongProperty() + nonisolated(unsafe) var root: HasStrongProperty! = HasStrongProperty() - var lastError: Swift.Error? = nil + nonisolated(unsafe) var lastError: Swift.Error? = nil _ = root.rx.observeWeakly(NSNumber.self, "property.notExist") .subscribe(onError: { error in @@ -1114,7 +1114,7 @@ extension KVOObservableTests { XCTAssertTrue(lastError != nil) - var rootDeallocated = false + nonisolated(unsafe) var rootDeallocated = false _ = root .rx.deallocated @@ -1133,9 +1133,9 @@ extension KVOObservableTests { extension KVOObservableTests { func testObserve_ObserveIntegerRepresentable() { - var root: HasStrongProperty! = HasStrongProperty() + nonisolated(unsafe) var root: HasStrongProperty! = HasStrongProperty() - var latest: Int? + nonisolated(unsafe) var latest: Int? XCTAssertTrue(latest == nil) @@ -1149,7 +1149,7 @@ extension KVOObservableTests { XCTAssertTrue(latest == 2) - var rootDeallocated = false + nonisolated(unsafe) var rootDeallocated = false _ = root .rx.deallocated @@ -1166,9 +1166,9 @@ extension KVOObservableTests { } func testObserve_ObserveUIntegerRepresentable() { - var root: HasStrongProperty! = HasStrongProperty() + nonisolated(unsafe) var root: HasStrongProperty! = HasStrongProperty() - var latest: UInt? + nonisolated(unsafe) var latest: UInt? XCTAssertTrue(latest == nil) @@ -1182,7 +1182,7 @@ extension KVOObservableTests { XCTAssertTrue(latest == 2) - var rootDeallocated = false + nonisolated(unsafe) var rootDeallocated = false _ = root .rx.deallocated @@ -1202,9 +1202,9 @@ extension KVOObservableTests { #if !DISABLE_SWIZZLING extension KVOObservableTests { func testObserveWeak_ObserveIntegerRepresentable() { - var root: HasStrongProperty! = HasStrongProperty() + nonisolated(unsafe) var root: HasStrongProperty! = HasStrongProperty() - var latest: Int? + nonisolated(unsafe) var latest: Int? XCTAssertTrue(latest == nil) @@ -1220,7 +1220,7 @@ extension KVOObservableTests { XCTAssertTrue(latest == 2) - var rootDeallocated = false + nonisolated(unsafe) var rootDeallocated = false _ = root .rx.deallocated @@ -1235,9 +1235,9 @@ extension KVOObservableTests { } func testObserveWeak_ObserveUIntegerRepresentable() { - var root: HasStrongProperty! = HasStrongProperty() + nonisolated(unsafe) var root: HasStrongProperty! = HasStrongProperty() - var latest: UInt? + nonisolated(unsafe) var latest: UInt? XCTAssertTrue(latest == nil) @@ -1253,7 +1253,7 @@ extension KVOObservableTests { XCTAssertTrue(latest == 2) - var rootDeallocated = false + nonisolated(unsafe) var rootDeallocated = false _ = root .rx.deallocated @@ -1272,9 +1272,9 @@ extension KVOObservableTests { // MARK: RawRepresentable extension KVOObservableTests { func testObserve_ObserveIntEnum() { - var root: HasStrongProperty! = HasStrongProperty() + nonisolated(unsafe) var root: HasStrongProperty! = HasStrongProperty() - var latest: IntEnum? + nonisolated(unsafe) var latest: IntEnum? XCTAssertTrue(latest == nil) @@ -1288,7 +1288,7 @@ extension KVOObservableTests { XCTAssertTrue(latest == .two) - var rootDeallocated = false + nonisolated(unsafe) var rootDeallocated = false _ = root .rx.deallocated @@ -1305,9 +1305,9 @@ extension KVOObservableTests { } func testObserve_ObserveInt32Enum() { - var root: HasStrongProperty! = HasStrongProperty() + nonisolated(unsafe) var root: HasStrongProperty! = HasStrongProperty() - var latest: Int32Enum? + nonisolated(unsafe) var latest: Int32Enum? XCTAssertTrue(latest == nil) @@ -1321,7 +1321,7 @@ extension KVOObservableTests { XCTAssertTrue(latest == .two) - var rootDeallocated = false + nonisolated(unsafe) var rootDeallocated = false _ = root .rx.deallocated @@ -1338,9 +1338,9 @@ extension KVOObservableTests { } func testObserve_ObserveInt64Enum() { - var root: HasStrongProperty! = HasStrongProperty() + nonisolated(unsafe) var root: HasStrongProperty! = HasStrongProperty() - var latest: Int64Enum? + nonisolated(unsafe) var latest: Int64Enum? XCTAssertTrue(latest == nil) @@ -1354,7 +1354,7 @@ extension KVOObservableTests { XCTAssertTrue(latest == .two) - var rootDeallocated = false + nonisolated(unsafe) var rootDeallocated = false _ = root .rx.deallocated @@ -1372,9 +1372,9 @@ extension KVOObservableTests { func testObserve_ObserveUIntEnum() { - var root: HasStrongProperty! = HasStrongProperty() + nonisolated(unsafe) var root: HasStrongProperty! = HasStrongProperty() - var latest: UIntEnum? + nonisolated(unsafe) var latest: UIntEnum? XCTAssertTrue(latest == nil) @@ -1388,7 +1388,7 @@ extension KVOObservableTests { XCTAssertTrue(latest == .two) - var rootDeallocated = false + nonisolated(unsafe) var rootDeallocated = false _ = root .rx.deallocated @@ -1405,9 +1405,9 @@ extension KVOObservableTests { } func testObserve_ObserveUInt32Enum() { - var root: HasStrongProperty! = HasStrongProperty() + nonisolated(unsafe) var root: HasStrongProperty! = HasStrongProperty() - var latest: UInt32Enum? + nonisolated(unsafe) var latest: UInt32Enum? XCTAssertTrue(latest == nil) @@ -1421,7 +1421,7 @@ extension KVOObservableTests { XCTAssertTrue(latest == .two) - var rootDeallocated = false + nonisolated(unsafe) var rootDeallocated = false _ = root .rx.deallocated @@ -1438,9 +1438,9 @@ extension KVOObservableTests { } func testObserve_ObserveUInt64Enum() { - var root: HasStrongProperty! = HasStrongProperty() + nonisolated(unsafe) var root: HasStrongProperty! = HasStrongProperty() - var latest: UInt64Enum? + nonisolated(unsafe) var latest: UInt64Enum? XCTAssertTrue(latest == nil) @@ -1454,7 +1454,7 @@ extension KVOObservableTests { XCTAssertTrue(latest == .two) - var rootDeallocated = false + nonisolated(unsafe) var rootDeallocated = false _ = root .rx.deallocated @@ -1474,9 +1474,9 @@ extension KVOObservableTests { #if !DISABLE_SWIZZLING extension KVOObservableTests { func testObserveWeak_ObserveIntEnum() { - var root: HasStrongProperty! = HasStrongProperty() + nonisolated(unsafe) var root: HasStrongProperty! = HasStrongProperty() - var latest: IntEnum? + nonisolated(unsafe) var latest: IntEnum? XCTAssertTrue(latest == nil) @@ -1491,7 +1491,7 @@ extension KVOObservableTests { XCTAssertTrue(latest == .two) - var rootDeallocated = false + nonisolated(unsafe) var rootDeallocated = false _ = root .rx.deallocated @@ -1506,9 +1506,9 @@ extension KVOObservableTests { } func testObserveWeak_ObserveInt32Enum() { - var root: HasStrongProperty! = HasStrongProperty() + nonisolated(unsafe) var root: HasStrongProperty! = HasStrongProperty() - var latest: Int32Enum? + nonisolated(unsafe) var latest: Int32Enum? XCTAssertTrue(latest == nil) @@ -1523,7 +1523,7 @@ extension KVOObservableTests { XCTAssertTrue(latest == .two) - var rootDeallocated = false + nonisolated(unsafe) var rootDeallocated = false _ = root .rx.deallocated @@ -1538,9 +1538,9 @@ extension KVOObservableTests { } func testObserveWeak_ObserveInt64Enum() { - var root: HasStrongProperty! = HasStrongProperty() + nonisolated(unsafe) var root: HasStrongProperty! = HasStrongProperty() - var latest: Int64Enum? + nonisolated(unsafe) var latest: Int64Enum? XCTAssertTrue(latest == nil) @@ -1555,7 +1555,7 @@ extension KVOObservableTests { XCTAssertTrue(latest == .two) - var rootDeallocated = false + nonisolated(unsafe) var rootDeallocated = false _ = root .rx.deallocated @@ -1570,9 +1570,9 @@ extension KVOObservableTests { } func testObserveWeak_ObserveUIntEnum() { - var root: HasStrongProperty! = HasStrongProperty() + nonisolated(unsafe) var root: HasStrongProperty! = HasStrongProperty() - var latest: UIntEnum? + nonisolated(unsafe) var latest: UIntEnum? XCTAssertTrue(latest == nil) @@ -1587,7 +1587,7 @@ extension KVOObservableTests { XCTAssertTrue(latest == .two) - var rootDeallocated = false + nonisolated(unsafe) var rootDeallocated = false _ = root .rx.deallocated @@ -1602,9 +1602,9 @@ extension KVOObservableTests { } func testObserveWeak_ObserveUInt32Enum() { - var root: HasStrongProperty! = HasStrongProperty() + nonisolated(unsafe) var root: HasStrongProperty! = HasStrongProperty() - var latest: UInt32Enum? + nonisolated(unsafe) var latest: UInt32Enum? XCTAssertTrue(latest == nil) @@ -1619,7 +1619,7 @@ extension KVOObservableTests { XCTAssertTrue(latest == .two) - var rootDeallocated = false + nonisolated(unsafe) var rootDeallocated = false _ = root .rx.deallocated @@ -1634,9 +1634,9 @@ extension KVOObservableTests { } func testObserveWeak_ObserveUInt64Enum() { - var root: HasStrongProperty! = HasStrongProperty() + nonisolated(unsafe) var root: HasStrongProperty! = HasStrongProperty() - var latest: UInt32Enum? + nonisolated(unsafe) var latest: UInt32Enum? XCTAssertTrue(latest == nil) @@ -1651,7 +1651,7 @@ extension KVOObservableTests { XCTAssertTrue(latest == .two) - var rootDeallocated = false + nonisolated(unsafe) var rootDeallocated = false _ = root .rx.deallocated diff --git a/Tests/RxCocoaTests/RxTest+Controls.swift b/Tests/RxCocoaTests/RxTest+Controls.swift index be88ece66..5bb44e440 100644 --- a/Tests/RxCocoaTests/RxTest+Controls.swift +++ b/Tests/RxCocoaTests/RxTest+Controls.swift @@ -35,10 +35,10 @@ extension RxTest { let completeExpectation = XCTestExpectation(description: "completion") let deallocateExpectation = XCTestExpectation(description: "deallocation") - var lastReturnedPropertyValue: T? + nonisolated(unsafe) var lastReturnedPropertyValue: T? autoreleasepool { - var control: C! = createControl() + nonisolated(unsafe) var control: C! = createControl() let property = propertySelector(control) @@ -69,13 +69,13 @@ extension RxTest { ) } - func ensureEventDeallocated(_ createControl: @escaping () -> C, file: StaticString = #file, line: UInt = #line, _ eventSelector: (C) -> ControlEvent) where C: NSObject { + func ensureEventDeallocated(_ createControl: @escaping @Sendable () -> C, file: StaticString = #file, line: UInt = #line, _ eventSelector: (C) -> ControlEvent) where C: NSObject { ensureEventDeallocated({ () -> (C, Disposable) in (createControl(), Disposables.create()) }, file: file, line: line, eventSelector) } func ensureEventDeallocated(_ createControl: () -> (C, Disposable), file: StaticString = #file, line: UInt = #line, _ eventSelector: (C) -> ControlEvent) where C: NSObject { - var completed = false - var deallocated = false + nonisolated(unsafe) var completed = false + nonisolated(unsafe) var deallocated = false let outerDisposable = SingleAssignmentDisposable() autoreleasepool { @@ -101,7 +101,7 @@ extension RxTest { } func ensureControlObserverHasWeakReference(file: StaticString = #file, line: UInt = #line, _ createControl: @autoclosure() -> (C), _ observerSelector: (C) -> AnyObserver, _ observableSelector: () -> (Observable)) where C: NSObject { - var deallocated = false + nonisolated(unsafe) var deallocated = false let disposeBag = DisposeBag() diff --git a/Tests/RxCocoaTests/SentMessageTest.swift b/Tests/RxCocoaTests/SentMessageTest.swift index 430f4e23d..8a12ae0b2 100644 --- a/Tests/RxCocoaTests/SentMessageTest.swift +++ b/Tests/RxCocoaTests/SentMessageTest.swift @@ -461,7 +461,7 @@ extension SentMessageTest { < BaseClass: SentMessageTestClassCreationProtocol & NSObjectProtocol, TargetClass: SentMessageTestClassCreationProtocol & NSObjectProtocol - >(_ baseClass: BaseClass.Type, _ targetClass: TargetClass.Type, _ method: Selector, _ invoke: @escaping (BaseClass) -> [[MethodParameters]]) { + >(_ baseClass: BaseClass.Type, _ targetClass: TargetClass.Type, _ method: Selector, _ invoke: @escaping @Sendable (BaseClass) -> [[MethodParameters]]) { // now force forwarding mechanism for normal class ensureGlobalRuntimeChangesAreCached( createNormalInstance(), @@ -559,8 +559,8 @@ extension SentMessageTest { extension SentMessageTest { func testBasicForwardingCase() { let target = SentMessageTest_forwarding_basic() - var messages = [[Any]]() - var messageStage: [MessageProcessingStage] = [] + nonisolated(unsafe) var messages = [[Any]]() + nonisolated(unsafe) var messageStage: [MessageProcessingStage] = [] let d = target.rx.sentMessage(#selector(SentMessageTestBase_shared.message_allSupportedParameters(_:p2:p3:p4:p5:p6:p7:p8:p9:p10:p11:p12:p13:p14:p15:p16:))).subscribe(onNext: { n in messages.append(n) @@ -795,13 +795,13 @@ extension SentMessageTest { let target = SentMessageTest_shared() let messages = target.rx.sentMessage(#selector(SentMessageTestBase_shared.justCalledBool(toSay:))) - var stages: [MessageProcessingStage] = [] + nonisolated(unsafe) var stages: [MessageProcessingStage] = [] let kvo = target.rx.observe(NSArray.self, "messages") .subscribe(onNext: { _ in }) - var recordedMessages = [MethodParameters]() + nonisolated(unsafe) var recordedMessages = [MethodParameters]() let methodObserving = messages.subscribe(onNext: { n in stages.append(.sentMessage) recordedMessages.append(n) @@ -827,13 +827,13 @@ extension SentMessageTest { let target = SentMessageTest_shared() let messages = target.rx.methodInvoked(#selector(SentMessageTestBase_shared.justCalledBool(toSay:))) - var stages: [MessageProcessingStage] = [] + nonisolated(unsafe) var stages: [MessageProcessingStage] = [] let kvo = target.rx.observe(NSArray.self, "messages") .subscribe(onNext: { _ in }) - var recordedMessages = [MethodParameters]() + nonisolated(unsafe) var recordedMessages = [MethodParameters]() let methodObserving = messages.subscribe(onNext: { n in stages.append(.methodInvoked) recordedMessages.append(n) @@ -860,12 +860,12 @@ extension SentMessageTest { extension SentMessageTest { func testMessageSentSubjectHasPublishBehavior() { - var messages: Observable! - var recordedMessages = [MethodParameters]() - var completed = false + nonisolated(unsafe) var messages: Observable! + nonisolated(unsafe) var recordedMessages = [MethodParameters]() + nonisolated(unsafe) var completed = false let disposeBag = DisposeBag() - var stages: [MessageProcessingStage] = [] + nonisolated(unsafe) var stages: [MessageProcessingStage] = [] autoreleasepool { let target = SentMessageTest_shared() @@ -894,12 +894,12 @@ extension SentMessageTest { } func testInvokedMethodSubjectHasPublishBehavior() { - var messages: Observable! - var recordedMessages = [MethodParameters]() - var completed = false + nonisolated(unsafe) var messages: Observable! + nonisolated(unsafe) var recordedMessages = [MethodParameters]() + nonisolated(unsafe) var completed = false let disposeBag = DisposeBag() - var stages: [MessageProcessingStage] = [] + nonisolated(unsafe) var stages: [MessageProcessingStage] = [] autoreleasepool { let target = SentMessageTest_shared() @@ -928,15 +928,15 @@ extension SentMessageTest { } func testDeallocSubjectHasReplayBehavior1() { - var deallocSequence: Observable! + nonisolated(unsafe) var deallocSequence: Observable! autoreleasepool { let target = SentMessageTest_shared() deallocSequence = target.rx.sentMessage(NSSelectorFromString("dealloc")) } - var called = false - var completed = false + nonisolated(unsafe) var called = false + nonisolated(unsafe) var completed = false _ = deallocSequence.subscribe(onNext: { n in called = true }, onCompleted: { @@ -948,15 +948,15 @@ extension SentMessageTest { } func testDeallocSubjectHasReplayBehavior2() { - var deallocSequence: Observable<()>! + nonisolated(unsafe) var deallocSequence: Observable<()>! autoreleasepool { let target = SentMessageTest_shared() deallocSequence = target.rx.deallocating } - var called = false - var completed = false + nonisolated(unsafe) var called = false + nonisolated(unsafe) var completed = false _ = deallocSequence.subscribe(onNext: { n in called = true }, onCompleted: { @@ -1182,9 +1182,9 @@ extension SentMessageTest { func testObservingForAllTypes() { let object = SentMessageTest_all_supported_types() - let closure: () -> Void = { } + let closure: @Sendable () -> Void = { } - let constChar = ("you better be listening" as NSString).utf8String! + nonisolated(unsafe) let constChar = ("you better be listening" as NSString).utf8String! let largeStruct = some_insanely_large_struct(a: (0, 1, 2, 3, 4, 5, 6, 7), some_large_text: nil, next: nil) @@ -1287,7 +1287,7 @@ extension SentMessageTest { } - func _testMessageRecordedAndAllCallsAreMade(_ selector: Selector, sendMessage: @escaping (SentMessageTest_all_supported_types) -> Result, expectedResult: Result) { + func _testMessageRecordedAndAllCallsAreMade(_ selector: Selector, sendMessage: @escaping @Sendable (SentMessageTest_all_supported_types) -> Result, expectedResult: Result) { _testMessageRecordedAndAllCallsAreMade(selector, sendMessage: sendMessage, expectedResult: expectedResult) { target, selector in return ObservedSequence.sentMessage(target.rx.sentMessage(selector)) } @@ -1296,15 +1296,15 @@ extension SentMessageTest { } } - func _testMessageRecordedAndAllCallsAreMade(_ selector: Selector, sendMessage: @escaping (SentMessageTest_all_supported_types) -> Result, expectedResult: Result, methodSelector: @escaping (SentMessageTest_all_supported_types, Selector) -> ObservedSequence) { - var observedMessages = [[Any]]() - var receivedDerivedClassMessage = [[Any]]() - var receivedBaseClassMessage = [[Any]]() - var completed = false + func _testMessageRecordedAndAllCallsAreMade(_ selector: Selector, sendMessage: @escaping @Sendable (SentMessageTest_all_supported_types) -> Result, expectedResult: Result, methodSelector: @escaping @Sendable (SentMessageTest_all_supported_types, Selector) -> ObservedSequence) { + nonisolated(unsafe) var observedMessages = [[Any]]() + nonisolated(unsafe) var receivedDerivedClassMessage = [[Any]]() + nonisolated(unsafe) var receivedBaseClassMessage = [[Any]]() + nonisolated(unsafe) var completed = false - var result: Result! = nil + nonisolated(unsafe) var result: Result! = nil - var stages: [MessageProcessingStage] = [] + nonisolated(unsafe) var stages: [MessageProcessingStage] = [] let action: () -> Disposable = { () -> Disposable in let target = SentMessageTest_all_supported_types() @@ -1350,12 +1350,12 @@ extension SentMessageTest { results properly can cause serious memory leaks. */ func ensureGlobalRuntimeChangesAreCached( - _ createIt: @escaping () -> T, - observeIt: @escaping (T) -> [ObservedSequence], + _ createIt: @escaping @Sendable () -> T, + observeIt: @escaping @Sendable (T) -> [ObservedSequence], objectActingClassChange: [ObjectRuntimeChange], objectRealClassChange: [ObjectRuntimeChange], runtimeChange: RxObjCRuntimeChange, - useIt: @escaping (T) -> [[MethodParameters]] + useIt: @escaping @Sendable (T) -> [[MethodParameters]] ) { // First run normal experiment _ensureGlobalRuntimeChangesAreCached(createIt, @@ -1392,12 +1392,12 @@ extension SentMessageTest { let originalRuntimeState = RxObjCRuntimeState() - var createdObject: T! = nil - var disposables = [Disposable]() + nonisolated(unsafe) var createdObject: T! = nil + nonisolated(unsafe) var disposables = [Disposable]() - var nCompleted = 0 - var recordedParameters = [[MethodParameters]]() - var observables: [ObservedSequence] = [] + nonisolated(unsafe) var nCompleted = 0 + nonisolated(unsafe) var recordedParameters = [[MethodParameters]]() + nonisolated(unsafe) var observables: [ObservedSequence] = [] autoreleasepool { createdObject = createIt() @@ -1420,9 +1420,9 @@ extension SentMessageTest { ) afterObserveRuntimeState.assertAfterThisMoment(originalRuntimeState, changed: runtimeChange) - var messageProcessingStage: [MessageProcessingStage] = [] + nonisolated(unsafe) var messageProcessingStage: [MessageProcessingStage] = [] autoreleasepool { - var i = 0 + nonisolated(unsafe) var i = 0 for o in observables { let index = i @@ -1439,7 +1439,7 @@ extension SentMessageTest { } } - var invokedCount = 0 + nonisolated(unsafe) var invokedCount = 0 createdObject.invokedMethod = { messageProcessingStage.append(.invoking) invokedCount = invokedCount + 1 @@ -1491,7 +1491,7 @@ extension SentMessageTest { } - func createKVODynamicSubclassed(_ type: T.Type = T.self) -> () -> (T, [Disposable]) { + func createKVODynamicSubclassed(_ type: T.Type = T.self) -> @Sendable () -> (T, [Disposable]) { return { let t = T.createInstance() //let disposable = (t as! NSObject).rx.observe(NSArray.self, "messages").publish().connect() @@ -1500,7 +1500,7 @@ extension SentMessageTest { } } - func createNormalInstance(_ type: T.Type = T.self) -> () -> T { + func createNormalInstance(_ type: T.Type = T.self) -> @Sendable () -> T { return { return T.createInstance() } diff --git a/Tests/RxCocoaTests/SharedSequence+Test.swift b/Tests/RxCocoaTests/SharedSequence+Test.swift index e2406f477..217f2f2df 100644 --- a/Tests/RxCocoaTests/SharedSequence+Test.swift +++ b/Tests/RxCocoaTests/SharedSequence+Test.swift @@ -26,9 +26,9 @@ class SharedSequenceTest: RxTest { // * events are observed on main thread - observe(on:MainScheduler.instance) // * it can't error out - it needs to have catch somewhere extension SharedSequenceTest { - func subscribeTwiceOnBackgroundSchedulerAndOnlyOneSubscription(_ xs: SharedSequence, expectationFulfilled: @escaping (Result) -> Bool = { _ in false }, subscribedOnBackground: () -> Void) -> [Result] { - var firstElements = [Result]() - var secondElements = [Result]() + func subscribeTwiceOnBackgroundSchedulerAndOnlyOneSubscription(_ xs: SharedSequence, expectationFulfilled: @escaping @Sendable (Result) -> Bool = { _ in false }, subscribedOnBackground: () -> Void) -> [Result] { + nonisolated(unsafe) var firstElements = [Result]() + nonisolated(unsafe) var secondElements = [Result]() let subscribeFinished = self.expectation(description: "subscribeFinished") diff --git a/Tests/RxSwiftTests/RecursiveLockTest.swift b/Tests/RxSwiftTests/RecursiveLockTest.swift index 37061a29e..8e9ecf0a0 100644 --- a/Tests/RxSwiftTests/RecursiveLockTest.swift +++ b/Tests/RxSwiftTests/RecursiveLockTest.swift @@ -16,9 +16,9 @@ import XCTest #endif private class StrandClosure { - let closure: () -> Void + let closure: @Sendable () -> Void - init(closure: @escaping () -> Void) { + init(closure: @escaping @Sendable () -> Void) { self.closure = closure } } @@ -53,7 +53,7 @@ class RecursiveLockTests: RxTest { // code taken from https://github.com/ketzusaka/Strand/blob/master/Sources/Strand.swift - func thread(action: @escaping () -> ()) { + func thread(action: @escaping @Sendable () -> ()) { let holder = Unmanaged.passRetained(StrandClosure(closure: action)) let pointer = UnsafeMutableRawPointer(holder.toOpaque()) #if os(Linux) diff --git a/Tests/RxSwiftTests/SharingSchedulerTests.swift b/Tests/RxSwiftTests/SharingSchedulerTests.swift index ea36bfd4a..10e48a7b3 100644 --- a/Tests/RxSwiftTests/SharingSchedulerTests.swift +++ b/Tests/RxSwiftTests/SharingSchedulerTests.swift @@ -69,15 +69,15 @@ class Scheduler1: SchedulerType { fatalError() } - func schedule(_ state: StateType, action: @escaping (StateType) -> Disposable) -> Disposable { + func schedule(_ state: StateType, action: @escaping @Sendable (StateType) -> Disposable) -> Disposable { fatalError() } - func scheduleRelative(_ state: StateType, dueTime: RxTimeInterval, action: @escaping (StateType) -> Disposable) -> Disposable { + func scheduleRelative(_ state: StateType, dueTime: RxTimeInterval, action: @escaping @Sendable (StateType) -> Disposable) -> Disposable { fatalError() } - func schedulePeriodic(_ state: StateType, startAfter: RxTimeInterval, period: RxTimeInterval, action: @escaping (StateType) -> StateType) -> Disposable { + func schedulePeriodic(_ state: StateType, startAfter: RxTimeInterval, period: RxTimeInterval, action: @escaping @Sendable (StateType) -> StateType) -> Disposable { fatalError() } } @@ -87,15 +87,15 @@ class Scheduler2: SchedulerType { fatalError() } - func schedule(_ state: StateType, action: @escaping (StateType) -> Disposable) -> Disposable { + func schedule(_ state: StateType, action: @escaping @Sendable (StateType) -> Disposable) -> Disposable { fatalError() } - func scheduleRelative(_ state: StateType, dueTime: RxTimeInterval, action: @escaping (StateType) -> Disposable) -> Disposable { + func scheduleRelative(_ state: StateType, dueTime: RxTimeInterval, action: @escaping @Sendable (StateType) -> Disposable) -> Disposable { fatalError() } - func schedulePeriodic(_ state: StateType, startAfter: RxTimeInterval, period: RxTimeInterval, action: @escaping (StateType) -> StateType) -> Disposable { + func schedulePeriodic(_ state: StateType, startAfter: RxTimeInterval, period: RxTimeInterval, action: @escaping @Sendable (StateType) -> StateType) -> Disposable { fatalError() } } diff --git a/Tests/XCTest+AllTests.swift b/Tests/XCTest+AllTests.swift index cc54f5dd2..c478981aa 100644 --- a/Tests/XCTest+AllTests.swift +++ b/Tests/XCTest+AllTests.swift @@ -80,10 +80,10 @@ func XCTAssertArraysEqual(_ lhs: [T], _ rhs: [T], file: StaticString = #file, } -func doOnBackgroundQueue(_ action: @escaping () -> Void) { +func doOnBackgroundQueue(_ action: @escaping @Sendable () -> Void) { DispatchQueue.global(qos: .default).async(execute: action) } -func doOnMainQueue(_ action: @escaping () -> Void) { +func doOnMainQueue(_ action: @escaping @Sendable () -> Void) { DispatchQueue.main.async(execute: action) } From 52b40a977874532a7e7e9b73a9750d3fd0510e3c Mon Sep 17 00:00:00 2001 From: Andrei Ardelean <> Date: Wed, 23 Oct 2024 16:05:21 +0300 Subject: [PATCH 06/11] Make ObservableConvertibleType Sendable --- RxSwift/GroupedObservable.swift | 2 +- RxSwift/Observable.swift | 2 +- RxSwift/ObservableConvertibleType.swift | 2 +- RxSwift/Observables/AddRef.swift | 2 +- RxSwift/Observables/Amb.swift | 2 +- RxSwift/Observables/AsMaybe.swift | 2 +- RxSwift/Observables/AsSingle.swift | 2 +- RxSwift/Observables/Buffer.swift | 2 +- RxSwift/Observables/Catch.swift | 4 ++-- RxSwift/Observables/CombineLatest+Collection.swift | 2 +- RxSwift/Observables/CombineLatest+arity.swift | 14 +++++++------- RxSwift/Observables/CompactMap.swift | 2 +- RxSwift/Observables/Concat.swift | 2 +- RxSwift/Observables/Create.swift | 2 +- RxSwift/Observables/Debounce.swift | 2 +- RxSwift/Observables/Debug.swift | 2 +- RxSwift/Observables/DefaultIfEmpty.swift | 2 +- RxSwift/Observables/Deferred.swift | 2 +- RxSwift/Observables/Delay.swift | 2 +- RxSwift/Observables/DelaySubscription.swift | 2 +- RxSwift/Observables/Dematerialize.swift | 2 +- RxSwift/Observables/DistinctUntilChanged.swift | 2 +- RxSwift/Observables/Do.swift | 2 +- RxSwift/Observables/ElementAt.swift | 2 +- RxSwift/Observables/Empty.swift | 2 +- RxSwift/Observables/Enumerated.swift | 2 +- RxSwift/Observables/Error.swift | 2 +- RxSwift/Observables/Filter.swift | 2 +- RxSwift/Observables/First.swift | 2 +- RxSwift/Observables/Generate.swift | 2 +- RxSwift/Observables/GroupBy.swift | 4 ++-- RxSwift/Observables/Just.swift | 4 ++-- RxSwift/Observables/Map.swift | 2 +- RxSwift/Observables/Materialize.swift | 2 +- RxSwift/Observables/Merge.swift | 12 ++++++------ RxSwift/Observables/Multicast.swift | 14 ++++++++------ RxSwift/Observables/Never.swift | 2 +- RxSwift/Observables/ObserveOn.swift | 4 ++-- RxSwift/Observables/Optional.swift | 4 ++-- RxSwift/Observables/Producer.swift | 2 +- RxSwift/Observables/Range.swift | 2 +- RxSwift/Observables/Reduce.swift | 2 +- RxSwift/Observables/Repeat.swift | 2 +- RxSwift/Observables/RetryWhen.swift | 2 +- RxSwift/Observables/Sample.swift | 2 +- RxSwift/Observables/Scan.swift | 2 +- RxSwift/Observables/Sequence.swift | 2 +- RxSwift/Observables/ShareReplayScope.swift | 6 ++++-- RxSwift/Observables/SingleAsync.swift | 2 +- RxSwift/Observables/Skip.swift | 4 ++-- RxSwift/Observables/SkipUntil.swift | 2 +- RxSwift/Observables/SkipWhile.swift | 2 +- RxSwift/Observables/StartWith.swift | 2 +- RxSwift/Observables/SubscribeOn.swift | 2 +- RxSwift/Observables/Switch.swift | 4 ++-- RxSwift/Observables/SwitchIfEmpty.swift | 2 +- RxSwift/Observables/Take.swift | 4 ++-- RxSwift/Observables/TakeLast.swift | 2 +- RxSwift/Observables/TakeWithPredicate.swift | 4 ++-- RxSwift/Observables/Throttle.swift | 2 +- RxSwift/Observables/Timeout.swift | 2 +- RxSwift/Observables/Timer.swift | 2 +- RxSwift/Observables/ToArray.swift | 2 +- RxSwift/Observables/Using.swift | 2 +- RxSwift/Observables/Window.swift | 2 +- RxSwift/Observables/WithLatestFrom.swift | 2 +- RxSwift/Observables/Zip+Collection.swift | 2 +- RxSwift/Observables/Zip+arity.swift | 14 +++++++------- RxSwift/Subjects/AsyncSubject.swift | 3 ++- RxSwift/Subjects/BehaviorSubject.swift | 3 ++- RxSwift/Subjects/PublishSubject.swift | 3 ++- RxSwift/Subjects/ReplaySubject.swift | 14 ++++++++------ .../PrimitiveSequence/Completable+AndThen.swift | 2 +- 73 files changed, 119 insertions(+), 110 deletions(-) diff --git a/RxSwift/GroupedObservable.swift b/RxSwift/GroupedObservable.swift index c4ac44628..13d3c5185 100644 --- a/RxSwift/GroupedObservable.swift +++ b/RxSwift/GroupedObservable.swift @@ -36,7 +36,7 @@ /// next(Banana) /// next(Blueberry) /// ``` -public struct GroupedObservable : ObservableType { +public struct GroupedObservable : ObservableType { /// The key associated with this grouped observable sequence. /// All elements emitted by this observable share this common key. public let key: Key diff --git a/RxSwift/Observable.swift b/RxSwift/Observable.swift index 7a9221f0b..4122ff69b 100644 --- a/RxSwift/Observable.swift +++ b/RxSwift/Observable.swift @@ -12,7 +12,7 @@ public typealias RxObservable = RxSwift.Observable -public class Observable : ObservableType { +public class Observable : ObservableType, @unchecked Sendable { init() { #if TRACE_RESOURCES _ = Resources.incrementTotal() diff --git a/RxSwift/ObservableConvertibleType.swift b/RxSwift/ObservableConvertibleType.swift index 0f56a8165..b3a2df529 100644 --- a/RxSwift/ObservableConvertibleType.swift +++ b/RxSwift/ObservableConvertibleType.swift @@ -7,7 +7,7 @@ // /// Type that can be converted to observable sequence (`Observable`). -public protocol ObservableConvertibleType { +public protocol ObservableConvertibleType: Sendable { /// Type of elements in sequence. associatedtype Element diff --git a/RxSwift/Observables/AddRef.swift b/RxSwift/Observables/AddRef.swift index a96dfcb03..9e128c981 100644 --- a/RxSwift/Observables/AddRef.swift +++ b/RxSwift/Observables/AddRef.swift @@ -24,7 +24,7 @@ final class AddRefSink : Sink, ObserverType { } } -final class AddRef : Producer { +final class AddRef : Producer, @unchecked Sendable { private let source: Observable private let refCount: RefCountDisposable diff --git a/RxSwift/Observables/Amb.swift b/RxSwift/Observables/Amb.swift index 73fcda60b..eced1fb93 100644 --- a/RxSwift/Observables/Amb.swift +++ b/RxSwift/Observables/Amb.swift @@ -140,7 +140,7 @@ final private class AmbSink: Sink { } } -final private class Amb: Producer { +final private class Amb: Producer, @unchecked Sendable { fileprivate let left: Observable fileprivate let right: Observable diff --git a/RxSwift/Observables/AsMaybe.swift b/RxSwift/Observables/AsMaybe.swift index 6fa625784..7f4699ac9 100644 --- a/RxSwift/Observables/AsMaybe.swift +++ b/RxSwift/Observables/AsMaybe.swift @@ -33,7 +33,7 @@ private final class AsMaybeSink : Sink, Observ } } -final class AsMaybe: Producer { +final class AsMaybe: Producer, @unchecked Sendable { private let source: Observable init(source: Observable) { diff --git a/RxSwift/Observables/AsSingle.swift b/RxSwift/Observables/AsSingle.swift index b39932f12..43ebd12cc 100644 --- a/RxSwift/Observables/AsSingle.swift +++ b/RxSwift/Observables/AsSingle.swift @@ -36,7 +36,7 @@ private final class AsSingleSink : Sink, Obser } } -final class AsSingle: Producer { +final class AsSingle: Producer, @unchecked Sendable { private let source: Observable init(source: Observable) { diff --git a/RxSwift/Observables/Buffer.swift b/RxSwift/Observables/Buffer.swift index 61424e8bf..5d28b5e04 100644 --- a/RxSwift/Observables/Buffer.swift +++ b/RxSwift/Observables/Buffer.swift @@ -28,7 +28,7 @@ extension ObservableType { } } -final private class BufferTimeCount: Producer<[Element]> { +final private class BufferTimeCount: Producer<[Element]>, @unchecked Sendable { fileprivate let timeSpan: RxTimeInterval fileprivate let count: Int diff --git a/RxSwift/Observables/Catch.swift b/RxSwift/Observables/Catch.swift index 4d7c6fe34..4721ca621 100644 --- a/RxSwift/Observables/Catch.swift +++ b/RxSwift/Observables/Catch.swift @@ -188,7 +188,7 @@ final private class CatchSink: Sink, ObserverT } } -final private class Catch: Producer { +final private class Catch: Producer, @unchecked Sendable { typealias Handler = @Sendable (Swift.Error) throws -> Observable fileprivate let source: Observable @@ -258,7 +258,7 @@ final private class CatchSequenceSink: Producer where Sequence.Element: ObservableConvertibleType { +final private class CatchSequence: Producer, @unchecked Sendable where Sequence.Element: ObservableConvertibleType { typealias Element = Sequence.Element.Element let sources: Sequence diff --git a/RxSwift/Observables/CombineLatest+Collection.swift b/RxSwift/Observables/CombineLatest+Collection.swift index 0c828f0f3..8c5e1a1ad 100644 --- a/RxSwift/Observables/CombineLatest+Collection.swift +++ b/RxSwift/Observables/CombineLatest+Collection.swift @@ -144,7 +144,7 @@ final class CombineLatestCollectionTypeSink: Producer where Collection.Element: ObservableConvertibleType { +final class CombineLatestCollectionType: Producer, @unchecked Sendable where Collection.Element: ObservableConvertibleType { typealias ResultSelector = @Sendable ([Collection.Element.Element]) throws -> Result let sources: Collection diff --git a/RxSwift/Observables/CombineLatest+arity.swift b/RxSwift/Observables/CombineLatest+arity.swift index 1e1e3d5b9..d9fcadc06 100644 --- a/RxSwift/Observables/CombineLatest+arity.swift +++ b/RxSwift/Observables/CombineLatest+arity.swift @@ -83,7 +83,7 @@ final class CombineLatestSink2_ : CombineLatestS } } -final class CombineLatest2 : Producer { +final class CombineLatest2 : Producer, @unchecked Sendable { typealias ResultSelector = @Sendable (E1, E2) throws -> Result let source1: Observable @@ -186,7 +186,7 @@ final class CombineLatestSink3_ : CombineLat } } -final class CombineLatest3 : Producer { +final class CombineLatest3 : Producer, @unchecked Sendable { typealias ResultSelector = @Sendable (E1, E2, E3) throws -> Result let source1: Observable @@ -296,7 +296,7 @@ final class CombineLatestSink4_ : Combin } } -final class CombineLatest4 : Producer { +final class CombineLatest4 : Producer, @unchecked Sendable { typealias ResultSelector = @Sendable (E1, E2, E3, E4) throws -> Result let source1: Observable @@ -413,7 +413,7 @@ final class CombineLatestSink5_ : Co } } -final class CombineLatest5 : Producer { +final class CombineLatest5 : Producer, @unchecked Sendable { typealias ResultSelector = @Sendable (E1, E2, E3, E4, E5) throws -> Result let source1: Observable @@ -537,7 +537,7 @@ final class CombineLatestSink6_ } } -final class CombineLatest6 : Producer { +final class CombineLatest6 : Producer, @unchecked Sendable { typealias ResultSelector = @Sendable (E1, E2, E3, E4, E5, E6) throws -> Result let source1: Observable @@ -668,7 +668,7 @@ final class CombineLatestSink7_ : Producer { +final class CombineLatest7 : Producer, @unchecked Sendable { typealias ResultSelector = @Sendable (E1, E2, E3, E4, E5, E6, E7) throws -> Result let source1: Observable @@ -806,7 +806,7 @@ final class CombineLatestSink8_ : Producer { +final class CombineLatest8 : Producer, @unchecked Sendable { typealias ResultSelector = @Sendable (E1, E2, E3, E4, E5, E6, E7, E8) throws -> Result let source1: Observable diff --git a/RxSwift/Observables/CompactMap.swift b/RxSwift/Observables/CompactMap.swift index 06b8d1d33..1404cfcc9 100644 --- a/RxSwift/Observables/CompactMap.swift +++ b/RxSwift/Observables/CompactMap.swift @@ -56,7 +56,7 @@ final private class CompactMapSink: Sink: Producer { +final private class CompactMap: Producer, @unchecked Sendable { typealias Transform = @Sendable (SourceType) throws -> ResultType? private let source: Observable diff --git a/RxSwift/Observables/Concat.swift b/RxSwift/Observables/Concat.swift index b2fb1a2e5..67d16cf0d 100644 --- a/RxSwift/Observables/Concat.swift +++ b/RxSwift/Observables/Concat.swift @@ -111,7 +111,7 @@ final private class ConcatSink } } -final private class Concat: Producer where Sequence.Element: ObservableConvertibleType { +final private class Concat: Producer, @unchecked Sendable where Sequence.Element: ObservableConvertibleType { typealias Element = Sequence.Element.Element fileprivate let sources: Sequence diff --git a/RxSwift/Observables/Create.swift b/RxSwift/Observables/Create.swift index 50be8ff00..9749ebf1b 100644 --- a/RxSwift/Observables/Create.swift +++ b/RxSwift/Observables/Create.swift @@ -61,7 +61,7 @@ final private class AnonymousObservableSink: Sink: Producer { +final private class AnonymousObservable: Producer, @unchecked Sendable { typealias SubscribeHandler = @Sendable (AnyObserver) -> Disposable let subscribeHandler: SubscribeHandler diff --git a/RxSwift/Observables/Debounce.swift b/RxSwift/Observables/Debounce.swift index e9ce18f29..ef147cdee 100644 --- a/RxSwift/Observables/Debounce.swift +++ b/RxSwift/Observables/Debounce.swift @@ -102,7 +102,7 @@ final private class DebounceSink } } -final private class Debounce: Producer { +final private class Debounce: Producer, @unchecked Sendable { fileprivate let source: Observable fileprivate let dueTime: RxTimeInterval fileprivate let scheduler: SchedulerType diff --git a/RxSwift/Observables/Debug.swift b/RxSwift/Observables/Debug.swift index 762e394fc..cea505c04 100644 --- a/RxSwift/Observables/Debug.swift +++ b/RxSwift/Observables/Debug.swift @@ -71,7 +71,7 @@ final private class DebugSink: S } } -final private class Debug: Producer { +final private class Debug: Producer, @unchecked Sendable { fileprivate let identifier: String fileprivate let trimOutput: Bool private let source: Source diff --git a/RxSwift/Observables/DefaultIfEmpty.swift b/RxSwift/Observables/DefaultIfEmpty.swift index 8d133d8f8..20546d0f0 100644 --- a/RxSwift/Observables/DefaultIfEmpty.swift +++ b/RxSwift/Observables/DefaultIfEmpty.swift @@ -49,7 +49,7 @@ final private class DefaultIfEmptySink: Sink, } } -final private class DefaultIfEmpty: Producer { +final private class DefaultIfEmpty: Producer, @unchecked Sendable { private let source: Observable private let `default`: SourceType diff --git a/RxSwift/Observables/Deferred.swift b/RxSwift/Observables/Deferred.swift index f5b6f0d48..d9812d14a 100644 --- a/RxSwift/Observables/Deferred.swift +++ b/RxSwift/Observables/Deferred.swift @@ -55,7 +55,7 @@ final private class DeferredSink } } -final private class Deferred: Producer { +final private class Deferred: Producer, @unchecked Sendable { typealias Factory = @Sendable () throws -> Source let observableFactory : Factory diff --git a/RxSwift/Observables/Delay.swift b/RxSwift/Observables/Delay.swift index 5f5a90219..6aaf68d3f 100644 --- a/RxSwift/Observables/Delay.swift +++ b/RxSwift/Observables/Delay.swift @@ -156,7 +156,7 @@ final private class DelaySink } } -final private class Delay: Producer { +final private class Delay: Producer, @unchecked Sendable { private let source: Observable private let dueTime: RxTimeInterval private let scheduler: SchedulerType diff --git a/RxSwift/Observables/DelaySubscription.swift b/RxSwift/Observables/DelaySubscription.swift index 099c0ddcb..eef836bab 100644 --- a/RxSwift/Observables/DelaySubscription.swift +++ b/RxSwift/Observables/DelaySubscription.swift @@ -38,7 +38,7 @@ final private class DelaySubscriptionSink } -final private class DelaySubscription: Producer { +final private class DelaySubscription: Producer, @unchecked Sendable { private let source: Observable private let dueTime: RxTimeInterval private let scheduler: SchedulerType diff --git a/RxSwift/Observables/Dematerialize.swift b/RxSwift/Observables/Dematerialize.swift index 2ccd54620..c3256c39c 100644 --- a/RxSwift/Observables/Dematerialize.swift +++ b/RxSwift/Observables/Dematerialize.swift @@ -36,7 +36,7 @@ private final class DematerializeSink: Producer { +final private class Dematerialize: Producer, @unchecked Sendable { private let source: Observable init(source: Observable) { diff --git a/RxSwift/Observables/DistinctUntilChanged.swift b/RxSwift/Observables/DistinctUntilChanged.swift index 470073144..4046c8709 100644 --- a/RxSwift/Observables/DistinctUntilChanged.swift +++ b/RxSwift/Observables/DistinctUntilChanged.swift @@ -115,7 +115,7 @@ final private class DistinctUntilChangedSink: Sink< } } -final private class DistinctUntilChanged: Producer { +final private class DistinctUntilChanged: Producer, @unchecked Sendable { typealias KeySelector = @Sendable (Element) throws -> Key typealias EqualityComparer = @Sendable (Key, Key) throws -> Bool diff --git a/RxSwift/Observables/Do.swift b/RxSwift/Observables/Do.swift index 093511b54..c9f50d309 100644 --- a/RxSwift/Observables/Do.swift +++ b/RxSwift/Observables/Do.swift @@ -77,7 +77,7 @@ final private class DoSink: Sink, ObserverType } } -final private class Do: Producer { +final private class Do: Producer, @unchecked Sendable { typealias EventHandler = @Sendable (Event) throws -> Void typealias AfterEventHandler = @Sendable (Event) throws -> Void diff --git a/RxSwift/Observables/ElementAt.swift b/RxSwift/Observables/ElementAt.swift index 3f09c7087..da99d4f19 100644 --- a/RxSwift/Observables/ElementAt.swift +++ b/RxSwift/Observables/ElementAt.swift @@ -82,7 +82,7 @@ final private class ElementAtSink: Sink, Obser } } -final private class ElementAt: Producer { +final private class ElementAt: Producer, @unchecked Sendable { let source: Observable let throwOnEmpty: Bool let index: Int diff --git a/RxSwift/Observables/Empty.swift b/RxSwift/Observables/Empty.swift index 9ca596594..150be905f 100644 --- a/RxSwift/Observables/Empty.swift +++ b/RxSwift/Observables/Empty.swift @@ -19,7 +19,7 @@ extension ObservableType { } } -final private class EmptyProducer: Producer { +final private class EmptyProducer: Producer, @unchecked Sendable { override func subscribe(_ observer: Observer) -> Disposable where Observer.Element == Element { observer.on(.completed) return Disposables.create() diff --git a/RxSwift/Observables/Enumerated.swift b/RxSwift/Observables/Enumerated.swift index ef8a0ff02..46e001eb0 100644 --- a/RxSwift/Observables/Enumerated.swift +++ b/RxSwift/Observables/Enumerated.swift @@ -46,7 +46,7 @@ final private class EnumeratedSink: Sink: Producer<(index: Int, element: Element)> { +final private class Enumerated: Producer<(index: Int, element: Element)>, @unchecked Sendable { private let source: Observable init(source: Observable) { diff --git a/RxSwift/Observables/Error.swift b/RxSwift/Observables/Error.swift index 2e722d670..b15fa1773 100644 --- a/RxSwift/Observables/Error.swift +++ b/RxSwift/Observables/Error.swift @@ -19,7 +19,7 @@ extension ObservableType { } } -final private class ErrorProducer: Producer { +final private class ErrorProducer: Producer, @unchecked Sendable { private let error: Swift.Error init(error: Swift.Error) { diff --git a/RxSwift/Observables/Filter.swift b/RxSwift/Observables/Filter.swift index 8819d921a..4ce76e848 100644 --- a/RxSwift/Observables/Filter.swift +++ b/RxSwift/Observables/Filter.swift @@ -67,7 +67,7 @@ final private class FilterSink: Sink, Observer } } -final private class Filter: Producer { +final private class Filter: Producer, @unchecked Sendable { typealias Predicate = @Sendable (Element) throws -> Bool private let source: Observable diff --git a/RxSwift/Observables/First.swift b/RxSwift/Observables/First.swift index 001411485..0dade66c6 100644 --- a/RxSwift/Observables/First.swift +++ b/RxSwift/Observables/First.swift @@ -26,7 +26,7 @@ private final class FirstSink : Sink, } } -final class First: Producer { +final class First: Producer, @unchecked Sendable { private let source: Observable init(source: Observable) { diff --git a/RxSwift/Observables/Generate.swift b/RxSwift/Observables/Generate.swift index 23fd13cf5..6e634e742 100644 --- a/RxSwift/Observables/Generate.swift +++ b/RxSwift/Observables/Generate.swift @@ -63,7 +63,7 @@ final private class GenerateSink: Sink: Producer { +final private class Generate: Producer, @unchecked Sendable { fileprivate let initialState: Sequence fileprivate let condition: @Sendable (Sequence) throws -> Bool fileprivate let iterate: @Sendable (Sequence) throws -> Sequence diff --git a/RxSwift/Observables/GroupBy.swift b/RxSwift/Observables/GroupBy.swift index 4415d7841..6718c4f00 100644 --- a/RxSwift/Observables/GroupBy.swift +++ b/RxSwift/Observables/GroupBy.swift @@ -21,7 +21,7 @@ extension ObservableType { } } -final private class GroupedObservableImpl: Observable { +final private class GroupedObservableImpl: Observable, @unchecked Sendable { private var subject: PublishSubject private var refCount: RefCountDisposable @@ -115,7 +115,7 @@ final private class GroupBySink } } -final private class GroupBy: Producer> { +final private class GroupBy: Producer>, @unchecked Sendable { typealias KeySelector = @Sendable (Element) throws -> Key fileprivate let source: Observable diff --git a/RxSwift/Observables/Just.swift b/RxSwift/Observables/Just.swift index 93490837f..4d5073a25 100644 --- a/RxSwift/Observables/Just.swift +++ b/RxSwift/Observables/Just.swift @@ -56,7 +56,7 @@ final private class JustScheduledSink: Sink { } } -final private class JustScheduled: Producer { +final private class JustScheduled: Producer, @unchecked Sendable { fileprivate let scheduler: ImmediateSchedulerType fileprivate let element: Element @@ -72,7 +72,7 @@ final private class JustScheduled: Producer { } } -final private class Just: Producer { +final private class Just: Producer, @unchecked Sendable { private let element: Element init(element: Element) { diff --git a/RxSwift/Observables/Map.swift b/RxSwift/Observables/Map.swift index 352f17438..ede14c775 100644 --- a/RxSwift/Observables/Map.swift +++ b/RxSwift/Observables/Map.swift @@ -56,7 +56,7 @@ final private class MapSink: Sink, } } -final private class Map: Producer { +final private class Map: Producer, @unchecked Sendable { typealias Transform = @Sendable (SourceType) throws -> ResultType private let source: Observable diff --git a/RxSwift/Observables/Materialize.swift b/RxSwift/Observables/Materialize.swift index e2577be5d..7ac573d81 100644 --- a/RxSwift/Observables/Materialize.swift +++ b/RxSwift/Observables/Materialize.swift @@ -28,7 +28,7 @@ private final class MaterializeSink: Sink: Producer> { +final private class Materialize: Producer>, @unchecked Sendable { private let source: Observable init(source: Observable) { diff --git a/RxSwift/Observables/Merge.swift b/RxSwift/Observables/Merge.swift index 03b88f5f8..2484c5768 100644 --- a/RxSwift/Observables/Merge.swift +++ b/RxSwift/Observables/Merge.swift @@ -312,7 +312,7 @@ private class MergeLimitedSink: Producer { +final private class MergeLimited: Producer, @unchecked Sendable { private let source: Observable private let maxConcurrent: Int @@ -515,7 +515,7 @@ private class MergeSink: Producer { +final private class FlatMap: Producer, @unchecked Sendable { typealias Selector = @Sendable (SourceElement) throws -> SourceSequence private let source: Observable @@ -534,7 +534,7 @@ final private class FlatMap: Producer { +final private class FlatMapFirst: Producer, @unchecked Sendable { typealias Selector = @Sendable (SourceElement) throws -> SourceSequence private let source: Observable @@ -553,7 +553,7 @@ final private class FlatMapFirst: Producer { +final class ConcatMap: Producer, @unchecked Sendable { typealias Selector = @Sendable (SourceElement) throws -> SourceSequence private let source: Observable @@ -571,7 +571,7 @@ final class ConcatMap: } } -final class Merge : Producer { +final class Merge : Producer, @unchecked Sendable { private let source: Observable init(source: Observable) { @@ -585,7 +585,7 @@ final class Merge : Producer: Producer { +final private class MergeArray: Producer, @unchecked Sendable { private let sources: [Observable] init(sources: [Observable]) { diff --git a/RxSwift/Observables/Multicast.swift b/RxSwift/Observables/Multicast.swift index 6bf297594..82dda739d 100644 --- a/RxSwift/Observables/Multicast.swift +++ b/RxSwift/Observables/Multicast.swift @@ -11,7 +11,8 @@ */ public class ConnectableObservable : Observable - , ConnectableObservableType { + , ConnectableObservableType + , @unchecked Sendable { /** Connects the observable wrapper to its source. All subscribed observers will receive values from the underlying observable sequence as long as the connection is established. @@ -194,7 +195,8 @@ final private class Connection: ObserverType, Disposable { } final private class ConnectableObservableAdapter - : ConnectableObservable { + : ConnectableObservable + , @unchecked Sendable { typealias ConnectionType = Connection private let source: Observable @@ -320,7 +322,7 @@ final private class RefCountSink: Producer { +final private class RefCount: Producer, @unchecked Sendable { fileprivate let lock = RecursiveLock() // state @@ -342,8 +344,8 @@ final private class RefCount: Prod } } -final private class MulticastSink: Sink, ObserverType { - typealias Element = Observer.Element +final private class MulticastSink: Sink, ObserverType, @unchecked Sendable { + typealias Element = Observer.Element typealias ResultType = Element typealias MutlicastType = Multicast @@ -383,7 +385,7 @@ final private class MulticastSink: } } -final private class Multicast: Producer { +final private class Multicast: Producer, @unchecked Sendable { typealias SubjectSelectorType = @Sendable () throws -> Subject typealias SelectorType = @Sendable (Observable) throws -> Observable diff --git a/RxSwift/Observables/Never.swift b/RxSwift/Observables/Never.swift index 7b456eed9..f700c476a 100644 --- a/RxSwift/Observables/Never.swift +++ b/RxSwift/Observables/Never.swift @@ -20,7 +20,7 @@ extension ObservableType { } } -final private class NeverProducer: Producer { +final private class NeverProducer: Producer, @unchecked Sendable { override func subscribe(_ observer: Observer) -> Disposable where Observer.Element == Element { Disposables.create() } diff --git a/RxSwift/Observables/ObserveOn.swift b/RxSwift/Observables/ObserveOn.swift index ce43d8f59..eae0f63da 100644 --- a/RxSwift/Observables/ObserveOn.swift +++ b/RxSwift/Observables/ObserveOn.swift @@ -46,7 +46,7 @@ extension ObservableType { } } -final private class ObserveOn: Producer { +final private class ObserveOn: Producer, @unchecked Sendable { let scheduler: ImmediateSchedulerType let source: Observable @@ -215,7 +215,7 @@ final private class ObserveOnSerialDispatchQueueSink: Ob } } -final private class ObserveOnSerialDispatchQueue: Producer { +final private class ObserveOnSerialDispatchQueue: Producer, @unchecked Sendable { let scheduler: SerialDispatchQueueScheduler let source: Observable diff --git a/RxSwift/Observables/Optional.swift b/RxSwift/Observables/Optional.swift index 64f8f1fdd..85945751f 100644 --- a/RxSwift/Observables/Optional.swift +++ b/RxSwift/Observables/Optional.swift @@ -62,7 +62,7 @@ final private class ObservableOptionalScheduledSink: Sin } } -final private class ObservableOptionalScheduled: Producer { +final private class ObservableOptionalScheduled: Producer, @unchecked Sendable { fileprivate let optional: Element? fileprivate let scheduler: ImmediateSchedulerType @@ -78,7 +78,7 @@ final private class ObservableOptionalScheduled: Producer { } } -final private class ObservableOptional: Producer { +final private class ObservableOptional: Producer, @unchecked Sendable { private let optional: Element? init(optional: Element?) { diff --git a/RxSwift/Observables/Producer.swift b/RxSwift/Observables/Producer.swift index e611930a5..7ab8140f0 100644 --- a/RxSwift/Observables/Producer.swift +++ b/RxSwift/Observables/Producer.swift @@ -6,7 +6,7 @@ // Copyright © 2015 Krunoslav Zaher. All rights reserved. // -class Producer: Observable { +class Producer: Observable, @unchecked Sendable { override init() { super.init() } diff --git a/RxSwift/Observables/Range.swift b/RxSwift/Observables/Range.swift index 245353249..ff3ac3ba5 100644 --- a/RxSwift/Observables/Range.swift +++ b/RxSwift/Observables/Range.swift @@ -22,7 +22,7 @@ extension ObservableType where Element: RxAbstractInteger { } } -final private class RangeProducer: Producer { +final private class RangeProducer: Producer, @unchecked Sendable { fileprivate let start: Element fileprivate let count: Element fileprivate let scheduler: ImmediateSchedulerType diff --git a/RxSwift/Observables/Reduce.swift b/RxSwift/Observables/Reduce.swift index 947b76a34..e01a89981 100644 --- a/RxSwift/Observables/Reduce.swift +++ b/RxSwift/Observables/Reduce.swift @@ -84,7 +84,7 @@ final private class ReduceSink: Producer { +final private class Reduce: Producer, @unchecked Sendable { typealias AccumulatorType = @Sendable (AccumulateType, SourceType) throws -> AccumulateType typealias ResultSelectorType = @Sendable (AccumulateType) throws -> ResultType diff --git a/RxSwift/Observables/Repeat.swift b/RxSwift/Observables/Repeat.swift index 69a3ba02e..90b5aa351 100644 --- a/RxSwift/Observables/Repeat.swift +++ b/RxSwift/Observables/Repeat.swift @@ -21,7 +21,7 @@ extension ObservableType { } } -final private class RepeatElement: Producer { +final private class RepeatElement: Producer, @unchecked Sendable { fileprivate let element: Element fileprivate let scheduler: ImmediateSchedulerType diff --git a/RxSwift/Observables/RetryWhen.swift b/RxSwift/Observables/RetryWhen.swift index d45de12ed..5a7a774a6 100644 --- a/RxSwift/Observables/RetryWhen.swift +++ b/RxSwift/Observables/RetryWhen.swift @@ -192,7 +192,7 @@ final private class RetryWhenSequenceSink: Producer where Sequence.Element: ObservableType { +final private class RetryWhenSequence: Producer, @unchecked Sendable where Sequence.Element: ObservableType { typealias Element = Sequence.Element.Element private let sources: Sequence diff --git a/RxSwift/Observables/Sample.swift b/RxSwift/Observables/Sample.swift index 9301c9af7..62f0200fa 100644 --- a/RxSwift/Observables/Sample.swift +++ b/RxSwift/Observables/Sample.swift @@ -120,7 +120,7 @@ final private class SampleSequenceSink } -final private class Sample: Producer { +final private class Sample: Producer, @unchecked Sendable { fileprivate let source: Observable fileprivate let sampler: Observable fileprivate let defaultValue: Element? diff --git a/RxSwift/Observables/Scan.swift b/RxSwift/Observables/Scan.swift index b81f29e85..169ed1717 100644 --- a/RxSwift/Observables/Scan.swift +++ b/RxSwift/Observables/Scan.swift @@ -79,7 +79,7 @@ final private class ScanSink: Sink, O } -final private class Scan: Producer { +final private class Scan: Producer, @unchecked Sendable { typealias Accumulator = @Sendable (inout Accumulate, Element) throws -> Void private let source: Observable diff --git a/RxSwift/Observables/Sequence.swift b/RxSwift/Observables/Sequence.swift index c6d10896e..e308475eb 100644 --- a/RxSwift/Observables/Sequence.swift +++ b/RxSwift/Observables/Sequence.swift @@ -72,7 +72,7 @@ final private class ObservableSequenceSink: Producer { +final private class ObservableSequence: Producer, @unchecked Sendable { fileprivate let elements: Sequence fileprivate let scheduler: ImmediateSchedulerType diff --git a/RxSwift/Observables/ShareReplayScope.swift b/RxSwift/Observables/ShareReplayScope.swift index 59d440dc3..1839c8a95 100644 --- a/RxSwift/Observables/ShareReplayScope.swift +++ b/RxSwift/Observables/ShareReplayScope.swift @@ -255,7 +255,8 @@ private final class ShareReplay1WhileConnectedConnection // optimized version of share replay for most common case final private class ShareReplay1WhileConnected - : Observable { + : Observable + , @unchecked Sendable { fileprivate typealias Connection = ShareReplay1WhileConnectedConnection @@ -395,7 +396,8 @@ private final class ShareWhileConnectedConnection // optimized version of share replay for most common case final private class ShareWhileConnected - : Observable { + : Observable + , @unchecked Sendable { fileprivate typealias Connection = ShareWhileConnectedConnection diff --git a/RxSwift/Observables/SingleAsync.swift b/RxSwift/Observables/SingleAsync.swift index 679c8da3a..ec156547c 100644 --- a/RxSwift/Observables/SingleAsync.swift +++ b/RxSwift/Observables/SingleAsync.swift @@ -85,7 +85,7 @@ private final class SingleAsyncSink : Sink, Ob } } -final class SingleAsync: Producer { +final class SingleAsync: Producer, @unchecked Sendable { typealias Predicate = @Sendable (Element) throws -> Bool private let source: Observable diff --git a/RxSwift/Observables/Skip.swift b/RxSwift/Observables/Skip.swift index 1d7361e8a..a5f77ef42 100644 --- a/RxSwift/Observables/Skip.swift +++ b/RxSwift/Observables/Skip.swift @@ -78,7 +78,7 @@ final private class SkipCountSink: Sink, Obser } -final private class SkipCount: Producer { +final private class SkipCount: Producer, @unchecked Sendable { let source: Observable let count: Int @@ -141,7 +141,7 @@ final private class SkipTimeSink: Sink: Producer { +final private class SkipTime: Producer, @unchecked Sendable { let source: Observable let duration: RxTimeInterval let scheduler: SchedulerType diff --git a/RxSwift/Observables/SkipUntil.swift b/RxSwift/Observables/SkipUntil.swift index c8fe19340..c2f8ecdb3 100644 --- a/RxSwift/Observables/SkipUntil.swift +++ b/RxSwift/Observables/SkipUntil.swift @@ -134,7 +134,7 @@ final private class SkipUntilSink } } -final private class SkipUntil: Producer { +final private class SkipUntil: Producer, @unchecked Sendable { fileprivate let source: Observable fileprivate let other: Observable diff --git a/RxSwift/Observables/SkipWhile.swift b/RxSwift/Observables/SkipWhile.swift index 79e60c0aa..3e7fb463d 100644 --- a/RxSwift/Observables/SkipWhile.swift +++ b/RxSwift/Observables/SkipWhile.swift @@ -68,7 +68,7 @@ final private class SkipWhileSink: Sink, Obser } } -final private class SkipWhile: Producer { +final private class SkipWhile: Producer, @unchecked Sendable { typealias Predicate = @Sendable (Element) throws -> Bool private let source: Observable diff --git a/RxSwift/Observables/StartWith.swift b/RxSwift/Observables/StartWith.swift index 13fb31d33..4758c1e40 100644 --- a/RxSwift/Observables/StartWith.swift +++ b/RxSwift/Observables/StartWith.swift @@ -22,7 +22,7 @@ extension ObservableType { } } -final private class StartWith: Producer { +final private class StartWith: Producer, @unchecked Sendable { let elements: [Element] let source: Observable diff --git a/RxSwift/Observables/SubscribeOn.swift b/RxSwift/Observables/SubscribeOn.swift index e8e41d9cf..88c4c5d22 100644 --- a/RxSwift/Observables/SubscribeOn.swift +++ b/RxSwift/Observables/SubscribeOn.swift @@ -86,7 +86,7 @@ final private class SubscribeOnSink: } } -final private class SubscribeOn: Producer { +final private class SubscribeOn: Producer, @unchecked Sendable { let source: Ob let scheduler: ImmediateSchedulerType diff --git a/RxSwift/Observables/Switch.swift b/RxSwift/Observables/Switch.swift index 150cc81f9..2e8190a37 100644 --- a/RxSwift/Observables/Switch.swift +++ b/RxSwift/Observables/Switch.swift @@ -218,7 +218,7 @@ final private class MapSwitchSink: Producer { +final private class Switch: Producer, @unchecked Sendable { private let source: Observable init(source: Observable) { @@ -232,7 +232,7 @@ final private class Switch: Producer: Producer { +final private class FlatMapLatest: Producer, @unchecked Sendable { typealias Selector = @Sendable (SourceType) throws -> Source private let source: Observable diff --git a/RxSwift/Observables/SwitchIfEmpty.swift b/RxSwift/Observables/SwitchIfEmpty.swift index 037bf6970..1a779dd03 100644 --- a/RxSwift/Observables/SwitchIfEmpty.swift +++ b/RxSwift/Observables/SwitchIfEmpty.swift @@ -20,7 +20,7 @@ extension ObservableType { } } -final private class SwitchIfEmpty: Producer { +final private class SwitchIfEmpty: Producer, @unchecked Sendable { private let source: Observable private let ifEmpty: Observable diff --git a/RxSwift/Observables/Take.swift b/RxSwift/Observables/Take.swift index acf3aaebd..07c69e87f 100644 --- a/RxSwift/Observables/Take.swift +++ b/RxSwift/Observables/Take.swift @@ -101,7 +101,7 @@ final private class TakeCountSink: Sink, Obser } -final private class TakeCount: Producer { +final private class TakeCount: Producer, @unchecked Sendable { private let source: Observable fileprivate let count: Int @@ -174,7 +174,7 @@ final private class TakeTimeSink } } -final private class TakeTime: Producer { +final private class TakeTime: Producer, @unchecked Sendable { typealias TimeInterval = RxTimeInterval fileprivate let source: Observable diff --git a/RxSwift/Observables/TakeLast.swift b/RxSwift/Observables/TakeLast.swift index 91833872d..23b2b7f88 100644 --- a/RxSwift/Observables/TakeLast.swift +++ b/RxSwift/Observables/TakeLast.swift @@ -58,7 +58,7 @@ final private class TakeLastSink: Sink, Observ } } -final private class TakeLast: Producer { +final private class TakeLast: Producer, @unchecked Sendable { private let source: Observable fileprivate let count: Int diff --git a/RxSwift/Observables/TakeWithPredicate.swift b/RxSwift/Observables/TakeWithPredicate.swift index 2ef69a6d4..40a9cefe3 100644 --- a/RxSwift/Observables/TakeWithPredicate.swift +++ b/RxSwift/Observables/TakeWithPredicate.swift @@ -198,7 +198,7 @@ final private class TakeUntilSink } } -final private class TakeUntil: Producer { +final private class TakeUntil: Producer, @unchecked Sendable { fileprivate let source: Observable fileprivate let other: Observable @@ -262,7 +262,7 @@ final private class TakeUntilPredicateSink } -final private class TakeUntilPredicate: Producer { +final private class TakeUntilPredicate: Producer, @unchecked Sendable { typealias Predicate = @Sendable (Element) throws -> Bool private let source: Observable diff --git a/RxSwift/Observables/Throttle.swift b/RxSwift/Observables/Throttle.swift index b1068de85..30d5f61cd 100644 --- a/RxSwift/Observables/Throttle.swift +++ b/RxSwift/Observables/Throttle.swift @@ -139,7 +139,7 @@ final private class ThrottleSink } } -final private class Throttle: Producer { +final private class Throttle: Producer, @unchecked Sendable { fileprivate let source: Observable fileprivate let dueTime: RxTimeInterval fileprivate let latest: Bool diff --git a/RxSwift/Observables/Timeout.swift b/RxSwift/Observables/Timeout.swift index 7531eeeae..e4b6fc313 100644 --- a/RxSwift/Observables/Timeout.swift +++ b/RxSwift/Observables/Timeout.swift @@ -132,7 +132,7 @@ final private class TimeoutSink: Sink, LockOwn } -final private class Timeout: Producer { +final private class Timeout: Producer, @unchecked Sendable { fileprivate let source: Observable fileprivate let dueTime: RxTimeInterval fileprivate let other: Observable diff --git a/RxSwift/Observables/Timer.swift b/RxSwift/Observables/Timer.swift index 30bbdf67d..455f8d62d 100644 --- a/RxSwift/Observables/Timer.swift +++ b/RxSwift/Observables/Timer.swift @@ -91,7 +91,7 @@ final private class TimerOneOffSink: Sink wher } } -final private class Timer: Producer { +final private class Timer: Producer, @unchecked Sendable { fileprivate let scheduler: SchedulerType fileprivate let dueTime: RxTimeInterval fileprivate let period: RxTimeInterval? diff --git a/RxSwift/Observables/ToArray.swift b/RxSwift/Observables/ToArray.swift index 76c7370aa..2269f45a9 100644 --- a/RxSwift/Observables/ToArray.swift +++ b/RxSwift/Observables/ToArray.swift @@ -49,7 +49,7 @@ final private class ToArraySink: Sink: Producer<[SourceType]> { +final private class ToArray: Producer<[SourceType]>, @unchecked Sendable { let source: Observable init(source: Observable) { diff --git a/RxSwift/Observables/Using.swift b/RxSwift/Observables/Using.swift index 08573f3cd..e13c98360 100644 --- a/RxSwift/Observables/Using.swift +++ b/RxSwift/Observables/Using.swift @@ -66,7 +66,7 @@ final private class UsingSink: } } -final private class Using: Producer { +final private class Using: Producer, @unchecked Sendable { typealias Element = SourceType diff --git a/RxSwift/Observables/Window.swift b/RxSwift/Observables/Window.swift index c52dd3f49..065cb07fd 100644 --- a/RxSwift/Observables/Window.swift +++ b/RxSwift/Observables/Window.swift @@ -149,7 +149,7 @@ final private class WindowTimeCountSink } } -final private class WindowTimeCount: Producer> { +final private class WindowTimeCount: Producer>, @unchecked Sendable { fileprivate let timeSpan: RxTimeInterval fileprivate let count: Int fileprivate let scheduler: SchedulerType diff --git a/RxSwift/Observables/WithLatestFrom.swift b/RxSwift/Observables/WithLatestFrom.swift index b1dc4e331..30a51841f 100644 --- a/RxSwift/Observables/WithLatestFrom.swift +++ b/RxSwift/Observables/WithLatestFrom.swift @@ -130,7 +130,7 @@ final private class WithLatestFromSecond: Producer { +final private class WithLatestFrom: Producer, @unchecked Sendable { typealias ResultSelector = @Sendable (FirstType, SecondType) throws -> ResultType fileprivate let first: Observable diff --git a/RxSwift/Observables/Zip+Collection.swift b/RxSwift/Observables/Zip+Collection.swift index 9ac77316e..e93a1b282 100644 --- a/RxSwift/Observables/Zip+Collection.swift +++ b/RxSwift/Observables/Zip+Collection.swift @@ -147,7 +147,7 @@ final private class ZipCollectionTypeSink: Producer where Collection.Element: ObservableConvertibleType { +final private class ZipCollectionType: Producer, @unchecked Sendable where Collection.Element: ObservableConvertibleType { typealias ResultSelector = @Sendable ([Collection.Element.Element]) throws -> Result let sources: Collection diff --git a/RxSwift/Observables/Zip+arity.swift b/RxSwift/Observables/Zip+arity.swift index cbf52e399..de971f722 100644 --- a/RxSwift/Observables/Zip+arity.swift +++ b/RxSwift/Observables/Zip+arity.swift @@ -93,7 +93,7 @@ final class ZipSink2_ : ZipSink { } } -final class Zip2 : Producer { +final class Zip2 : Producer, @unchecked Sendable { typealias ResultSelector = @Sendable (E1, E2) throws -> Result let source1: Observable @@ -207,7 +207,7 @@ final class ZipSink3_ : ZipSink { } } -final class Zip3 : Producer { +final class Zip3 : Producer, @unchecked Sendable { typealias ResultSelector = @Sendable (E1, E2, E3) throws -> Result let source1: Observable @@ -329,7 +329,7 @@ final class ZipSink4_ : ZipSink : Producer { +final class Zip4 : Producer, @unchecked Sendable { typealias ResultSelector = @Sendable (E1, E2, E3, E4) throws -> Result let source1: Observable @@ -459,7 +459,7 @@ final class ZipSink5_ : ZipSink : Producer { +final class Zip5 : Producer, @unchecked Sendable { typealias ResultSelector = @Sendable (E1, E2, E3, E4, E5) throws -> Result let source1: Observable @@ -597,7 +597,7 @@ final class ZipSink6_ : ZipSink< } } -final class Zip6 : Producer { +final class Zip6 : Producer, @unchecked Sendable { typealias ResultSelector = @Sendable (E1, E2, E3, E4, E5, E6) throws -> Result let source1: Observable @@ -743,7 +743,7 @@ final class ZipSink7_ : ZipS } } -final class Zip7 : Producer { +final class Zip7 : Producer, @unchecked Sendable { typealias ResultSelector = @Sendable (E1, E2, E3, E4, E5, E6, E7) throws -> Result let source1: Observable @@ -897,7 +897,7 @@ final class ZipSink8_ : } } -final class Zip8 : Producer { +final class Zip8 : Producer, @unchecked Sendable { typealias ResultSelector = @Sendable (E1, E2, E3, E4, E5, E6, E7, E8) throws -> Result let source1: Observable diff --git a/RxSwift/Subjects/AsyncSubject.swift b/RxSwift/Subjects/AsyncSubject.swift index 30b012f0b..c23fa127d 100644 --- a/RxSwift/Subjects/AsyncSubject.swift +++ b/RxSwift/Subjects/AsyncSubject.swift @@ -14,7 +14,8 @@ public final class AsyncSubject : Observable , SubjectType , ObserverType - , SynchronizedUnsubscribeType { + , SynchronizedUnsubscribeType + , @unchecked Sendable { public typealias SubjectObserverType = AsyncSubject typealias Observers = AnyObserver.s diff --git a/RxSwift/Subjects/BehaviorSubject.swift b/RxSwift/Subjects/BehaviorSubject.swift index 7251f616b..ca2225b72 100644 --- a/RxSwift/Subjects/BehaviorSubject.swift +++ b/RxSwift/Subjects/BehaviorSubject.swift @@ -14,7 +14,8 @@ public final class BehaviorSubject , SubjectType , ObserverType , SynchronizedUnsubscribeType - , Cancelable { + , Cancelable + , @unchecked Sendable { public typealias SubjectObserverType = BehaviorSubject typealias Observers = AnyObserver.s diff --git a/RxSwift/Subjects/PublishSubject.swift b/RxSwift/Subjects/PublishSubject.swift index 0318486ef..74eefc590 100644 --- a/RxSwift/Subjects/PublishSubject.swift +++ b/RxSwift/Subjects/PublishSubject.swift @@ -14,7 +14,8 @@ public final class PublishSubject , SubjectType , Cancelable , ObserverType - , SynchronizedUnsubscribeType { + , SynchronizedUnsubscribeType + , @unchecked Sendable { public typealias SubjectObserverType = PublishSubject typealias Observers = AnyObserver.s diff --git a/RxSwift/Subjects/ReplaySubject.swift b/RxSwift/Subjects/ReplaySubject.swift index 2336ce78f..e45cd6d40 100644 --- a/RxSwift/Subjects/ReplaySubject.swift +++ b/RxSwift/Subjects/ReplaySubject.swift @@ -13,7 +13,8 @@ public class ReplaySubject : Observable , SubjectType , ObserverType - , Disposable { + , Disposable + , @unchecked Sendable { public typealias SubjectObserverType = ReplaySubject typealias Observers = AnyObserver.s @@ -93,7 +94,8 @@ public class ReplaySubject private class ReplayBufferBase : ReplaySubject - , SynchronizedUnsubscribeType { + , SynchronizedUnsubscribeType + , @unchecked Sendable { func trim() { rxAbstractMethod() @@ -190,7 +192,7 @@ private class ReplayBufferBase } } -private final class ReplayOne : ReplayBufferBase { +private final class ReplayOne : ReplayBufferBase, @unchecked Sendable { private var value: Element? override init() { @@ -217,7 +219,7 @@ private final class ReplayOne : ReplayBufferBase { } } -private class ReplayManyBase: ReplayBufferBase { +private class ReplayManyBase: ReplayBufferBase, @unchecked Sendable { fileprivate var queue: Queue init(queueSize: Int) { @@ -240,7 +242,7 @@ private class ReplayManyBase: ReplayBufferBase { } } -private final class ReplayMany : ReplayManyBase { +private final class ReplayMany : ReplayManyBase, @unchecked Sendable { private let bufferSize: Int init(bufferSize: Int) { @@ -256,7 +258,7 @@ private final class ReplayMany : ReplayManyBase { } } -private final class ReplayAll : ReplayManyBase { +private final class ReplayAll : ReplayManyBase, @unchecked Sendable { init() { super.init(queueSize: 0) } diff --git a/RxSwift/Traits/PrimitiveSequence/Completable+AndThen.swift b/RxSwift/Traits/PrimitiveSequence/Completable+AndThen.swift index dd1dc9723..ba8f1b149 100644 --- a/RxSwift/Traits/PrimitiveSequence/Completable+AndThen.swift +++ b/RxSwift/Traits/PrimitiveSequence/Completable+AndThen.swift @@ -60,7 +60,7 @@ extension PrimitiveSequenceType where Trait == CompletableTrait, Element == Neve } } -final private class ConcatCompletable: Producer { +final private class ConcatCompletable: Producer, @unchecked Sendable { fileprivate let completable: Observable fileprivate let second: Observable From c4d7fdf3767bbf7ab2b79abee443a739e0c04750 Mon Sep 17 00:00:00 2001 From: Andrei Ardelean <> Date: Wed, 23 Oct 2024 16:27:41 +0300 Subject: [PATCH 07/11] Make Disposable and Observers sendable --- RxSwift/Concurrency/AsyncLock.swift | 5 ++-- RxSwift/Disposable.swift | 2 +- RxSwift/Disposables/AnonymousDisposable.swift | 2 +- RxSwift/Disposables/BinaryDisposable.swift | 2 +- RxSwift/Disposables/CompositeDisposable.swift | 2 +- RxSwift/Disposables/DisposeBag.swift | 2 +- RxSwift/Disposables/DisposeBase.swift | 2 +- RxSwift/Disposables/RefCountDisposable.swift | 4 ++-- RxSwift/Disposables/ScheduledDisposable.swift | 2 +- RxSwift/Disposables/SerialDisposable.swift | 2 +- .../SingleAssignmentDisposable.swift | 2 +- .../Disposables/SubscriptionDisposable.swift | 2 +- RxSwift/GroupedObservable.swift | 2 +- RxSwift/ImmediateSchedulerType.swift | 2 +- RxSwift/Observables/AddRef.swift | 2 +- RxSwift/Observables/Amb.swift | 6 ++--- RxSwift/Observables/AsMaybe.swift | 2 +- RxSwift/Observables/AsSingle.swift | 2 +- RxSwift/Observables/Buffer.swift | 3 ++- RxSwift/Observables/Catch.swift | 5 ++-- .../CombineLatest+Collection.swift | 2 +- RxSwift/Observables/CombineLatest+arity.swift | 14 +++++------ RxSwift/Observables/CombineLatest.swift | 8 ++++--- RxSwift/Observables/CompactMap.swift | 2 +- RxSwift/Observables/Concat.swift | 5 ++-- RxSwift/Observables/Create.swift | 2 +- RxSwift/Observables/Debounce.swift | 5 ++-- RxSwift/Observables/Debug.swift | 2 +- RxSwift/Observables/DefaultIfEmpty.swift | 2 +- RxSwift/Observables/Deferred.swift | 2 +- RxSwift/Observables/Delay.swift | 5 ++-- RxSwift/Observables/DelaySubscription.swift | 5 ++-- RxSwift/Observables/Dematerialize.swift | 2 +- .../Observables/DistinctUntilChanged.swift | 2 +- RxSwift/Observables/Do.swift | 2 +- RxSwift/Observables/ElementAt.swift | 2 +- RxSwift/Observables/Enumerated.swift | 2 +- RxSwift/Observables/Filter.swift | 2 +- RxSwift/Observables/First.swift | 2 +- RxSwift/Observables/Generate.swift | 2 +- RxSwift/Observables/GroupBy.swift | 5 ++-- RxSwift/Observables/Just.swift | 2 +- RxSwift/Observables/Map.swift | 2 +- RxSwift/Observables/Materialize.swift | 2 +- RxSwift/Observables/Merge.swift | 21 +++++++++------- RxSwift/Observables/Multicast.swift | 7 +++--- RxSwift/Observables/ObserveOn.swift | 12 +++++----- RxSwift/Observables/Optional.swift | 2 +- RxSwift/Observables/Producer.swift | 2 +- RxSwift/Observables/Range.swift | 2 +- RxSwift/Observables/Reduce.swift | 2 +- RxSwift/Observables/Repeat.swift | 2 +- RxSwift/Observables/RetryWhen.swift | 5 ++-- RxSwift/Observables/Sample.swift | 5 ++-- RxSwift/Observables/Scan.swift | 2 +- RxSwift/Observables/Sequence.swift | 2 +- RxSwift/Observables/ShareReplayScope.swift | 6 +++-- RxSwift/Observables/SingleAsync.swift | 2 +- RxSwift/Observables/Sink.swift | 2 +- RxSwift/Observables/Skip.swift | 4 ++-- RxSwift/Observables/SkipUntil.swift | 5 ++-- RxSwift/Observables/SkipWhile.swift | 2 +- RxSwift/Observables/SubscribeOn.swift | 2 +- RxSwift/Observables/Switch.swift | 7 +++--- RxSwift/Observables/SwitchIfEmpty.swift | 3 ++- RxSwift/Observables/Take.swift | 5 ++-- RxSwift/Observables/TakeLast.swift | 2 +- RxSwift/Observables/TakeWithPredicate.swift | 7 +++--- RxSwift/Observables/Throttle.swift | 5 ++-- RxSwift/Observables/Timeout.swift | 2 +- RxSwift/Observables/Timer.swift | 4 ++-- RxSwift/Observables/ToArray.swift | 2 +- RxSwift/Observables/Using.swift | 2 +- RxSwift/Observables/Window.swift | 3 ++- RxSwift/Observables/WithLatestFrom.swift | 3 ++- RxSwift/Observables/Zip+Collection.swift | 5 ++-- RxSwift/Observables/Zip+arity.swift | 24 +++++++++---------- RxSwift/Observables/Zip.swift | 5 ++-- RxSwift/ObserverType.swift | 2 +- RxSwift/Observers/AnonymousObserver.swift | 2 +- RxSwift/Observers/ObserverBase.swift | 2 +- RxSwift/Observers/TailRecursiveSink.swift | 3 ++- .../ConcurrentDispatchQueueScheduler.swift | 2 +- .../Schedulers/CurrentThreadScheduler.swift | 2 +- RxSwift/Schedulers/HistoricalScheduler.swift | 2 +- .../Schedulers/Internal/ScheduledItem.swift | 3 ++- RxSwift/Schedulers/MainScheduler.swift | 2 +- .../Schedulers/OperationQueueScheduler.swift | 2 +- .../SerialDispatchQueueScheduler.swift | 2 +- RxSwift/Schedulers/VirtualTimeScheduler.swift | 6 +++-- .../Completable+AndThen.swift | 3 ++- 91 files changed, 183 insertions(+), 150 deletions(-) diff --git a/RxSwift/Concurrency/AsyncLock.swift b/RxSwift/Concurrency/AsyncLock.swift index 7821f3831..3f0b2d11b 100644 --- a/RxSwift/Concurrency/AsyncLock.swift +++ b/RxSwift/Concurrency/AsyncLock.swift @@ -19,10 +19,11 @@ That means that enqueued work could possibly be executed later on a different th final class AsyncLock : Disposable , Lock - , SynchronizedDisposeType { + , SynchronizedDisposeType + , @unchecked Sendable { typealias Action = @Sendable () -> Void - private var _lock = SpinLock() + nonisolated(unsafe) private var _lock = SpinLock() private var queue: Queue = Queue(capacity: 0) diff --git a/RxSwift/Disposable.swift b/RxSwift/Disposable.swift index b79c77a75..9e26911df 100644 --- a/RxSwift/Disposable.swift +++ b/RxSwift/Disposable.swift @@ -7,7 +7,7 @@ // /// Represents a disposable resource. -public protocol Disposable { +public protocol Disposable: Sendable { /// Dispose resource. func dispose() } diff --git a/RxSwift/Disposables/AnonymousDisposable.swift b/RxSwift/Disposables/AnonymousDisposable.swift index 2f8e79948..4f008e01b 100644 --- a/RxSwift/Disposables/AnonymousDisposable.swift +++ b/RxSwift/Disposables/AnonymousDisposable.swift @@ -9,7 +9,7 @@ /// Represents an Action-based disposable. /// /// When dispose method is called, disposal action will be dereferenced. -private final class AnonymousDisposable : DisposeBase, Cancelable { +private final class AnonymousDisposable : DisposeBase, Cancelable, @unchecked Sendable { public typealias DisposeAction = @Sendable () -> Void private let disposed = AtomicInt(0) diff --git a/RxSwift/Disposables/BinaryDisposable.swift b/RxSwift/Disposables/BinaryDisposable.swift index a3d493708..1e727e569 100644 --- a/RxSwift/Disposables/BinaryDisposable.swift +++ b/RxSwift/Disposables/BinaryDisposable.swift @@ -7,7 +7,7 @@ // /// Represents two disposable resources that are disposed together. -private final class BinaryDisposable : DisposeBase, Cancelable { +private final class BinaryDisposable : DisposeBase, Cancelable, @unchecked Sendable { private let disposed = AtomicInt(0) diff --git a/RxSwift/Disposables/CompositeDisposable.swift b/RxSwift/Disposables/CompositeDisposable.swift index bb4efe6ac..66ca6005c 100644 --- a/RxSwift/Disposables/CompositeDisposable.swift +++ b/RxSwift/Disposables/CompositeDisposable.swift @@ -7,7 +7,7 @@ // /// Represents a group of disposable resources that are disposed together. -public final class CompositeDisposable : DisposeBase, Cancelable { +public final class CompositeDisposable : DisposeBase, Cancelable, @unchecked Sendable { /// Key used to remove disposable from composite disposable public struct DisposeKey { fileprivate let key: BagKey diff --git a/RxSwift/Disposables/DisposeBag.swift b/RxSwift/Disposables/DisposeBag.swift index 1a673bcce..36eb8e8f8 100644 --- a/RxSwift/Disposables/DisposeBag.swift +++ b/RxSwift/Disposables/DisposeBag.swift @@ -27,7 +27,7 @@ or create a new one in its place. In case explicit disposal is necessary, there is also `CompositeDisposable`. */ -public final class DisposeBag: DisposeBase { +public final class DisposeBag: DisposeBase, @unchecked Sendable { private var lock = SpinLock() diff --git a/RxSwift/Disposables/DisposeBase.swift b/RxSwift/Disposables/DisposeBase.swift index 0d4b2fb7f..7102574b7 100644 --- a/RxSwift/Disposables/DisposeBase.swift +++ b/RxSwift/Disposables/DisposeBase.swift @@ -7,7 +7,7 @@ // /// Base class for all disposables. -public class DisposeBase { +public class DisposeBase: @unchecked Sendable { init() { #if TRACE_RESOURCES _ = Resources.incrementTotal() diff --git a/RxSwift/Disposables/RefCountDisposable.swift b/RxSwift/Disposables/RefCountDisposable.swift index a59f7789d..50edc9419 100644 --- a/RxSwift/Disposables/RefCountDisposable.swift +++ b/RxSwift/Disposables/RefCountDisposable.swift @@ -7,7 +7,7 @@ // /// Represents a disposable resource that only disposes its underlying disposable resource when all dependent disposable objects have been disposed. -public final class RefCountDisposable : DisposeBase, Cancelable { +public final class RefCountDisposable : DisposeBase, Cancelable, @unchecked Sendable { private var lock = SpinLock() private var disposable = nil as Disposable? private var primaryDisposed = false @@ -93,7 +93,7 @@ public final class RefCountDisposable : DisposeBase, Cancelable { } } -internal final class RefCountInnerDisposable: DisposeBase, Disposable +internal final class RefCountInnerDisposable: DisposeBase, Disposable, @unchecked Sendable { private let parent: RefCountDisposable private let isDisposed = AtomicInt(0) diff --git a/RxSwift/Disposables/ScheduledDisposable.swift b/RxSwift/Disposables/ScheduledDisposable.swift index 672391b6f..5bb072d7b 100644 --- a/RxSwift/Disposables/ScheduledDisposable.swift +++ b/RxSwift/Disposables/ScheduledDisposable.swift @@ -12,7 +12,7 @@ private let disposeScheduledDisposable: @Sendable (ScheduledDisposable) -> Dispo } /// Represents a disposable resource whose disposal invocation will be scheduled on the specified scheduler. -public final class ScheduledDisposable : Cancelable { +public final class ScheduledDisposable : Cancelable, @unchecked Sendable { public let scheduler: ImmediateSchedulerType private let disposed = AtomicInt(0) diff --git a/RxSwift/Disposables/SerialDisposable.swift b/RxSwift/Disposables/SerialDisposable.swift index ef4690d32..77d29d859 100644 --- a/RxSwift/Disposables/SerialDisposable.swift +++ b/RxSwift/Disposables/SerialDisposable.swift @@ -7,7 +7,7 @@ // /// Represents a disposable resource whose underlying disposable resource can be replaced by another disposable resource, causing automatic disposal of the previous underlying disposable resource. -public final class SerialDisposable : DisposeBase, Cancelable { +public final class SerialDisposable : DisposeBase, Cancelable, @unchecked Sendable { private var lock = SpinLock() // state diff --git a/RxSwift/Disposables/SingleAssignmentDisposable.swift b/RxSwift/Disposables/SingleAssignmentDisposable.swift index 4a5fb8662..8e49e9b56 100644 --- a/RxSwift/Disposables/SingleAssignmentDisposable.swift +++ b/RxSwift/Disposables/SingleAssignmentDisposable.swift @@ -11,7 +11,7 @@ Represents a disposable resource which only allows a single assignment of its un If an underlying disposable resource has already been set, future attempts to set the underlying disposable resource will throw an exception. */ -public final class SingleAssignmentDisposable : DisposeBase, Cancelable { +public final class SingleAssignmentDisposable : DisposeBase, Cancelable, @unchecked Sendable { private struct DisposeState: OptionSet { let rawValue: Int32 diff --git a/RxSwift/Disposables/SubscriptionDisposable.swift b/RxSwift/Disposables/SubscriptionDisposable.swift index a406c84cb..f85b6febd 100644 --- a/RxSwift/Disposables/SubscriptionDisposable.swift +++ b/RxSwift/Disposables/SubscriptionDisposable.swift @@ -6,7 +6,7 @@ // Copyright © 2015 Krunoslav Zaher. All rights reserved. // -struct SubscriptionDisposable : Disposable { +struct SubscriptionDisposable : Disposable, @unchecked Sendable { private let key: T.DisposeKey private weak var owner: T? diff --git a/RxSwift/GroupedObservable.swift b/RxSwift/GroupedObservable.swift index 13d3c5185..ae11142c8 100644 --- a/RxSwift/GroupedObservable.swift +++ b/RxSwift/GroupedObservable.swift @@ -36,7 +36,7 @@ /// next(Banana) /// next(Blueberry) /// ``` -public struct GroupedObservable : ObservableType { +public struct GroupedObservable : ObservableType, @unchecked Sendable { /// The key associated with this grouped observable sequence. /// All elements emitted by this observable share this common key. public let key: Key diff --git a/RxSwift/ImmediateSchedulerType.swift b/RxSwift/ImmediateSchedulerType.swift index 1e90aa76e..f6acb0368 100644 --- a/RxSwift/ImmediateSchedulerType.swift +++ b/RxSwift/ImmediateSchedulerType.swift @@ -7,7 +7,7 @@ // /// Represents an object that immediately schedules units of work. -public protocol ImmediateSchedulerType { +public protocol ImmediateSchedulerType: Sendable { /** Schedules an action to be executed immediately. diff --git a/RxSwift/Observables/AddRef.swift b/RxSwift/Observables/AddRef.swift index 9e128c981..a1d076579 100644 --- a/RxSwift/Observables/AddRef.swift +++ b/RxSwift/Observables/AddRef.swift @@ -6,7 +6,7 @@ // Copyright © 2015 Krunoslav Zaher. All rights reserved. // -final class AddRefSink : Sink, ObserverType { +final class AddRefSink : Sink, ObserverType, @unchecked Sendable { typealias Element = Observer.Element override init(observer: Observer, cancel: Cancelable) { diff --git a/RxSwift/Observables/Amb.swift b/RxSwift/Observables/Amb.swift index eced1fb93..78209e9be 100644 --- a/RxSwift/Observables/Amb.swift +++ b/RxSwift/Observables/Amb.swift @@ -52,8 +52,8 @@ final private class AmbObserver: ObserverType { typealias Sink = @Sendable (This, Event) -> Void private let parent: Parent - fileprivate var sink: Sink - fileprivate var cancel: Disposable + nonisolated(unsafe) fileprivate var sink: Sink + nonisolated(unsafe) fileprivate var cancel: Disposable init(parent: Parent, cancel: Disposable, sink: @escaping Sink) { #if TRACE_RESOURCES @@ -79,7 +79,7 @@ final private class AmbObserver: ObserverType { } } -final private class AmbSink: Sink { +final private class AmbSink: Sink, @unchecked Sendable { typealias Element = Observer.Element typealias Parent = Amb typealias AmbObserverType = AmbObserver diff --git a/RxSwift/Observables/AsMaybe.swift b/RxSwift/Observables/AsMaybe.swift index 7f4699ac9..4dcde701f 100644 --- a/RxSwift/Observables/AsMaybe.swift +++ b/RxSwift/Observables/AsMaybe.swift @@ -6,7 +6,7 @@ // Copyright © 2017 Krunoslav Zaher. All rights reserved. // -private final class AsMaybeSink : Sink, ObserverType { +private final class AsMaybeSink : Sink, ObserverType, @unchecked Sendable { typealias Element = Observer.Element private var element: Event? diff --git a/RxSwift/Observables/AsSingle.swift b/RxSwift/Observables/AsSingle.swift index 43ebd12cc..c22a6a694 100644 --- a/RxSwift/Observables/AsSingle.swift +++ b/RxSwift/Observables/AsSingle.swift @@ -6,7 +6,7 @@ // Copyright © 2017 Krunoslav Zaher. All rights reserved. // -private final class AsSingleSink : Sink, ObserverType { +private final class AsSingleSink : Sink, ObserverType, @unchecked Sendable { typealias Element = Observer.Element private var element: Event? diff --git a/RxSwift/Observables/Buffer.swift b/RxSwift/Observables/Buffer.swift index 5d28b5e04..8d1f4d3f9 100644 --- a/RxSwift/Observables/Buffer.swift +++ b/RxSwift/Observables/Buffer.swift @@ -53,7 +53,8 @@ final private class BufferTimeCountSink : Sink , LockOwnerType , ObserverType - , SynchronizedOnType where Observer.Element == [Element] { + , SynchronizedOnType + , @unchecked Sendable where Observer.Element == [Element] { typealias Parent = BufferTimeCount private let parent: Parent diff --git a/RxSwift/Observables/Catch.swift b/RxSwift/Observables/Catch.swift index 4721ca621..b1046c81d 100644 --- a/RxSwift/Observables/Catch.swift +++ b/RxSwift/Observables/Catch.swift @@ -145,7 +145,7 @@ final private class CatchSinkProxy: ObserverType { } } -final private class CatchSink: Sink, ObserverType { +final private class CatchSink: Sink, ObserverType, @unchecked Sendable { typealias Element = Observer.Element typealias Parent = Catch @@ -210,7 +210,8 @@ final private class Catch: Producer, @unchecked Sendable { final private class CatchSequenceSink : TailRecursiveSink - , ObserverType where Sequence.Element: ObservableConvertibleType, Sequence.Element.Element == Observer.Element { + , ObserverType + , @unchecked Sendable where Sequence.Element: ObservableConvertibleType, Sequence.Element.Element == Observer.Element { typealias Element = Observer.Element typealias Parent = CatchSequence diff --git a/RxSwift/Observables/CombineLatest+Collection.swift b/RxSwift/Observables/CombineLatest+Collection.swift index 8c5e1a1ad..b0df24a6a 100644 --- a/RxSwift/Observables/CombineLatest+Collection.swift +++ b/RxSwift/Observables/CombineLatest+Collection.swift @@ -34,7 +34,7 @@ extension ObservableType { } final class CombineLatestCollectionTypeSink - : Sink where Collection.Element: ObservableConvertibleType { + : Sink, @unchecked Sendable where Collection.Element: ObservableConvertibleType { typealias Result = Observer.Element typealias Parent = CombineLatestCollectionType typealias SourceElement = Collection.Element.Element diff --git a/RxSwift/Observables/CombineLatest+arity.swift b/RxSwift/Observables/CombineLatest+arity.swift index d9fcadc06..983827dab 100644 --- a/RxSwift/Observables/CombineLatest+arity.swift +++ b/RxSwift/Observables/CombineLatest+arity.swift @@ -48,7 +48,7 @@ extension ObservableType where Element == Any { } } -final class CombineLatestSink2_ : CombineLatestSink { +final class CombineLatestSink2_ : CombineLatestSink, @unchecked Sendable { typealias Result = Observer.Element typealias Parent = CombineLatest2 @@ -146,7 +146,7 @@ extension ObservableType where Element == Any { } } -final class CombineLatestSink3_ : CombineLatestSink { +final class CombineLatestSink3_ : CombineLatestSink, @unchecked Sendable { typealias Result = Observer.Element typealias Parent = CombineLatest3 @@ -251,7 +251,7 @@ extension ObservableType where Element == Any { } } -final class CombineLatestSink4_ : CombineLatestSink { +final class CombineLatestSink4_ : CombineLatestSink, @unchecked Sendable { typealias Result = Observer.Element typealias Parent = CombineLatest4 @@ -363,7 +363,7 @@ extension ObservableType where Element == Any { } } -final class CombineLatestSink5_ : CombineLatestSink { +final class CombineLatestSink5_ : CombineLatestSink, @unchecked Sendable { typealias Result = Observer.Element typealias Parent = CombineLatest5 @@ -482,7 +482,7 @@ extension ObservableType where Element == Any { } } -final class CombineLatestSink6_ : CombineLatestSink { +final class CombineLatestSink6_ : CombineLatestSink, @unchecked Sendable { typealias Result = Observer.Element typealias Parent = CombineLatest6 @@ -608,7 +608,7 @@ extension ObservableType where Element == Any { } } -final class CombineLatestSink7_ : CombineLatestSink { +final class CombineLatestSink7_ : CombineLatestSink, @unchecked Sendable { typealias Result = Observer.Element typealias Parent = CombineLatest7 @@ -741,7 +741,7 @@ extension ObservableType where Element == Any { } } -final class CombineLatestSink8_ : CombineLatestSink { +final class CombineLatestSink8_ : CombineLatestSink, @unchecked Sendable { typealias Result = Observer.Element typealias Parent = CombineLatest8 diff --git a/RxSwift/Observables/CombineLatest.swift b/RxSwift/Observables/CombineLatest.swift index 399688e8e..e278a8288 100644 --- a/RxSwift/Observables/CombineLatest.swift +++ b/RxSwift/Observables/CombineLatest.swift @@ -14,8 +14,9 @@ protocol CombineLatestProtocol: AnyObject { class CombineLatestSink : Sink - , CombineLatestProtocol { - typealias Element = Observer.Element + , CombineLatestProtocol + , @unchecked Sendable { + typealias Element = Observer.Element let lock = RecursiveLock() @@ -93,7 +94,8 @@ class CombineLatestSink final class CombineLatestObserver : ObserverType , LockOwnerType - , SynchronizedOnType { + , SynchronizedOnType + , @unchecked Sendable { typealias ValueSetter = @Sendable (Element) -> Void private let parent: CombineLatestProtocol diff --git a/RxSwift/Observables/CompactMap.swift b/RxSwift/Observables/CompactMap.swift index 1404cfcc9..a2bc49f3d 100644 --- a/RxSwift/Observables/CompactMap.swift +++ b/RxSwift/Observables/CompactMap.swift @@ -21,7 +21,7 @@ extension ObservableType { } } -final private class CompactMapSink: Sink, ObserverType { +final private class CompactMapSink: Sink, ObserverType, @unchecked Sendable { typealias Transform = @Sendable (SourceType) throws -> ResultType? typealias ResultType = Observer.Element diff --git a/RxSwift/Observables/Concat.swift b/RxSwift/Observables/Concat.swift index 67d16cf0d..d5e25ca09 100644 --- a/RxSwift/Observables/Concat.swift +++ b/RxSwift/Observables/Concat.swift @@ -78,8 +78,9 @@ extension ObservableType { final private class ConcatSink : TailRecursiveSink - , ObserverType where Sequence.Element: ObservableConvertibleType, Sequence.Element.Element == Observer.Element { - typealias Element = Observer.Element + , ObserverType + , @unchecked Sendable where Sequence.Element: ObservableConvertibleType, Sequence.Element.Element == Observer.Element { + typealias Element = Observer.Element override init(observer: Observer, cancel: Cancelable) { super.init(observer: observer, cancel: cancel) diff --git a/RxSwift/Observables/Create.swift b/RxSwift/Observables/Create.swift index 9749ebf1b..495f8a120 100644 --- a/RxSwift/Observables/Create.swift +++ b/RxSwift/Observables/Create.swift @@ -22,7 +22,7 @@ extension ObservableType { } } -final private class AnonymousObservableSink: Sink, ObserverType { +final private class AnonymousObservableSink: Sink, ObserverType, @unchecked Sendable { typealias Element = Observer.Element typealias Parent = AnonymousObservable diff --git a/RxSwift/Observables/Debounce.swift b/RxSwift/Observables/Debounce.swift index ef147cdee..b8a9132c8 100644 --- a/RxSwift/Observables/Debounce.swift +++ b/RxSwift/Observables/Debounce.swift @@ -29,8 +29,9 @@ final private class DebounceSink : Sink , ObserverType , LockOwnerType - , SynchronizedOnType { - typealias Element = Observer.Element + , SynchronizedOnType + , @unchecked Sendable { + typealias Element = Observer.Element typealias ParentType = Debounce private let parent: ParentType diff --git a/RxSwift/Observables/Debug.swift b/RxSwift/Observables/Debug.swift index cea505c04..10e863c5b 100644 --- a/RxSwift/Observables/Debug.swift +++ b/RxSwift/Observables/Debug.swift @@ -31,7 +31,7 @@ private func logEvent(_ identifier: String, dateFormat: DateFormatter, content: print("\(dateFormat.string(from: Date())): \(identifier) -> \(content)") } -final private class DebugSink: Sink, ObserverType where Observer.Element == Source.Element { +final private class DebugSink: Sink, ObserverType, @unchecked Sendable where Observer.Element == Source.Element { typealias Element = Observer.Element typealias Parent = Debug diff --git a/RxSwift/Observables/DefaultIfEmpty.swift b/RxSwift/Observables/DefaultIfEmpty.swift index 20546d0f0..356bdbf33 100644 --- a/RxSwift/Observables/DefaultIfEmpty.swift +++ b/RxSwift/Observables/DefaultIfEmpty.swift @@ -21,7 +21,7 @@ extension ObservableType { } } -final private class DefaultIfEmptySink: Sink, ObserverType { +final private class DefaultIfEmptySink: Sink, ObserverType, @unchecked Sendable { typealias Element = Observer.Element private let `default`: Element private var isEmpty = true diff --git a/RxSwift/Observables/Deferred.swift b/RxSwift/Observables/Deferred.swift index d9812d14a..f86100f04 100644 --- a/RxSwift/Observables/Deferred.swift +++ b/RxSwift/Observables/Deferred.swift @@ -21,7 +21,7 @@ extension ObservableType { } } -final private class DeferredSink: Sink, ObserverType where Source.Element == Observer.Element { +final private class DeferredSink: Sink, ObserverType, @unchecked Sendable where Source.Element == Observer.Element { typealias Element = Observer.Element typealias Parent = Deferred diff --git a/RxSwift/Observables/Delay.swift b/RxSwift/Observables/Delay.swift index 6aaf68d3f..f15779b17 100644 --- a/RxSwift/Observables/Delay.swift +++ b/RxSwift/Observables/Delay.swift @@ -27,8 +27,9 @@ extension ObservableType { final private class DelaySink : Sink - , ObserverType { - typealias Element = Observer.Element + , ObserverType + , @unchecked Sendable { + typealias Element = Observer.Element typealias Source = Observable typealias DisposeKey = Bag.KeyType diff --git a/RxSwift/Observables/DelaySubscription.swift b/RxSwift/Observables/DelaySubscription.swift index eef836bab..97154f46d 100644 --- a/RxSwift/Observables/DelaySubscription.swift +++ b/RxSwift/Observables/DelaySubscription.swift @@ -26,8 +26,9 @@ extension ObservableType { } final private class DelaySubscriptionSink - : Sink, ObserverType { - typealias Element = Observer.Element + : Sink, ObserverType + , @unchecked Sendable { + typealias Element = Observer.Element func on(_ event: Event) { self.forwardOn(event) diff --git a/RxSwift/Observables/Dematerialize.swift b/RxSwift/Observables/Dematerialize.swift index c3256c39c..8e05c12aa 100644 --- a/RxSwift/Observables/Dematerialize.swift +++ b/RxSwift/Observables/Dematerialize.swift @@ -18,7 +18,7 @@ extension ObservableType where Element: EventConvertible { } -private final class DematerializeSink: Sink, ObserverType where Observer.Element == T.Element { +private final class DematerializeSink: Sink, ObserverType, @unchecked Sendable where Observer.Element == T.Element { fileprivate func on(_ event: Event) { switch event { case .next(let element): diff --git a/RxSwift/Observables/DistinctUntilChanged.swift b/RxSwift/Observables/DistinctUntilChanged.swift index 4046c8709..0429fb0f6 100644 --- a/RxSwift/Observables/DistinctUntilChanged.swift +++ b/RxSwift/Observables/DistinctUntilChanged.swift @@ -75,7 +75,7 @@ extension ObservableType { } } -final private class DistinctUntilChangedSink: Sink, ObserverType { +final private class DistinctUntilChangedSink: Sink, ObserverType, @unchecked Sendable { typealias Element = Observer.Element private let parent: DistinctUntilChanged diff --git a/RxSwift/Observables/Do.swift b/RxSwift/Observables/Do.swift index c9f50d309..0069c0dd7 100644 --- a/RxSwift/Observables/Do.swift +++ b/RxSwift/Observables/Do.swift @@ -47,7 +47,7 @@ extension ObservableType { } } -final private class DoSink: Sink, ObserverType { +final private class DoSink: Sink, ObserverType, @unchecked Sendable { typealias Element = Observer.Element typealias EventHandler = @Sendable (Event) throws -> Void typealias AfterEventHandler = @Sendable (Event) throws -> Void diff --git a/RxSwift/Observables/ElementAt.swift b/RxSwift/Observables/ElementAt.swift index da99d4f19..4fd6330b8 100644 --- a/RxSwift/Observables/ElementAt.swift +++ b/RxSwift/Observables/ElementAt.swift @@ -35,7 +35,7 @@ extension ObservableType { } } -final private class ElementAtSink: Sink, ObserverType { +final private class ElementAtSink: Sink, ObserverType, @unchecked Sendable { typealias SourceType = Observer.Element typealias Parent = ElementAt diff --git a/RxSwift/Observables/Enumerated.swift b/RxSwift/Observables/Enumerated.swift index 46e001eb0..ded154f78 100644 --- a/RxSwift/Observables/Enumerated.swift +++ b/RxSwift/Observables/Enumerated.swift @@ -21,7 +21,7 @@ extension ObservableType { } } -final private class EnumeratedSink: Sink, ObserverType where Observer.Element == (index: Int, element: Element) { +final private class EnumeratedSink: Sink, ObserverType, @unchecked Sendable where Observer.Element == (index: Int, element: Element) { var index = 0 func on(_ event: Event) { diff --git a/RxSwift/Observables/Filter.swift b/RxSwift/Observables/Filter.swift index 4ce76e848..06a0bce1f 100644 --- a/RxSwift/Observables/Filter.swift +++ b/RxSwift/Observables/Filter.swift @@ -36,7 +36,7 @@ extension ObservableType { } } -final private class FilterSink: Sink, ObserverType { +final private class FilterSink: Sink, ObserverType, @unchecked Sendable { typealias Predicate = @Sendable (Element) throws -> Bool typealias Element = Observer.Element diff --git a/RxSwift/Observables/First.swift b/RxSwift/Observables/First.swift index 0dade66c6..e3242c28d 100644 --- a/RxSwift/Observables/First.swift +++ b/RxSwift/Observables/First.swift @@ -6,7 +6,7 @@ // Copyright © 2017 Krunoslav Zaher. All rights reserved. // -private final class FirstSink : Sink, ObserverType where Observer.Element == Element? { +private final class FirstSink : Sink, ObserverType, @unchecked Sendable where Observer.Element == Element? { typealias Parent = First func on(_ event: Event) { diff --git a/RxSwift/Observables/Generate.swift b/RxSwift/Observables/Generate.swift index 6e634e742..8f0f3be63 100644 --- a/RxSwift/Observables/Generate.swift +++ b/RxSwift/Observables/Generate.swift @@ -24,7 +24,7 @@ extension ObservableType { } } -final private class GenerateSink: Sink { +final private class GenerateSink: Sink, @unchecked Sendable { typealias Parent = Generate private let parent: Parent diff --git a/RxSwift/Observables/GroupBy.swift b/RxSwift/Observables/GroupBy.swift index 6718c4f00..1dec82bd4 100644 --- a/RxSwift/Observables/GroupBy.swift +++ b/RxSwift/Observables/GroupBy.swift @@ -40,8 +40,9 @@ final private class GroupedObservableImpl: Observable, @unchec final private class GroupBySink : Sink - , ObserverType where Observer.Element == GroupedObservable { - typealias ResultType = Observer.Element + , ObserverType + , @unchecked Sendable where Observer.Element == GroupedObservable { + typealias ResultType = Observer.Element typealias Parent = GroupBy private let parent: Parent diff --git a/RxSwift/Observables/Just.swift b/RxSwift/Observables/Just.swift index 4d5073a25..6a1397e42 100644 --- a/RxSwift/Observables/Just.swift +++ b/RxSwift/Observables/Just.swift @@ -33,7 +33,7 @@ extension ObservableType { } } -final private class JustScheduledSink: Sink { +final private class JustScheduledSink: Sink, @unchecked Sendable { typealias Parent = JustScheduled private let parent: Parent diff --git a/RxSwift/Observables/Map.swift b/RxSwift/Observables/Map.swift index ede14c775..c13e32e6b 100644 --- a/RxSwift/Observables/Map.swift +++ b/RxSwift/Observables/Map.swift @@ -23,7 +23,7 @@ extension ObservableType { } } -final private class MapSink: Sink, ObserverType { +final private class MapSink: Sink, ObserverType, @unchecked Sendable { typealias Transform = @Sendable (SourceType) throws -> ResultType typealias ResultType = Observer.Element diff --git a/RxSwift/Observables/Materialize.swift b/RxSwift/Observables/Materialize.swift index 7ac573d81..4b1fd82bd 100644 --- a/RxSwift/Observables/Materialize.swift +++ b/RxSwift/Observables/Materialize.swift @@ -17,7 +17,7 @@ extension ObservableType { } } -private final class MaterializeSink: Sink, ObserverType where Observer.Element == Event { +private final class MaterializeSink: Sink, ObserverType, @unchecked Sendable where Observer.Element == Event { func on(_ event: Event) { self.forwardOn(.next(event)) diff --git a/RxSwift/Observables/Merge.swift b/RxSwift/Observables/Merge.swift index 2484c5768..e5a91b3d5 100644 --- a/RxSwift/Observables/Merge.swift +++ b/RxSwift/Observables/Merge.swift @@ -139,7 +139,8 @@ extension ObservableType { private final class MergeLimitedSinkIter : ObserverType , LockOwnerType - , SynchronizedOnType where SourceSequence.Element == Observer.Element { + , SynchronizedOnType + , @unchecked Sendable where SourceSequence.Element == Observer.Element { typealias Element = Observer.Element typealias DisposeKey = CompositeDisposable.DisposeKey typealias Parent = MergeLimitedSink @@ -184,7 +185,7 @@ private final class MergeLimitedSinkIter: MergeLimitedSink where Observer.Element == SourceSequence.Element { +private final class ConcatMapSink: MergeLimitedSink, @unchecked Sendable where Observer.Element == SourceSequence.Element { typealias Selector = @Sendable (SourceElement) throws -> SourceSequence private let selector: Selector @@ -199,7 +200,7 @@ private final class ConcatMapSink: MergeLimitedSink where Observer.Element == SourceSequence.Element { +private final class MergeLimitedBasicSink: MergeLimitedSink, @unchecked Sendable where Observer.Element == SourceSequence.Element { override func performMap(_ element: SourceSequence) throws -> SourceSequence { element @@ -208,7 +209,8 @@ private final class MergeLimitedBasicSink : Sink - , ObserverType where Observer.Element == SourceSequence.Element { + , ObserverType + , @unchecked Sendable where Observer.Element == SourceSequence.Element { typealias QueueType = Queue let maxConcurrent: Int @@ -330,7 +332,7 @@ final private class MergeLimited: Pro // MARK: Merge -private final class MergeBasicSink : MergeSink where Observer.Element == Source.Element { +private final class MergeBasicSink : MergeSink, @unchecked Sendable where Observer.Element == Source.Element { override func performMap(_ element: Source) throws -> Source { element } @@ -338,7 +340,7 @@ private final class MergeBasicSink : MergeSink where Observer.Element == SourceSequence.Element { +private final class FlatMapSink : MergeSink, @unchecked Sendable where Observer.Element == SourceSequence.Element { typealias Selector = @Sendable (SourceElement) throws -> SourceSequence private let selector: Selector @@ -355,7 +357,7 @@ private final class FlatMapSink : MergeSink where Observer.Element == SourceSequence.Element { +private final class FlatMapFirstSink : MergeSink, @unchecked Sendable where Observer.Element == SourceSequence.Element { typealias Selector = @Sendable (SourceElement) throws -> SourceSequence private let selector: Selector @@ -374,7 +376,7 @@ private final class FlatMapFirstSink : ObserverType where Observer.Element == SourceSequence.Element { +private final class MergeSinkIter : ObserverType, @unchecked Sendable where Observer.Element == SourceSequence.Element { typealias Parent = MergeSink typealias DisposeKey = CompositeDisposable.DisposeKey typealias Element = Observer.Element @@ -407,7 +409,8 @@ private final class MergeSinkIter : Sink - , ObserverType where Observer.Element == SourceSequence.Element { + , ObserverType + , @unchecked Sendable where Observer.Element == SourceSequence.Element { typealias ResultType = Observer.Element typealias Element = SourceElement diff --git a/RxSwift/Observables/Multicast.swift b/RxSwift/Observables/Multicast.swift index 82dda739d..8ad07775e 100644 --- a/RxSwift/Observables/Multicast.swift +++ b/RxSwift/Observables/Multicast.swift @@ -148,7 +148,7 @@ extension ObservableType { } } -final private class Connection: ObserverType, Disposable { +final private class Connection: ObserverType, Disposable, @unchecked Sendable { typealias Element = Subject.Observer.Element private var lock: RecursiveLock @@ -247,8 +247,9 @@ final private class ConnectableObservableAdapter final private class RefCountSink : Sink - , ObserverType where ConnectableSource.Element == Observer.Element { - typealias Element = Observer.Element + , ObserverType + , @unchecked Sendable where ConnectableSource.Element == Observer.Element { + typealias Element = Observer.Element typealias Parent = RefCount private let parent: Parent diff --git a/RxSwift/Observables/ObserveOn.swift b/RxSwift/Observables/ObserveOn.swift index eae0f63da..a8e976440 100644 --- a/RxSwift/Observables/ObserveOn.swift +++ b/RxSwift/Observables/ObserveOn.swift @@ -79,17 +79,17 @@ enum ObserveOnState : Int32 { case running = 1 } -final private class ObserveOnSink: ObserverBase { +final private class ObserveOnSink: ObserverBase, @unchecked Sendable { typealias Element = Observer.Element let scheduler: ImmediateSchedulerType - var lock = SpinLock() + let lock = SpinLock() let observer: Observer // state - var state = ObserveOnState.stopped - var queue = Queue>(capacity: 10) + nonisolated(unsafe) var state = ObserveOnState.stopped + nonisolated(unsafe) var queue = Queue>(capacity: 10) let scheduleDisposable = SerialDisposable() let cancel: Cancelable @@ -177,13 +177,13 @@ final private class ObserveOnSink: ObserverBase: ObserverBase { +final private class ObserveOnSerialDispatchQueueSink: ObserverBase, @unchecked Sendable { let scheduler: SerialDispatchQueueScheduler let observer: Observer let cancel: Cancelable - var cachedScheduleLambda: (@Sendable ((sink: ObserveOnSerialDispatchQueueSink, event: Event)) -> Disposable)! + nonisolated(unsafe) var cachedScheduleLambda: (@Sendable ((sink: ObserveOnSerialDispatchQueueSink, event: Event)) -> Disposable)! init(scheduler: SerialDispatchQueueScheduler, observer: Observer, cancel: Cancelable) { self.scheduler = scheduler diff --git a/RxSwift/Observables/Optional.swift b/RxSwift/Observables/Optional.swift index 85945751f..a12e34cff 100644 --- a/RxSwift/Observables/Optional.swift +++ b/RxSwift/Observables/Optional.swift @@ -33,7 +33,7 @@ extension ObservableType { } } -final private class ObservableOptionalScheduledSink: Sink { +final private class ObservableOptionalScheduledSink: Sink, @unchecked Sendable { typealias Element = Observer.Element typealias Parent = ObservableOptionalScheduled diff --git a/RxSwift/Observables/Producer.swift b/RxSwift/Observables/Producer.swift index 7ab8140f0..0286ef952 100644 --- a/RxSwift/Observables/Producer.swift +++ b/RxSwift/Observables/Producer.swift @@ -36,7 +36,7 @@ class Producer: Observable, @unchecked Sendable { } } -private final class SinkDisposer: Cancelable { +private final class SinkDisposer: Cancelable, @unchecked Sendable { private enum DisposeState: Int32 { case disposed = 1 case sinkAndSubscriptionSet = 2 diff --git a/RxSwift/Observables/Range.swift b/RxSwift/Observables/Range.swift index ff3ac3ba5..f736ace1f 100644 --- a/RxSwift/Observables/Range.swift +++ b/RxSwift/Observables/Range.swift @@ -48,7 +48,7 @@ final private class RangeProducer: Producer } } -final private class RangeSink: Sink where Observer.Element: RxAbstractInteger { +final private class RangeSink: Sink, @unchecked Sendable where Observer.Element: RxAbstractInteger { typealias Parent = RangeProducer private let parent: Parent diff --git a/RxSwift/Observables/Reduce.swift b/RxSwift/Observables/Reduce.swift index e01a89981..016c0309f 100644 --- a/RxSwift/Observables/Reduce.swift +++ b/RxSwift/Observables/Reduce.swift @@ -42,7 +42,7 @@ extension ObservableType { } } -final private class ReduceSink: Sink, ObserverType { +final private class ReduceSink: Sink, ObserverType, @unchecked Sendable { typealias ResultType = Observer.Element typealias Parent = Reduce diff --git a/RxSwift/Observables/Repeat.swift b/RxSwift/Observables/Repeat.swift index 90b5aa351..272c739a5 100644 --- a/RxSwift/Observables/Repeat.swift +++ b/RxSwift/Observables/Repeat.swift @@ -38,7 +38,7 @@ final private class RepeatElement: Producer, @unchecked Sendab } } -final private class RepeatElementSink: Sink { +final private class RepeatElementSink: Sink, @unchecked Sendable { typealias Parent = RepeatElement private let parent: Parent diff --git a/RxSwift/Observables/RetryWhen.swift b/RxSwift/Observables/RetryWhen.swift index 5a7a774a6..4e0ef284d 100644 --- a/RxSwift/Observables/RetryWhen.swift +++ b/RxSwift/Observables/RetryWhen.swift @@ -140,8 +140,9 @@ final private class RetryWhenSequenceSinkIter - : TailRecursiveSink where Sequence.Element: ObservableType, Sequence.Element.Element == Observer.Element { - typealias Element = Observer.Element + : TailRecursiveSink + , @unchecked Sendable where Sequence.Element: ObservableType, Sequence.Element.Element == Observer.Element { + typealias Element = Observer.Element typealias Parent = RetryWhenSequence let lock = RecursiveLock() diff --git a/RxSwift/Observables/Sample.swift b/RxSwift/Observables/Sample.swift index 62f0200fa..3c8bb9b17 100644 --- a/RxSwift/Observables/Sample.swift +++ b/RxSwift/Observables/Sample.swift @@ -73,8 +73,9 @@ final private class SampleSequenceSink : Sink , ObserverType , LockOwnerType - , SynchronizedOnType { - typealias Element = Observer.Element + , SynchronizedOnType + , @unchecked Sendable { + typealias Element = Observer.Element typealias Parent = Sample fileprivate let parent: Parent diff --git a/RxSwift/Observables/Scan.swift b/RxSwift/Observables/Scan.swift index 169ed1717..3aef6782c 100644 --- a/RxSwift/Observables/Scan.swift +++ b/RxSwift/Observables/Scan.swift @@ -44,7 +44,7 @@ extension ObservableType { } } -final private class ScanSink: Sink, ObserverType { +final private class ScanSink: Sink, ObserverType, @unchecked Sendable { typealias Accumulate = Observer.Element typealias Parent = Scan diff --git a/RxSwift/Observables/Sequence.swift b/RxSwift/Observables/Sequence.swift index e308475eb..29ca51943 100644 --- a/RxSwift/Observables/Sequence.swift +++ b/RxSwift/Observables/Sequence.swift @@ -47,7 +47,7 @@ extension ObservableType { } } -final private class ObservableSequenceSink: Sink where Sequence.Element == Observer.Element { +final private class ObservableSequenceSink: Sink, @unchecked Sendable where Sequence.Element == Observer.Element { typealias Parent = ObservableSequence private let parent: Parent diff --git a/RxSwift/Observables/ShareReplayScope.swift b/RxSwift/Observables/ShareReplayScope.swift index 1839c8a95..68a2bb2e9 100644 --- a/RxSwift/Observables/ShareReplayScope.swift +++ b/RxSwift/Observables/ShareReplayScope.swift @@ -158,7 +158,8 @@ extension ObservableType { private final class ShareReplay1WhileConnectedConnection : ObserverType - , SynchronizedUnsubscribeType { + , SynchronizedUnsubscribeType + , @unchecked Sendable { typealias Observers = AnyObserver.s typealias DisposeKey = Observers.KeyType @@ -305,7 +306,8 @@ final private class ShareReplay1WhileConnected private final class ShareWhileConnectedConnection : ObserverType - , SynchronizedUnsubscribeType { + , SynchronizedUnsubscribeType + , @unchecked Sendable { typealias Observers = AnyObserver.s typealias DisposeKey = Observers.KeyType diff --git a/RxSwift/Observables/SingleAsync.swift b/RxSwift/Observables/SingleAsync.swift index ec156547c..9dc23ae6b 100644 --- a/RxSwift/Observables/SingleAsync.swift +++ b/RxSwift/Observables/SingleAsync.swift @@ -36,7 +36,7 @@ extension ObservableType { } } -private final class SingleAsyncSink : Sink, ObserverType { +private final class SingleAsyncSink : Sink, ObserverType, @unchecked Sendable { typealias Element = Observer.Element typealias Parent = SingleAsync diff --git a/RxSwift/Observables/Sink.swift b/RxSwift/Observables/Sink.swift index ed4fec01e..f04eda75b 100644 --- a/RxSwift/Observables/Sink.swift +++ b/RxSwift/Observables/Sink.swift @@ -6,7 +6,7 @@ // Copyright © 2015 Krunoslav Zaher. All rights reserved. // -class Sink: Disposable { +class Sink: Disposable, @unchecked Sendable { fileprivate let observer: Observer fileprivate let cancel: Cancelable private let disposed = AtomicInt(0) diff --git a/RxSwift/Observables/Skip.swift b/RxSwift/Observables/Skip.swift index a5f77ef42..15bb7dc98 100644 --- a/RxSwift/Observables/Skip.swift +++ b/RxSwift/Observables/Skip.swift @@ -43,7 +43,7 @@ extension ObservableType { // count version -final private class SkipCountSink: Sink, ObserverType { +final private class SkipCountSink: Sink, ObserverType, @unchecked Sendable { typealias Element = Observer.Element typealias Parent = SkipCount @@ -97,7 +97,7 @@ final private class SkipCount: Producer, @unchecked Sendable { // time version -final private class SkipTimeSink: Sink, ObserverType where Observer.Element == Element { +final private class SkipTimeSink: Sink, ObserverType, @unchecked Sendable where Observer.Element == Element { typealias Parent = SkipTime let parent: Parent diff --git a/RxSwift/Observables/SkipUntil.swift b/RxSwift/Observables/SkipUntil.swift index c2f8ecdb3..5a86f264d 100644 --- a/RxSwift/Observables/SkipUntil.swift +++ b/RxSwift/Observables/SkipUntil.swift @@ -87,8 +87,9 @@ final private class SkipUntilSink : Sink , ObserverType , LockOwnerType - , SynchronizedOnType { - typealias Element = Observer.Element + , SynchronizedOnType + , @unchecked Sendable { + typealias Element = Observer.Element typealias Parent = SkipUntil let lock = RecursiveLock() diff --git a/RxSwift/Observables/SkipWhile.swift b/RxSwift/Observables/SkipWhile.swift index 3e7fb463d..adb0b62d1 100644 --- a/RxSwift/Observables/SkipWhile.swift +++ b/RxSwift/Observables/SkipWhile.swift @@ -33,7 +33,7 @@ extension ObservableType { } } -final private class SkipWhileSink: Sink, ObserverType { +final private class SkipWhileSink: Sink, ObserverType, @unchecked Sendable { typealias Element = Observer.Element typealias Parent = SkipWhile diff --git a/RxSwift/Observables/SubscribeOn.swift b/RxSwift/Observables/SubscribeOn.swift index 88c4c5d22..9aba1146d 100644 --- a/RxSwift/Observables/SubscribeOn.swift +++ b/RxSwift/Observables/SubscribeOn.swift @@ -49,7 +49,7 @@ extension ObservableType { } } -final private class SubscribeOnSink: Sink, ObserverType where Ob.Element == Observer.Element { +final private class SubscribeOnSink: Sink, ObserverType, @unchecked Sendable where Ob.Element == Observer.Element { typealias Element = Observer.Element typealias Parent = SubscribeOn diff --git a/RxSwift/Observables/Switch.swift b/RxSwift/Observables/Switch.swift index 2e8190a37..d0097a552 100644 --- a/RxSwift/Observables/Switch.swift +++ b/RxSwift/Observables/Switch.swift @@ -62,7 +62,8 @@ extension ObservableType where Element: ObservableConvertibleType { private class SwitchSink : Sink - , ObserverType where Source.Element == Observer.Element { + , ObserverType + , @unchecked Sendable where Source.Element == Observer.Element { typealias Element = SourceType private let subscriptions: SingleAssignmentDisposable = SingleAssignmentDisposable() @@ -190,7 +191,7 @@ final private class SwitchSinkIter: SwitchSink +final private class SwitchIdentitySink: SwitchSink, @unchecked Sendable where Observer.Element == Source.Element { override init(observer: Observer, cancel: Cancelable) { super.init(observer: observer, cancel: cancel) @@ -201,7 +202,7 @@ final private class SwitchIdentitySink: SwitchSink where Observer.Element == Source.Element { +final private class MapSwitchSink: SwitchSink, @unchecked Sendable where Observer.Element == Source.Element { typealias Selector = @Sendable (SourceType) throws -> Source private let selector: Selector diff --git a/RxSwift/Observables/SwitchIfEmpty.swift b/RxSwift/Observables/SwitchIfEmpty.swift index 1a779dd03..2500f5f6a 100644 --- a/RxSwift/Observables/SwitchIfEmpty.swift +++ b/RxSwift/Observables/SwitchIfEmpty.swift @@ -41,7 +41,8 @@ final private class SwitchIfEmpty: Producer, @unchecked Sendab } final private class SwitchIfEmptySink: Sink - , ObserverType { + , ObserverType + , @unchecked Sendable { typealias Element = Observer.Element private let ifEmpty: Observable diff --git a/RxSwift/Observables/Take.swift b/RxSwift/Observables/Take.swift index 07c69e87f..784fd8973 100644 --- a/RxSwift/Observables/Take.swift +++ b/RxSwift/Observables/Take.swift @@ -62,7 +62,7 @@ extension ObservableType { // count version -final private class TakeCountSink: Sink, ObserverType { +final private class TakeCountSink: Sink, ObserverType, @unchecked Sendable { typealias Element = Observer.Element typealias Parent = TakeCount @@ -126,7 +126,8 @@ final private class TakeTimeSink : Sink , LockOwnerType , ObserverType - , SynchronizedOnType where Observer.Element == Element { + , SynchronizedOnType + , @unchecked Sendable where Observer.Element == Element { typealias Parent = TakeTime private let parent: Parent diff --git a/RxSwift/Observables/TakeLast.swift b/RxSwift/Observables/TakeLast.swift index 23b2b7f88..19dfc5d37 100644 --- a/RxSwift/Observables/TakeLast.swift +++ b/RxSwift/Observables/TakeLast.swift @@ -24,7 +24,7 @@ extension ObservableType { } } -final private class TakeLastSink: Sink, ObserverType { +final private class TakeLastSink: Sink, ObserverType, @unchecked Sendable { typealias Element = Observer.Element typealias Parent = TakeLast diff --git a/RxSwift/Observables/TakeWithPredicate.swift b/RxSwift/Observables/TakeWithPredicate.swift index 40a9cefe3..bcf294ca8 100644 --- a/RxSwift/Observables/TakeWithPredicate.swift +++ b/RxSwift/Observables/TakeWithPredicate.swift @@ -157,8 +157,9 @@ final private class TakeUntilSink : Sink , LockOwnerType , ObserverType - , SynchronizedOnType { - typealias Element = Observer.Element + , SynchronizedOnType + , @unchecked Sendable { + typealias Element = Observer.Element typealias Parent = TakeUntil private let parent: Parent @@ -217,7 +218,7 @@ final private class TakeUntil: Producer, @unchecked Sen // MARK: - TakeUntil Predicate final private class TakeUntilPredicateSink - : Sink, ObserverType { + : Sink, ObserverType, @unchecked Sendable { typealias Element = Observer.Element typealias Parent = TakeUntilPredicate diff --git a/RxSwift/Observables/Throttle.swift b/RxSwift/Observables/Throttle.swift index 30d5f61cd..fe9d6bc19 100644 --- a/RxSwift/Observables/Throttle.swift +++ b/RxSwift/Observables/Throttle.swift @@ -32,8 +32,9 @@ final private class ThrottleSink : Sink , ObserverType , LockOwnerType - , SynchronizedOnType { - typealias Element = Observer.Element + , SynchronizedOnType + , @unchecked Sendable { + typealias Element = Observer.Element typealias ParentType = Throttle private let parent: ParentType diff --git a/RxSwift/Observables/Timeout.swift b/RxSwift/Observables/Timeout.swift index e4b6fc313..8d5f0f436 100644 --- a/RxSwift/Observables/Timeout.swift +++ b/RxSwift/Observables/Timeout.swift @@ -40,7 +40,7 @@ extension ObservableType { } } -final private class TimeoutSink: Sink, LockOwnerType, ObserverType { +final private class TimeoutSink: Sink, LockOwnerType, ObserverType, @unchecked Sendable { typealias Element = Observer.Element typealias Parent = Timeout diff --git a/RxSwift/Observables/Timer.swift b/RxSwift/Observables/Timer.swift index 455f8d62d..4ebd051c5 100644 --- a/RxSwift/Observables/Timer.swift +++ b/RxSwift/Observables/Timer.swift @@ -49,7 +49,7 @@ extension ObservableType where Element: RxAbstractInteger { import Foundation -final private class TimerSink : Sink where Observer.Element : RxAbstractInteger { +final private class TimerSink : Sink, @unchecked Sendable where Observer.Element : RxAbstractInteger { typealias Parent = Timer private let parent: Parent @@ -70,7 +70,7 @@ final private class TimerSink : Sink where Obs } } -final private class TimerOneOffSink: Sink where Observer.Element: RxAbstractInteger { +final private class TimerOneOffSink: Sink, @unchecked Sendable where Observer.Element: RxAbstractInteger { typealias Parent = Timer private let parent: Parent diff --git a/RxSwift/Observables/ToArray.swift b/RxSwift/Observables/ToArray.swift index 2269f45a9..0a2ba0011 100644 --- a/RxSwift/Observables/ToArray.swift +++ b/RxSwift/Observables/ToArray.swift @@ -22,7 +22,7 @@ extension ObservableType { } } -final private class ToArraySink: Sink, ObserverType where Observer.Element == [SourceType] { +final private class ToArraySink: Sink, ObserverType, @unchecked Sendable where Observer.Element == [SourceType] { typealias Parent = ToArray let parent: Parent diff --git a/RxSwift/Observables/Using.swift b/RxSwift/Observables/Using.swift index e13c98360..8ec59fe17 100644 --- a/RxSwift/Observables/Using.swift +++ b/RxSwift/Observables/Using.swift @@ -21,7 +21,7 @@ extension ObservableType { } } -final private class UsingSink: Sink, ObserverType { +final private class UsingSink: Sink, ObserverType, @unchecked Sendable { typealias SourceType = Observer.Element typealias Parent = Using diff --git a/RxSwift/Observables/Window.swift b/RxSwift/Observables/Window.swift index 065cb07fd..d1092e121 100644 --- a/RxSwift/Observables/Window.swift +++ b/RxSwift/Observables/Window.swift @@ -30,7 +30,8 @@ final private class WindowTimeCountSink : Sink , ObserverType , LockOwnerType - , SynchronizedOnType where Observer.Element == Observable { + , SynchronizedOnType + , @unchecked Sendable where Observer.Element == Observable { typealias Parent = WindowTimeCount private let parent: Parent diff --git a/RxSwift/Observables/WithLatestFrom.swift b/RxSwift/Observables/WithLatestFrom.swift index 30a51841f..358492507 100644 --- a/RxSwift/Observables/WithLatestFrom.swift +++ b/RxSwift/Observables/WithLatestFrom.swift @@ -40,7 +40,8 @@ final private class WithLatestFromSink , ObserverType , LockOwnerType - , SynchronizedOnType { + , SynchronizedOnType + , @unchecked Sendable { typealias ResultType = Observer.Element typealias Parent = WithLatestFrom typealias Element = FirstType diff --git a/RxSwift/Observables/Zip+Collection.swift b/RxSwift/Observables/Zip+Collection.swift index e93a1b282..719d948cb 100644 --- a/RxSwift/Observables/Zip+Collection.swift +++ b/RxSwift/Observables/Zip+Collection.swift @@ -35,8 +35,9 @@ extension ObservableType { } final private class ZipCollectionTypeSink - : Sink where Collection.Element: ObservableConvertibleType { - typealias Result = Observer.Element + : Sink + , @unchecked Sendable where Collection.Element: ObservableConvertibleType { + typealias Result = Observer.Element typealias Parent = ZipCollectionType typealias SourceElement = Collection.Element.Element diff --git a/RxSwift/Observables/Zip+arity.swift b/RxSwift/Observables/Zip+arity.swift index de971f722..941e560e1 100644 --- a/RxSwift/Observables/Zip+arity.swift +++ b/RxSwift/Observables/Zip+arity.swift @@ -48,8 +48,8 @@ extension ObservableType where Element == Any { } } -final class ZipSink2_ : ZipSink { - typealias Result = Observer.Element +final class ZipSink2_ : ZipSink, @unchecked Sendable { + typealias Result = Observer.Element typealias Parent = Zip2 let parent: Parent @@ -156,8 +156,8 @@ extension ObservableType where Element == Any { } } -final class ZipSink3_ : ZipSink { - typealias Result = Observer.Element +final class ZipSink3_ : ZipSink, @unchecked Sendable { + typealias Result = Observer.Element typealias Parent = Zip3 let parent: Parent @@ -272,7 +272,7 @@ extension ObservableType where Element == Any { } } -final class ZipSink4_ : ZipSink { +final class ZipSink4_ : ZipSink, @unchecked Sendable { typealias Result = Observer.Element typealias Parent = Zip4 @@ -396,8 +396,8 @@ extension ObservableType where Element == Any { } } -final class ZipSink5_ : ZipSink { - typealias Result = Observer.Element +final class ZipSink5_ : ZipSink, @unchecked Sendable { + typealias Result = Observer.Element typealias Parent = Zip5 let parent: Parent @@ -528,8 +528,8 @@ extension ObservableType where Element == Any { } } -final class ZipSink6_ : ZipSink { - typealias Result = Observer.Element +final class ZipSink6_ : ZipSink, @unchecked Sendable { + typealias Result = Observer.Element typealias Parent = Zip6 let parent: Parent @@ -668,8 +668,8 @@ extension ObservableType where Element == Any { } } -final class ZipSink7_ : ZipSink { - typealias Result = Observer.Element +final class ZipSink7_ : ZipSink, @unchecked Sendable { + typealias Result = Observer.Element typealias Parent = Zip7 let parent: Parent @@ -816,7 +816,7 @@ extension ObservableType where Element == Any { } } -final class ZipSink8_ : ZipSink { +final class ZipSink8_ : ZipSink, @unchecked Sendable { typealias Result = Observer.Element typealias Parent = Zip8 diff --git a/RxSwift/Observables/Zip.swift b/RxSwift/Observables/Zip.swift index cb198651c..300e4fc42 100644 --- a/RxSwift/Observables/Zip.swift +++ b/RxSwift/Observables/Zip.swift @@ -12,7 +12,7 @@ protocol ZipSinkProtocol: AnyObject { func done(_ index: Int) } -class ZipSink : Sink, ZipSinkProtocol { +class ZipSink : Sink, ZipSinkProtocol, @unchecked Sendable { typealias Element = Observer.Element let arity: Int @@ -84,7 +84,8 @@ class ZipSink : Sink, ZipSinkProtocol { final class ZipObserver : ObserverType , LockOwnerType - , SynchronizedOnType { + , SynchronizedOnType + , @unchecked Sendable { typealias ValueSetter = @Sendable (Element) -> Void private var parent: ZipSinkProtocol? diff --git a/RxSwift/ObserverType.swift b/RxSwift/ObserverType.swift index db2db2a27..e6817dc2f 100644 --- a/RxSwift/ObserverType.swift +++ b/RxSwift/ObserverType.swift @@ -7,7 +7,7 @@ // /// Supports push-style iteration over an observable sequence. -public protocol ObserverType { +public protocol ObserverType: Sendable { /// The type of elements in sequence that observer can observe. associatedtype Element diff --git a/RxSwift/Observers/AnonymousObserver.swift b/RxSwift/Observers/AnonymousObserver.swift index 72892a63e..4851207b7 100644 --- a/RxSwift/Observers/AnonymousObserver.swift +++ b/RxSwift/Observers/AnonymousObserver.swift @@ -6,7 +6,7 @@ // Copyright © 2015 Krunoslav Zaher. All rights reserved. // -final class AnonymousObserver: ObserverBase { +final class AnonymousObserver: ObserverBase, @unchecked Sendable { typealias EventHandler = @Sendable (Event) -> Void private let eventHandler : EventHandler diff --git a/RxSwift/Observers/ObserverBase.swift b/RxSwift/Observers/ObserverBase.swift index 48e09868b..625f2e859 100644 --- a/RxSwift/Observers/ObserverBase.swift +++ b/RxSwift/Observers/ObserverBase.swift @@ -6,7 +6,7 @@ // Copyright © 2015 Krunoslav Zaher. All rights reserved. // -class ObserverBase : Disposable, ObserverType { +class ObserverBase : Disposable, ObserverType, @unchecked Sendable { private let isStopped = AtomicInt(0) func on(_ event: Event) { diff --git a/RxSwift/Observers/TailRecursiveSink.swift b/RxSwift/Observers/TailRecursiveSink.swift index fd527001d..7f01ffcf2 100644 --- a/RxSwift/Observers/TailRecursiveSink.swift +++ b/RxSwift/Observers/TailRecursiveSink.swift @@ -18,7 +18,8 @@ enum TailRecursiveSinkCommand { /// This class is usually used with `Generator` version of the operators. class TailRecursiveSink : Sink - , InvocableWithValueType where Sequence.Element: ObservableConvertibleType, Sequence.Element.Element == Observer.Element { + , InvocableWithValueType + , @unchecked Sendable where Sequence.Element: ObservableConvertibleType, Sequence.Element.Element == Observer.Element { typealias Value = TailRecursiveSinkCommand typealias Element = Observer.Element typealias SequenceGenerator = (generator: Sequence.Iterator, remaining: IntMax?) diff --git a/RxSwift/Schedulers/ConcurrentDispatchQueueScheduler.swift b/RxSwift/Schedulers/ConcurrentDispatchQueueScheduler.swift index ac2cde22f..51fc07432 100644 --- a/RxSwift/Schedulers/ConcurrentDispatchQueueScheduler.swift +++ b/RxSwift/Schedulers/ConcurrentDispatchQueueScheduler.swift @@ -12,7 +12,7 @@ import Foundation /// Abstracts the work that needs to be performed on a specific `dispatch_queue_t`. You can also pass a serial dispatch queue, it shouldn't cause any problems. /// /// This scheduler is suitable when some work needs to be performed in background. -public class ConcurrentDispatchQueueScheduler: SchedulerType { +public class ConcurrentDispatchQueueScheduler: SchedulerType, @unchecked Sendable { public typealias TimeInterval = Foundation.TimeInterval public typealias Time = Date diff --git a/RxSwift/Schedulers/CurrentThreadScheduler.swift b/RxSwift/Schedulers/CurrentThreadScheduler.swift index 98b2adad8..d80dc9725 100644 --- a/RxSwift/Schedulers/CurrentThreadScheduler.swift +++ b/RxSwift/Schedulers/CurrentThreadScheduler.swift @@ -35,7 +35,7 @@ import Foundation /// This is the default scheduler for operators that generate elements. /// /// This scheduler is also sometimes called `trampoline scheduler`. -public class CurrentThreadScheduler : ImmediateSchedulerType { +public class CurrentThreadScheduler : ImmediateSchedulerType, @unchecked Sendable { typealias ScheduleQueue = RxMutableBox> /// The singleton instance of the current thread scheduler. diff --git a/RxSwift/Schedulers/HistoricalScheduler.swift b/RxSwift/Schedulers/HistoricalScheduler.swift index 254a3e83c..204b2f3a2 100644 --- a/RxSwift/Schedulers/HistoricalScheduler.swift +++ b/RxSwift/Schedulers/HistoricalScheduler.swift @@ -9,7 +9,7 @@ import Foundation /// Provides a virtual time scheduler that uses `Date` for absolute time and `TimeInterval` for relative time. -public class HistoricalScheduler : VirtualTimeScheduler { +public class HistoricalScheduler : VirtualTimeScheduler, @unchecked Sendable { /** Creates a new historical scheduler with initial clock value. diff --git a/RxSwift/Schedulers/Internal/ScheduledItem.swift b/RxSwift/Schedulers/Internal/ScheduledItem.swift index a1de958d9..f4724bf27 100644 --- a/RxSwift/Schedulers/Internal/ScheduledItem.swift +++ b/RxSwift/Schedulers/Internal/ScheduledItem.swift @@ -8,7 +8,8 @@ struct ScheduledItem : ScheduledItemType - , InvocableType { + , InvocableType + , @unchecked Sendable { typealias Action = @Sendable (T) -> Disposable private let action: Action diff --git a/RxSwift/Schedulers/MainScheduler.swift b/RxSwift/Schedulers/MainScheduler.swift index 4aa8736c9..4ac402409 100644 --- a/RxSwift/Schedulers/MainScheduler.swift +++ b/RxSwift/Schedulers/MainScheduler.swift @@ -21,7 +21,7 @@ Main scheduler is a specialization of `SerialDispatchQueueScheduler`. This scheduler is optimized for `observeOn` operator. To ensure observable sequence is subscribed on main thread using `subscribeOn` operator please use `ConcurrentMainScheduler` because it is more optimized for that purpose. */ -public final class MainScheduler : SerialDispatchQueueScheduler { +public final class MainScheduler : SerialDispatchQueueScheduler, @unchecked Sendable { private let mainQueue: DispatchQueue diff --git a/RxSwift/Schedulers/OperationQueueScheduler.swift b/RxSwift/Schedulers/OperationQueueScheduler.swift index cef2b82d2..c2984c929 100644 --- a/RxSwift/Schedulers/OperationQueueScheduler.swift +++ b/RxSwift/Schedulers/OperationQueueScheduler.swift @@ -12,7 +12,7 @@ import Foundation /// Abstracts the work that needs to be performed on a specific `NSOperationQueue`. /// /// This scheduler is suitable for cases when there is some bigger chunk of work that needs to be performed in background and you want to fine tune concurrent processing using `maxConcurrentOperationCount`. -public class OperationQueueScheduler: ImmediateSchedulerType { +public class OperationQueueScheduler: ImmediateSchedulerType, @unchecked Sendable { public let operationQueue: OperationQueue public let queuePriority: Operation.QueuePriority diff --git a/RxSwift/Schedulers/SerialDispatchQueueScheduler.swift b/RxSwift/Schedulers/SerialDispatchQueueScheduler.swift index a6586f0a0..65225d6e0 100644 --- a/RxSwift/Schedulers/SerialDispatchQueueScheduler.swift +++ b/RxSwift/Schedulers/SerialDispatchQueueScheduler.swift @@ -26,7 +26,7 @@ In case some customization need to be made on it before usage, internal serial queue can be customized using `serialQueueConfiguration` callback. */ -public class SerialDispatchQueueScheduler : SchedulerType { +public class SerialDispatchQueueScheduler : SchedulerType, @unchecked Sendable { public typealias TimeInterval = Foundation.TimeInterval public typealias Time = Date diff --git a/RxSwift/Schedulers/VirtualTimeScheduler.swift b/RxSwift/Schedulers/VirtualTimeScheduler.swift index 0af5d340f..8adc163c1 100644 --- a/RxSwift/Schedulers/VirtualTimeScheduler.swift +++ b/RxSwift/Schedulers/VirtualTimeScheduler.swift @@ -10,7 +10,8 @@ import Foundation /// Base class for virtual time schedulers using a priority queue for scheduled items. open class VirtualTimeScheduler - : SchedulerType { + : SchedulerType + , @unchecked Sendable { public typealias VirtualTime = Converter.VirtualTimeUnit public typealias VirtualTimeInterval = Converter.VirtualTimeIntervalUnit @@ -233,7 +234,8 @@ extension VirtualTimeScheduler: CustomDebugStringConvertible { } final class VirtualSchedulerItem