mirror of
https://github.com/apple/swift.git
synced 2026-10-16 16:50:49 +02:00
A cross-actor call to a synchronous distributed func is marked implicitly async, with the actor as its hop target. callsDistributedThunk() is meant to skip that hop when the call is dispatched through the distributed thunk, which never needs to run on the actor. It decides this by checking whether the callee's SILDeclRef is a distributed thunk reference. That is the case for direct calls, but not for calls through a protocol requirement: there the callee still names the requirement, and it is redirected to the requirement's distributed thunk only later, when the callee value is emitted (Callee::getFnValue). Generic code therefore still emitted: hop_to_executor %w try_apply witness_method $W, #P.f!distributed_thunk(...) which hops onto an actor that may be a remote reference, before the thunk's isRemote check. For a remote reference the hop lands on DistributedRemoteActorReferenceExecutor, whose enqueue is a fatal error. OptimizeHopToExecutor normally deletes this hop, which is why it went unnoticed. With -enable-sil-opaque-values, AddressLowering materializes the @in_guaranteed argument with a store_borrow between the hop and the call, the hop survives causing a crash with the following error: "Attempted to enqueue ExecutorJob ... on executor of remote distributed actor reference!". Make callsDistributedThunk() also return true for witness method callees that will be redirected to the thunk. It asks the same question as getFnValue so the two decisions cannot diverge. Add test/Distributed/SIL/distributed_thunk_call_no_hop.swift, which checks that no hop to the actor is emitted before direct, generic and distributed var calls, with and without opaque values.