Skip to content

Commit f48384b

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 a98a30d commit f48384b

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
@@ -4453,12 +4453,32 @@ void ASTMangler::appendDistributedThunk(
44534453
return nullptr;
44544454
};
44554455

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

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)