Skip to content

Commit 52a9713

Browse files
authored
Merge pull request #39523 from apple/wip-self-call-should-not-thunk
[Distributed] calls on self should not call the dist thunk
2 parents 16fc9e1 + a9dc948 commit 52a9713

File tree

2 files changed

+80
-1
lines changed

2 files changed

+80
-1
lines changed

lib/SILGen/SILGenApply.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1118,7 +1118,11 @@ class SILGenApply : public Lowering::ExprVisitor<SILGenApply> {
11181118
// Otherwise, we have a statically-dispatched call.
11191119
auto constant = SILDeclRef(e->getDecl());
11201120
if (e->getDecl()->getAttrs().hasAttribute<DistributedActorAttr>()) {
1121-
constant = constant.asDistributed(true);
1121+
// we're calling a distributed function, only in cross-actor situations
1122+
// does this actually need to call the thunk.
1123+
if (!selfApply) {
1124+
constant = constant.asDistributed(true);
1125+
}
11221126
} else {
11231127
constant = constant.asForeign(
11241128
!isConstructorWithGeneratedAllocatorThunk(e->getDecl())
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
// RUN: %target-swift-emit-silgen -enable-experimental-distributed -disable-availability-checking -parse-as-library %s | %FileCheck %s
2+
// RUN: %target-run-simple-swift(-Xfrontend -enable-experimental-distributed -Xfrontend -disable-availability-checking -parse-as-library)
3+
4+
// REQUIRES: executable_test
5+
// REQUIRES: concurrency
6+
// REQUIRES: distributed
7+
8+
// rdar://76038845
9+
// UNSUPPORTED: use_os_stdlib
10+
// UNSUPPORTED: back_deployment_runtime
11+
12+
import _Distributed
13+
14+
distributed actor Philosopher {
15+
16+
distributed func think() {
17+
}
18+
19+
// CHECK: sil hidden [ossa] @$s28distributed_actor_self_calls11PhilosopherC10stopEatingyyF : $@convention(method) (@guaranteed Philosopher) -> () {
20+
func stopEating() { // NOTE: marking this async solves the issue; we find the async context then
21+
self.think()
22+
23+
// Confirm we're calling the function directly, rather than the distributed thunk
24+
// Calling the thunk would crash, because it is async (and throws), and as we're not in an async function
25+
// trying to get the async context to call the async thunk would fail here.
26+
//
27+
// CHECK: // function_ref Philosopher.think()
28+
// CHECK-NEXT: [[E:%[0-9]+]] = function_ref @$s28distributed_actor_self_calls11PhilosopherC5thinkyyF : $@convention(method) (@guaranteed Philosopher) -> ()
29+
}
30+
}
31+
32+
33+
// ==== Fake Transport ---------------------------------------------------------
34+
35+
struct ActorAddress: ActorIdentity {
36+
let address: String
37+
init(parse address : String) {
38+
self.address = address
39+
}
40+
}
41+
42+
struct FakeTransport: ActorTransport {
43+
func decodeIdentity(from decoder: Decoder) throws -> AnyActorIdentity {
44+
fatalError("not implemented \(#function)")
45+
}
46+
47+
func resolve<Act>(_ identity: AnyActorIdentity, as actorType: Act.Type) throws -> Act?
48+
where Act: DistributedActor {
49+
return nil
50+
}
51+
52+
func assignIdentity<Act>(_ actorType: Act.Type) -> AnyActorIdentity
53+
where Act: DistributedActor {
54+
.init(ActorAddress(parse: ""))
55+
}
56+
57+
public func actorReady<Act>(_ actor: Act)
58+
where Act: DistributedActor {
59+
print("\(#function):\(actor)")
60+
}
61+
62+
func resignIdentity(_ id: AnyActorIdentity) {}
63+
}
64+
65+
// ==== Execute ----------------------------------------------------------------
66+
67+
func test(transport: FakeTransport) async {
68+
_ = Philosopher(transport: transport)
69+
}
70+
71+
@main struct Main {
72+
static func main() async {
73+
await test(transport: FakeTransport())
74+
}
75+
}

0 commit comments

Comments
 (0)