Static class property vs. global actor

The following behavior seems inconsistent or incomplete to me. Suppose we have a static reference-type property, where the type is associated with an actor isolation context. To make this concrete, here are 3 similar possibilities:

@MainActor class Assignee {
    static var currentAssignee: Assignee?
    var name: String
    …
}
class AssigneeToo {
    static var currentAssignee: Assignee?
    @MainActor var name: String
    …
}
actor AssigneeTri {
    static var currentAssignee: Assignee?
    var name: String
    …
}

In all 3 cases, access to the type's mutable instance state (e.g. name property) is isolated. Now consider the static property, and let's try some non-isolated accesses from somewhere else:

print(String(describing: Assignee.currentAssignee))
// ^^ Static property 'currentAssignee' isolated to global actor 'MainActor'
//    can not be referenced from this synchronous context
print(String(describing: AssigneeToo.currentAssignee))
print(String(describing: AssigneeTri.currentAssignee))

The 2nd and 3rd examples are fine, because the currentAssignee property is non-isolated by default. The error message on the first example is also correct, because the property is isolated.

The problem is that there's apparently no way to declare the static property nonisolated in type Assignee. It has defaulted to isolated because of the class-level @MainActor annotation.

However, the examples with AssigneeToo and AssigneeTri demonstrate that an instance's isolation "bubble" isn't necessary for static properties. Isolation of a static property is orthogonal to instance-level isolation.

It would seem, therefore, that in the Assignee case, it should be possible to mark the static property nonisolated, but this doesn't work:

    nonisolated static var currentAssignee: Assignee?
    // ^^ Nonisolated' can not be applied to stored properties

Is there some reason why this should be disallowed?

It comes down to a source-code ergonomics issue. I can certainly remove the global actor annotation from Assignee and apply it only to the declarations I want to be isolated — in other words, construct the class like AssigneeToo rather than Assignee — but this is painful to do and ugly to read if there are a lot of declarations in the type.


** Also, there's a tiny typo in that error message, it seems. It should be 'nonisolated', rather than Nonisolated', shouldn't it?

1 Like