Open
Description
Description
I would expect the dynamic check to be inserted to an actor call when we witness a synchronous requirement with an actor method and a @preoncurrency conformance, yet we don't get the check when we call the actor:
Reproduction
//// SampleAPI module
// Old Library
public protocol OldProtocol {
func check() async -> Int
func somethingHappened() -> Int
}
// My Library
@available(macOS 10.15, *)
public actor MyActor: @preconcurrency OldProtocol {
public init() {}
var num: Int = 12
public func check() async -> Int {
self.somethingHappened()
}
public func somethingHappened() -> Int { // ?!
self.preconditionIsolated() // WILL FAIL in "protocolCall" case
num += 1
return num
}
}
```swift
//// SampleAPITests module
import Testing
import SampleAPI
@Suite
class ClientTests {
@Test
@available(macOS 15.0, *)
func test() async throws {
let a = MyActor()
await a.somethingHappened()
}
@Test
@available(macOS 15.0, *)
func protocolCall() async throws {
let a: any OldProtocol = MyActor()
let v = a.somethingHappened()
#expect(v == 13)
}
}
Expected behavior
The problem is that the
let a: any OldProtocol = MyActor()
let v = a.somethingHappened()
actually opens the existential and we end up calling directly on MyActor
and therefore sidestepping the dynamic safety check we're supposed to be doing there.
We may need to insert checks directly into the actor methods when using a preconcurrency conformance?
Environment
Apple Swift version 6.0 (swiftlang-6.0.0.9.10 clang-1600.0.26.2)
Target: arm64-apple-macosx15.0
Additional information
Tracked as rdar://136067696