@MainActor errors seem inconsistent

I'm sure this is ignorance on my part, but I can't seem to grok how the compiler deals with @MainActor. For example, NSApplication inherits from NSResponder which is annotated with @MainActor. This means NSApplication should inherit that behavior. According to SE-0316, in a type annotated with a global actor "all of the methods, properties, and subscripts will implicitly be isolated to that global actor". I would expect this code would require isolation on the MainActor:

class Test {
    func getAppearance() -> NSAppearance {
        NSApp.effectiveAppearance
    }
}

Surprisingly, this code compiles with no warnings. Perhaps a class explicitly annotated as MainActor would raise an error:

extension Test {
    func modal() {
        NSAlert(error: CancellationError()).runModal()
    }
}

Nope, no warnings or errors there either. If I create my own method and annotate it:

extension NSApplication {
    @MainActor
    var mainProperty: Bool { .random() }
}

extension Test {
    func getMain() -> Bool {
        NSApp.mainProperty  // Error
    }
}

Sure enough, the compiler raises the following error: Main actor-isolated property 'mainProperty' can not be referenced from a non-isolated context.

Creating my own class and calling its method gives me this warning: Call to main actor-isolated initializer 'init()' in a synchronous nonisolated context; this is an error in Swift 6

@MainActor
class T {}

extension Test {
    func makeT() {
        _ = T()  // Warning
    }
}

Changing the Strict Concurrency Checking build setting to Complete adds errors/warnings to all above examples, but it also warns that NSApp is not concurrency-safe. This means any reference to NSApp would create warnings which is a bit too stingy. The other two settings, Targeted and Minimal behave as described above.

It isn't clear to me how to properly use @MainActor to protect against calling UI code outside the main thread. AppKit classes seem to be ignored which means I would need to sprinkle the annotation all over my UI classes, and any that I overlook wouldn't generate warnings. This seems like a truly useful technology, but it is confounding to understand.

1 Like

Found the answer to my own question. I discovered SE-0337 that lays out the incremental adoption plan for concurrency.