Why isn't Task/await required when accessing a custom @globalActor here?

@globalActor public actor Log: GlobalActor {
  public static let shared = Log()

  let logger = Logger()
}

struct Logger: Sendable {
  func log(_ message: String) {
    print(message)
  }
}

@MainActor
class Foo {
  func bar() {
    Log.shared.logger.log("Test")
  }
}

I would expect to have to call Log.shared.logger.log("Test") inside a Task, since I'm accessing my GlobalActor from the main thread, so it's a different concurrency context. Instead, I get no warnings or errors and it all just works. I have Strict Concurrency Checking set to Complete. What am I misunderstanding?

Hi @dangwu, this is happening because Logger is Sendable and is held as a let in Log. Here is a simple example to show this principle:

actor Count {
  let value = 0
}
func f() {
  let count = Count()
  _ = count.value  // No 'await'
}

There is no reason to isolate count.value since its immutable and sendable, and so Swift does not force you to await it.

3 Likes

D'oh, makes perfect sense. Thank you @mbrandonw!

1 Like