// RUN: %target-swift-emit-silgen -target %target-swift-5.7-abi-triple -parse-as-library %s | %FileCheck %s // RUN: %target-run-simple-swift( -target %target-swift-5.7-abi-triple -parse-as-library) // REQUIRES: executable_test // REQUIRES: concurrency // REQUIRES: distributed // rdar://76038845 // UNSUPPORTED: use_os_stdlib // UNSUPPORTED: back_deployment_runtime import Distributed distributed actor Philosopher { distributed func think() { } // CHECK: sil hidden [ossa] @$s28distributed_actor_self_calls11PhilosopherC10stopEatingyyF : $@convention(method) (@sil_isolated @guaranteed Philosopher) -> () { func stopEating() { // NOTE: marking this async solves the issue; we find the async context then self.think() // Confirm we're calling the function directly, rather than the distributed thunk // Calling the thunk would crash, because it is async (and throws), and as we're not in an async function // trying to get the async context to call the async thunk would fail here. // // CHECK: // function_ref Philosopher.think() // CHECK-NEXT: [[E:%[0-9]+]] = function_ref @$s28distributed_actor_self_calls11PhilosopherC5thinkyyF : $@convention(method) (@sil_isolated @guaranteed Philosopher) -> () } } // ==== Fake Transport --------------------------------------------------------- struct ActorAddress: Sendable, Hashable, Codable { let address: String init(parse address : String) { self.address = address } } struct FakeActorSystem: DistributedActorSystem { typealias ActorID = ActorAddress typealias InvocationDecoder = FakeInvocationDecoder typealias InvocationEncoder = FakeInvocationEncoder typealias SerializationRequirement = Codable typealias ResultHandler = FakeResultHandler func resolve(id: ActorID, as actorType: Act.Type) throws -> Act? where Act: DistributedActor, Act.ID == ActorID { return nil } func assignID(_ actorType: Act.Type) -> ActorID where Act: DistributedActor { ActorAddress(parse: "") } func actorReady(_ actor: Act) where Act: DistributedActor { print("\(#function):\(actor)") } func resignID(_ id: ActorID) {} func makeInvocationEncoder() -> InvocationEncoder { .init() } func remoteCall( on actor: Act, target: RemoteCallTarget, invocation invocationEncoder: inout InvocationEncoder, throwing: Err.Type, returning: Res.Type ) async throws -> Res where Act: DistributedActor, Act.ID == ActorID, Err: Error, Res: SerializationRequirement { fatalError("Not implemented") } func remoteCallVoid( on actor: Act, target: RemoteCallTarget, invocation invocationEncoder: inout InvocationEncoder, throwing: Err.Type ) async throws where Act: DistributedActor, Act.ID == ActorID, Err: Error { fatalError("Not implemented") } } // === Sending / encoding ------------------------------------------------- struct FakeInvocationEncoder: DistributedTargetInvocationEncoder { typealias SerializationRequirement = Codable mutating func recordGenericSubstitution(_ type: T.Type) throws {} mutating func recordArgument(_ argument: RemoteCallArgument) throws {} mutating func recordReturnType(_ type: R.Type) throws {} mutating func recordErrorType(_ type: E.Type) throws {} mutating func doneRecording() throws {} } // === Receiving / decoding ------------------------------------------------- class FakeInvocationDecoder : DistributedTargetInvocationDecoder { typealias SerializationRequirement = Codable func decodeGenericSubstitutions() throws -> [Any.Type] { [] } func decodeNextArgument() throws -> Argument { fatalError() } func decodeReturnType() throws -> Any.Type? { nil } func decodeErrorType() throws -> Any.Type? { nil } } public struct FakeResultHandler: DistributedTargetInvocationResultHandler { public typealias SerializationRequirement = Codable public func onReturn(value: Success) async throws { fatalError("Not implemented: \(#function)") } public func onReturnVoid() async throws { fatalError("Not implemented: \(#function)") } public func onThrow(error: Err) async throws { fatalError("Not implemented: \(#function)") } } typealias DefaultDistributedActorSystem = FakeActorSystem // ==== Execute ---------------------------------------------------------------- func test(system: FakeActorSystem) async { _ = Philosopher(actorSystem: system) } @main struct Main { static func main() async { await test(system: FakeActorSystem()) } }