Calling a MainActor method from a existential type

protocol Pro {
    func foo()
}

struct ST: Pro {
    @MainActor
    func foo(){
        print("foo")
    }
}

let x: any Pro = ST()


x.foo()
print("end")

Why doesn't x.foo() require await?
is it a bug?

Ideally when making the protocol requirement foo MainActor isolated you should get some warning, is this happening for you?

Is this a playground projects? I don‘t know, but I somewhat would assume that playground would spawn everything on the main thread and possibly know that on the static code level of the main code page. (Pure assumption, please feel free to correct me if that‘s wrong.)

I ran on Linux the top-level, in the main.swift. I assume it runs on main thread. but you can also use Task:

Task {
    x.foo() // no await required.
}

I think using Task it will spawn it on other thread.

If you add -Xfrontend -warn-concurrency, the compiler will detect the mismatch:

<source>:7:10: warning: main actor-isolated instance method 'foo()' cannot be used to satisfy nonisolated protocol requirement
    func foo(){
         ^
<source>:2:10: note: mark the protocol requirement 'foo()' 'async' to allow actor-isolated conformances
    func foo()
         ^
               async

My understanding is that in Swift 6, this option will be enabled by default, and this will result in a hard error rather than just a warning.

Also, if you add -Xfrontend -enable-actor-data-race-checks, you'll get a fatal error at runtime:

warning: data race detected: @MainActor function at output/example.swift:7 was not called on the main thread

Godbolt