Why can't actors call their own instance methods within their initializers?

A common problem I've encountered when working with actors is when the actor has stored properties that I want to setup synchronously within its initializer. I want to use an instance method to perform some or all of this setup work, but I can't, since actor-isolated instance method can't be referenced from a non-isolated context.

Here is a very simplified code example of what I think my options are:

ActorA is my ideal setup, but it's an error:

actor ActorA {
  var count = 0

  init() {
    // Actor-isolated instance method 'setup()' can not be referenced from a non-isolated context
    setup()
  }

  private func setup() {
    count = 1
  }
}

ActorB shares setup(), but then it has to spawn a Task inside init():

actor ActorB {
  var count = 0

  init() {
    Task {
      await setup()
    }
  }

  private func setup() {
    count = 1
  }
}

ActorC works, but it now has an async init()

actor ActorC {
  var count = 0

  init() async {
    setup()
  }

  private func setup() {
    count = 1
  }
}

ActorD works, but it duplicates the logic in setup()

actor ActorD {
  var count = 0

  init() {
    count = 1
  }

  private func setup() {
    count = 1
  }
}

Is there any option I'm missing here?

Can you mark setup() as private nonisolated ?

Nope, then setup() can't mutate the stored properties like count

1 Like

I wish there was a way to indicate that a function can only be called from within an initializer allowing that function to do initialization type tasks.