Skip to content

Commit 2a3ac44

Browse files
committed
[Distributed] Correct distributed accessor mangling for protocol calls
This is a crucial fix without which we can crash on some distributed protocol declarations with @resolvable. We cannot "just" use a String to represent the "fake base" of the thunks, and must instead find the $Target macro generated type and use it as the base of the thunk's mangling. Calls are made in such way that record for the protocol requirement: `$s4main28GreeterDefinedSystemProtocolP5greetSSyYaKFTEHF` points at `$$s4main29$GreeterDefinedSystemProtocolC5greetSSyYaKFTE` which makes a dispatch through the _apropriate_ witness table. And the record for the $witness named e.g. `$s4main29$GreeterDefinedSystemProtocolC5greetSSyYaKFTEHF` points to `$s4main28GreeterDefinedSystemProtocolPAA11Distributed01_F9ActorStubRzrlE5greetSSyYaKFTE` which is an extension method: `distributed thunk (extension in main):main.GreeterDefinedSystemProtocol< where A: Distributed._DistributedActorStub>.greet() async throws -> Swift.String`, this very specific design allows us to call the "right method" on the recieving end of a remote call where we do not know the recipient type.
1 parent a8a1f8b commit 2a3ac44

4 files changed

+31
-9
lines changed

lib/AST/ASTMangler.cpp

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4452,12 +4452,32 @@ void ASTMangler::appendDistributedThunk(
44524452
return nullptr;
44534453
};
44544454

4455-
if (auto *P = referenceInProtocolContextOrRequirement()) {
4456-
appendContext(P->getDeclContext(), base,
4457-
thunk->getAlternateModuleName());
4458-
appendIdentifier(Twine("$", P->getNameStr()).str());
4459-
appendOperator("C"); // necessary for roundtrip, though we don't use it
4455+
// Determine if we should mangle with a $Target substitute decl context,
4456+
// this matters for @Resolvable calls / protocol calls where the caller
4457+
// does not know the type of the recipient distributed actor, and we use the
4458+
// $Target type as substitute to then generically invoke it on the type of the
4459+
// recipient, whichever 'protocol Type'-conforming type it will be.
4460+
NominalTypeDecl *stubActorDecl = nullptr;
4461+
if (auto P = referenceInProtocolContextOrRequirement()) {
4462+
auto &C = thunk->getASTContext();
4463+
auto M = thunk->getModuleContext();
4464+
4465+
SmallVector<ValueDecl *, 1> stubClassLookupResults;
4466+
C.lookupInModule(M, ("$" + P->getNameStr()).str(), stubClassLookupResults);
4467+
4468+
if (stubClassLookupResults.size() > 0) {
4469+
stubActorDecl =
4470+
dyn_cast_or_null<NominalTypeDecl>(stubClassLookupResults.front());
4471+
}
4472+
}
4473+
4474+
if (stubActorDecl) {
4475+
// Effectively mangle the thunk as if it was declared on the $StubTarget
4476+
// type, rather than on a `protocol Target`.
4477+
appendContext(stubActorDecl, base, thunk->getAlternateModuleName());
44604478
} else {
4479+
// There's no need to replace the context, this is a normal concrete type
4480+
// remote call identifier.
44614481
appendContextOf(thunk, base);
44624482
}
44634483

test/Distributed/Runtime/distributed_actor_func_calls_remoteCall_extension.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,9 @@ func test() async throws {
4040
let ref = try KappaProtocolImpl.resolve(id: local.id, using: system)
4141

4242
let reply = try await ref.echo(name: "Caplin")
43-
// CHECK: >> remoteCall: on:main.KappaProtocolImpl, target:main.$KappaProtocol.echo(name:), invocation:FakeInvocationEncoder(genericSubs: [main.KappaProtocolImpl], arguments: ["Caplin"], returnType: Optional(Swift.String), errorType: nil), throwing:Swift.Never, returning:Swift.String
43+
// CHECK: >> remoteCall: on:main.KappaProtocolImpl, target:echo(name:), invocation:FakeInvocationEncoder(genericSubs: [main.KappaProtocolImpl], arguments: ["Caplin"], returnType: Optional(Swift.String), errorType: nil), throwing:Swift.Never, returning:Swift.String
44+
// CHECK: > execute distributed target: echo(name:), identifier: $s4main13KappaProtocolPAAE4echo4nameS2S_tYaKFTE
45+
// CHECK: > decode generic subs: [main.KappaProtocolImpl]
4446

4547
// CHECK: << remoteCall return: Echo: Caplin
4648
print("reply: \(reply)")

test/Distributed/Runtime/distributed_actor_func_calls_remoteCall_through_generic.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// RUN: %empty-directory(%t)
22
// RUN: %target-swift-frontend-emit-module -emit-module-path %t/FakeDistributedActorSystems.swiftmodule -module-name FakeDistributedActorSystems -target %target-swift-5.7-abi-triple %S/../Inputs/FakeDistributedActorSystems.swift
3-
// RUN: %target-build-swift -module-name main -target %target-swift-5.7-abi-triple -j2 -parse-as-library -I %t %s %S/../Inputs/FakeDistributedActorSystems.swift -o %t/a.out
3+
// RUN: %target-build-swift -module-name main -target %target-swift-5.7-abi-triple -j2 -parse-as-library -plugin-path %swift-plugin-dir -I %t %s %S/../Inputs/FakeDistributedActorSystems.swift -o %t/a.out
44
// RUN: %target-codesign %t/a.out
55
// RUN: %target-run %t/a.out | %FileCheck %s
66

test/Distributed/Runtime/distributed_actor_localSystem_distributedProtocol.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ func test_distributedVariable<DA: WorkerProtocol>(actor: DA) async throws -> Str
6464
let v1 = try await test_distributedVariable(actor: actor)
6565
print("v1 = \(v1)") // CHECK: v1 = implemented variable
6666

67-
let v = try await actor.distributedVariable
68-
print("v = \(v)") // CHECK: v = implemented variable
67+
let v2 = try await actor.distributedVariable
68+
print("v2 = \(v2)") // CHECK: v2 = implemented variable
6969
}
7070
}

0 commit comments

Comments
 (0)