Isolated Closure Question

Consider an example like this:

import Combine

let publisher = [1, 2, 3, 4, 5, 6, 7, 3, 5, 6, 7, 8]
    .publisher
    .receive(on: DispatchQueue.main)
    .eraseToAnyPublisher()

public actor MyActor {
    var count: Int = 0
    
    private var subscriptions = Set<AnyCancellable>()
    
    func countThrees() {
        observe(number: 3) { myActor in
            myActor.count = myActor.count + 1
        }
    }
    
    func observe(number: Int, action: @escaping (isolated MyActor) -> Void) {
        publisher
            .filter { $0 == number }
            .sink { _ in action(self) }
            .store(in: &subscriptions)
    }
}

The code seems to work and I can test it like so:

    func testIsolatedClosure() async throws {
        let a = MyActor()
        await a.countThrees()
        try await Task.sleep(nanoseconds: 1_000_000_000)
        let count = await a.count
        XCTAssertEqual(count, 2)
    }

But I am confused how it works here:

.sink { _ in action(self) }

How does the sink function know that it needs to call back on the actor isolation? I would think I would need to do something like this to get it to work:

           .sink { _ in
                Task {
                    await action(self)
                }
            }

But that gives me the warning:

No 'async' operations occur within 'await' expression

Although your setup is somewhat different, I think it might be the same question as:

1 Like

It does look to be the same question, thank you for pointing that out.