The problem is the use of a `nonisolated` function to initiate an asynchronous update of an actor-isolated property. (I'm surprised the compiler even permits that.) Not only is it misleading, but actors also feature [reentrancy][1], and you introduce all sorts of unintended races.

However, you can add an actor-isolated function to `Limiter`:

```swift
func submit(task: @escaping () async -> Void) {
    switch policy {
    case .throttle: throttle(task: task)
    case .debounce: debounce(task: task)
    }
}
```

Note, I am not using `callAsFunction` as an actor-isolated function as it looks like (in Xcode 13.2.1, for me, at least) that this causes a segmentation fault in the compiler.

Anyway, you can then modify your tests to use the `submit` actor-isolated function, e.g.:

```swift
// test throttling as user enters “hello, world” into a text field

func testThrottler() async throws {
    // Given
    let promise = expectation(description: "Ensure first task fired")
    let throttler = Limiter(policy: .throttle, duration: 1)

    var fulfillmentCount = 0
    promise.expectedFulfillmentCount = 2
    var value = ""

    func accumulateAndSendToServer(_ input: String) async {
        value += input

        await throttler.submit { [value] in
            // Then
            switch fulfillmentCount {
            case 0:  XCTAssertEqual(value, "h")
            case 1:  XCTAssertEqual(value, "hello,")
            default: XCTFail()
            }

            promise.fulfill()
            fulfillmentCount += 1
        }
    }

    // When
    await accumulateAndSendToServer("h")
    await accumulateAndSendToServer("e")
    await accumulateAndSendToServer("l")
    await accumulateAndSendToServer("l")
    await accumulateAndSendToServer("o")

    try await Task.sleep(seconds: 2)

    await accumulateAndSendToServer(",")
    await accumulateAndSendToServer(" ")
    await accumulateAndSendToServer("w")
    await accumulateAndSendToServer("o")
    await accumulateAndSendToServer("r")
    await accumulateAndSendToServer("l")
    await accumulateAndSendToServer("d")

    wait(for: [promise], timeout: 10)
}
```

As an aside:

 1. In `debounce`, the test for `isCancelled` is redundant. The `Task.sleep` will throw an error if the task was canceled.

 2. As a matter of convention, Apple uses `operation` for the name of the closure parameters, presumably to avoid confusion with `Task` instances.

 3. I would change the `Task` to be a `Task<Void, Error>?`. Then you can simplify `debounce` to:

    ```swift
    func debounce(operation: @escaping () async -> Void) {
        task?.cancel()

        task = Task {
            defer { task = nil }
            try await Task.sleep(seconds: duration)
            await operation()
        }
    }
    ```

 4. When throttling network requests for user input, you generally want to throttle the network requests, but not the accumulation of the user input. So I have pulled the `value += input` out of the throttler/debouncer. I also use a capture list of `[value]` to make sure that we avoid race conditions between the accumulation of user input and the network requests.

- - -

FWIW, this is my rendition of `Limiter`:

```swift
actor Limiter {
    private let policy: Policy
    private let duration: TimeInterval
    private var task: Task<Void, Error>?

    init(policy: Policy, duration: TimeInterval) {
        self.policy = policy
        self.duration = duration
    }

    func submit(operation: @escaping () async -> Void) {
        switch policy {
        case .throttle: throttle(operation: operation)
        case .debounce: debounce(operation: operation)
        }
    }
}

// MARK: - Limiter.Policy

extension Limiter {
    enum Policy {
        case throttle
        case debounce
    }
}

// MARK: - Private utility methods

private extension Limiter {
    func throttle(operation: @escaping () async -> Void) {
        guard task == nil else { return }

        task = Task {
            defer { task = nil }
            try await Task.sleep(seconds: duration)
        }

        Task {
            await operation()
        }
    }

    func debounce(operation: @escaping () async -> Void) {
        task?.cancel()

        task = Task {
            defer { task = nil }
            try await Task.sleep(seconds: duration)
            await operation()
        }
    }
}
```

Which uses these extensions

```swift
// MARK: - Task.sleep(seconds:)

extension Task where Success == Never, Failure == Never {

    /// Suspends the current task for at least the given duration
    /// in seconds.
    ///
    /// If the task is canceled before the time ends,
    /// this function throws `CancellationError`.
    ///
    /// This function doesn't block the underlying thread.
    public static func sleep(seconds duration: TimeInterval) async throws {
        try await Task.sleep(nanoseconds: UInt64(duration * .nanosecondsPerSecond))
    }
}

// MARK: - TimeInterval

extension TimeInterval {
    static let nanosecondsPerSecond = TimeInterval(NSEC_PER_SEC)
}
```

And the following tests:

```swift
final class LimiterTests: XCTestCase {

    // test throttling as user enters “hello, world” into a text field

    func testThrottler() async throws {
        // Given
        let promise = expectation(description: "Ensure first task fired")
        let throttler = Limiter(policy: .throttle, duration: 1)

        var fulfillmentCount = 0
        promise.expectedFulfillmentCount = 2
        var value = ""

        func accumulateAndSendToServer(_ input: String) async {
            value += input

            await throttler.submit { [value] in
                // Then
                switch fulfillmentCount {
                case 0:  XCTAssertEqual(value, "h")
                case 1:  XCTAssertEqual(value, "hello,")
                default: XCTFail()
                }

                promise.fulfill()
                fulfillmentCount += 1
            }
        }

        // When
        await accumulateAndSendToServer("h")
        await accumulateAndSendToServer("e")
        await accumulateAndSendToServer("l")
        await accumulateAndSendToServer("l")
        await accumulateAndSendToServer("o")

        try await Task.sleep(seconds: 2)

        await accumulateAndSendToServer(",")
        await accumulateAndSendToServer(" ")
        await accumulateAndSendToServer("w")
        await accumulateAndSendToServer("o")
        await accumulateAndSendToServer("r")
        await accumulateAndSendToServer("l")
        await accumulateAndSendToServer("d")

        wait(for: [promise], timeout: 10)
    }

    // test debouncing as user enters “hello, world” into a text field

    func testDebouncer() async throws {
        // Given
        let promise = expectation(description: "Ensure last task fired")
        let debouncer = Limiter(policy: .debounce, duration: 1)
        var value = ""

        var fulfillmentCount = 0
        promise.expectedFulfillmentCount = 2

        func accumulateAndSendToServer(_ input: String) async {
            value += input

            await debouncer.submit { [value] in
                // Then
                switch fulfillmentCount {
                case 0:  XCTAssertEqual(value, "hello")
                case 1:  XCTAssertEqual(value, "hello, world")
                default: XCTFail()
                }

                promise.fulfill()
                fulfillmentCount += 1
            }
        }

        // When
        await accumulateAndSendToServer("h")
        await accumulateAndSendToServer("e")
        await accumulateAndSendToServer("l")
        await accumulateAndSendToServer("l")
        await accumulateAndSendToServer("o")

        try await Task.sleep(seconds: 2)

        await accumulateAndSendToServer(",")
        await accumulateAndSendToServer(" ")
        await accumulateAndSendToServer("w")
        await accumulateAndSendToServer("o")
        await accumulateAndSendToServer("r")
        await accumulateAndSendToServer("l")
        await accumulateAndSendToServer("d")

        wait(for: [promise], timeout: 10)
    }

    func testThrottler2() async throws {
        // Given
        let promise = expectation(description: "Ensure throttle before duration")
        let throttler = Limiter(policy: .throttle, duration: 1)

        var end = Date.now + 1
        promise.expectedFulfillmentCount = 2

        func test() {
            // Then
            XCTAssertLessThanOrEqual(.now, end)
            promise.fulfill()
        }

        // When
        await throttler.submit(operation: test)
        await throttler.submit(operation: test)
        await throttler.submit(operation: test)
        await throttler.submit(operation: test)
        await throttler.submit(operation: test)

        try await Task.sleep(seconds: 2)
        end = .now + 1

        await throttler.submit(operation: test)
        await throttler.submit(operation: test)
        await throttler.submit(operation: test)

        try await Task.sleep(seconds: 2)

        wait(for: [promise], timeout: 10)
    }

    func testDebouncer2() async throws {
        // Given
        let promise = expectation(description: "Ensure debounce after duration")
        let debouncer = Limiter(policy: .debounce, duration: 1)

        var end = Date.now + 1
        promise.expectedFulfillmentCount = 2

        func test() {
            // Then
            XCTAssertGreaterThanOrEqual(.now, end)
            promise.fulfill()
        }

        // When
        await debouncer.submit(operation: test)
        await debouncer.submit(operation: test)
        await debouncer.submit(operation: test)
        await debouncer.submit(operation: test)
        await debouncer.submit(operation: test)

        try await Task.sleep(seconds: 2)
        end = .now + 1

        await debouncer.submit(operation: test)
        await debouncer.submit(operation: test)
        await debouncer.submit(operation: test)

        try await Task.sleep(seconds: 2)

        wait(for: [promise], timeout: 10)
    }
}
```

- - - 

You might consider using [`debounce`][2] and [`throttle`][3] from Apple’s [Swift Async Algorithms][4] library. 

  [1]: https://github.com/apple/swift-evolution/blob/main/proposals/0306-actors.md#actor-reentrancy
  [2]: https://github.com/apple/swift-async-algorithms/blob/main/Sources/AsyncAlgorithms/AsyncAlgorithms.docc/Guides/Debounce.md
  [3]: https://github.com/apple/swift-async-algorithms/blob/main/Sources/AsyncAlgorithms/AsyncAlgorithms.docc/Guides/Throttle.md
  [4]: https://github.com/apple/swift-async-algorithms