Skip to content

Commit 99ff788

Browse files
authored
Merge pull request #80574 from ktoso/wip-pickwip-tapi-validation
[6.2][Distributed] Fix distributed accessors for resilient modules
2 parents bd83ae1 + eca421d commit 99ff788

File tree

5 files changed

+276
-21
lines changed

5 files changed

+276
-21
lines changed

lib/IRGen/GenMeta.cpp

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1002,7 +1002,7 @@ namespace {
10021002
// Emit the dispatch thunk.
10031003
auto shouldEmitDispatchThunk =
10041004
(Resilient || IGM.getOptions().WitnessMethodElimination) &&
1005-
!func.isDistributed();
1005+
(!func.isDistributed() || !func.isDistributedThunk());
10061006
if (shouldEmitDispatchThunk) {
10071007
IGM.emitDispatchThunk(func);
10081008
}
@@ -1083,16 +1083,14 @@ namespace {
10831083
// Define the method descriptor.
10841084
SILDeclRef func(entry.getFunction());
10851085

1086-
/// Distributed thunks don't need resilience.
1087-
if (func.isDistributedThunk()) {
1088-
continue;
1086+
/// Distributed thunks don't need method descriptors
1087+
if (!func.isDistributedThunk()) {
1088+
auto *descriptor =
1089+
B.getAddrOfCurrentPosition(
1090+
IGM.ProtocolRequirementStructTy);
1091+
IGM.defineMethodDescriptor(func, Proto, descriptor,
1092+
IGM.ProtocolRequirementStructTy);
10891093
}
1090-
1091-
auto *descriptor =
1092-
B.getAddrOfCurrentPosition(
1093-
IGM.ProtocolRequirementStructTy);
1094-
IGM.defineMethodDescriptor(func, Proto, descriptor,
1095-
IGM.ProtocolRequirementStructTy);
10961094
}
10971095
}
10981096

lib/IRGen/IRSymbolVisitor.cpp

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -108,15 +108,6 @@ class IRSymbolVisitorImpl : public SILSymbolVisitor {
108108

109109
void addDispatchThunk(SILDeclRef declRef) override {
110110
auto entity = LinkEntity::forDispatchThunk(declRef);
111-
112-
// TODO: explain why
113-
if (declRef.isDistributedThunk()) {
114-
auto afd = declRef.getAbstractFunctionDecl();
115-
if (afd && isa<ProtocolDecl>(afd->getDeclContext())) {
116-
return;
117-
}
118-
}
119-
120111
addLinkEntity(entity);
121112

122113
if (declRef.getAbstractFunctionDecl()->hasAsync())
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-swift-frontend-emit-module -emit-module-path %t/FakeDistributedActorSystems.swiftmodule -module-name FakeDistributedActorSystems -target %target-swift-6.0-abi-triple %S/../Inputs/FakeDistributedActorSystems.swift -plugin-path %swift-plugin-dir
3+
// RUN: %target-build-swift -module-name ActorsFramework -target %target-swift-6.0-abi-triple -j2 -parse-as-library -I %t %s %S/../Inputs/FakeDistributedActorSystems.swift -plugin-path %swift-plugin-dir -o %t/a.out
4+
// RUN: %target-codesign %t/a.out
5+
// RUN: %env-SWIFT_DUMP_ACCESSIBLE_FUNCTIONS=true %target-run %t/a.out 2>&1 | %FileCheck %s --color --dump-input=always
6+
7+
// REQUIRES: executable_test
8+
// REQUIRES: concurrency
9+
// REQUIRES: distributed
10+
11+
// rdar://76038845
12+
// UNSUPPORTED: use_os_stdlib
13+
// UNSUPPORTED: back_deployment_runtime
14+
15+
// FIXME(distributed): Distributed actors currently have some issues on windows, isRemote always returns false. rdar://82593574
16+
// UNSUPPORTED: OS=windows-msvc
17+
18+
import Distributed
19+
import FakeDistributedActorSystems
20+
21+
// ==== Known actor system -----------------------------------------------------
22+
23+
public struct Response: Codable, Sendable {
24+
let resp: Int
25+
public init(resp: Int) {
26+
self.resp = resp
27+
}
28+
}
29+
30+
public struct Provider: Codable, Sendable {
31+
let r1: Int
32+
public init(r1: Int) {
33+
self.r1 = r1
34+
}
35+
}
36+
37+
@Resolvable
38+
public protocol DistributedNotificationService: DistributedActor
39+
where ActorSystem == FakeRoundtripActorSystem {
40+
distributed func getArray(a1: [Int], a2: String?) async throws -> [Response]
41+
}
42+
43+
distributed actor DistributedNotificationServiceImpl: DistributedNotificationService {
44+
typealias ActorSystem = FakeRoundtripActorSystem
45+
46+
distributed func getArray(a1: [Int], a2: String?) async throws -> [Response] {
47+
[] // mock impl is enough
48+
}
49+
}
50+
51+
// ==== ------------------------------------------------------------------------
52+
53+
@main struct Main {
54+
static func main() async throws {
55+
let roundtripSystem = FakeRoundtripActorSystem()
56+
57+
let real: any DistributedNotificationService = DistributedNotificationServiceImpl(
58+
actorSystem: roundtripSystem)
59+
60+
let proxy: any DistributedNotificationService =
61+
try $DistributedNotificationService.resolve(id: real.id, using: roundtripSystem)
62+
_ = try await proxy.getArray(a1: [], a2: "")
63+
64+
// CHECK: ==== Accessible Function Records ====
65+
66+
// CHECK: Record name: $s15ActorsFramework30DistributedNotificationServicePAA0C001_C9ActorStubRzrlE8getArray2a12a2SayAA8ResponseVGSaySiG_SSSgtYaKFTE
67+
// CHECK: Demangled: distributed thunk (extension in ActorsFramework):ActorsFramework.DistributedNotificationService< where A: Distributed._DistributedActorStub>.getArray(a1: Swift.Array<Swift.Int>, a2: Swift.Optional<Swift.String>) async throws -> Swift.Array<ActorsFramework.Response>
68+
// CHECK: Function Ptr: [[PTR:0x.*]]
69+
// CHECK: Flags.IsDistributed: 1
70+
71+
// CHECK: Record name: $s15ActorsFramework34DistributedNotificationServiceImplC8getArray2a12a2SayAA8ResponseVGSaySiG_SSSgtYaKFTE
72+
// CHECK: Demangled: distributed thunk ActorsFramework.DistributedNotificationServiceImpl.getArray(a1: Swift.Array<Swift.Int>, a2: Swift.Optional<Swift.String>) async throws -> Swift.Array<ActorsFramework.Response>
73+
// CHECK: Function Ptr: [[PTR:0x.*]]
74+
// CHECK: Flags.IsDistributed: 1
75+
76+
// CHECK: Record name: $s15ActorsFramework31$DistributedNotificationServiceC8getArray2a12a2SayAA8ResponseVGSaySiG_SSSgtYaKFTE
77+
// CHECK: Demangled: distributed thunk ActorsFramework.$DistributedNotificationService.getArray(a1: Swift.Array<Swift.Int>, a2: Swift.Optional<Swift.String>) async throws -> Swift.Array<ActorsFramework.Response>
78+
// CHECK: Function Ptr: [[PTR:0x.*]]
79+
// CHECK: Flags.IsDistributed: 1
80+
81+
// CHECK: Record count: 3
82+
// CHECK: ==== End of Accessible Function Records ====
83+
}
84+
}
Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
// RUN: %empty-directory(%t/src)
2+
// RUN: split-file %s %t/src
3+
4+
/// Build the fake actor systems lib
5+
// RUN: %target-build-swift \
6+
// RUN: -target %target-swift-6.0-abi-triple \
7+
// RUN: -parse-as-library -emit-library \
8+
// RUN: -emit-module-path %t/FakeDistributedActorSystems.swiftmodule \
9+
// RUN: -module-name FakeDistributedActorSystems \
10+
// RUN: %S/../Inputs/FakeDistributedActorSystems.swift \
11+
// RUN: -enable-library-evolution \
12+
// RUN: -Xfrontend -validate-tbd-against-ir=all \
13+
// RUN: -o %t/%target-library-name(FakeDistributedActorSystems)
14+
15+
/// Build the Lib
16+
// RUN: %target-build-swift \
17+
// RUN: -target %target-swift-6.0-abi-triple \
18+
// RUN: -parse-as-library -emit-library \
19+
// RUN: -emit-module-path %t/ResilientAPILib.swiftmodule \
20+
// RUN: -module-name ResilientAPILib \
21+
// RUN: -I %t \
22+
// RUN: -L %t \
23+
// RUN: -plugin-path %swift-plugin-dir \
24+
// RUN: %t/src/ResilientAPILib.swift \
25+
// RUN: -lFakeDistributedActorSystems \
26+
// RUN: -enable-library-evolution \
27+
// RUN: -Xfrontend -validate-tbd-against-ir=all \
28+
// RUN: -o %t/%target-library-name(ResilientAPILib)
29+
30+
/// Build the ActorLib
31+
// RUN: %target-build-swift \
32+
// RUN: -target %target-swift-6.0-abi-triple \
33+
// RUN: -parse-as-library -emit-library \
34+
// RUN: -emit-module-path %t/ResilientImplLib.swiftmodule \
35+
// RUN: -module-name ResilientImplLib \
36+
// RUN: -I %t \
37+
// RUN: -L %t \
38+
// RUN: %t/src/ResilientImplLib.swift \
39+
// RUN: -lFakeDistributedActorSystems \
40+
// RUN: -lResilientAPILib \
41+
// RUN: -enable-library-evolution \
42+
// RUN: -Xfrontend -validate-tbd-against-ir=all \
43+
// RUN: -o %t/%target-library-name(ResilientImplLib)
44+
45+
/// Build the client
46+
// RUN: %target-build-swift \
47+
// RUN: -target %target-swift-6.0-abi-triple \
48+
// RUN: -parse-as-library \
49+
// RUN: -lFakeDistributedActorSystems \
50+
// RUN: -lResilientAPILib \
51+
// RUN: -lResilientImplLib \
52+
// RUN: -module-name main \
53+
// RUN: -I %t \
54+
// RUN: -L %t \
55+
// RUN: %s \
56+
// RUN: -enable-library-evolution \
57+
// RUN: -Xfrontend -validate-tbd-against-ir=all \
58+
// RUN: -o %t/a.out
59+
60+
// Sign the main binary and all libraries
61+
// RUN: %target-codesign %t/a.out
62+
// RUN: %target-codesign %t/%target-library-name(FakeDistributedActorSystems)
63+
// RUN: %target-codesign %t/%target-library-name(ResilientAPILib)
64+
// RUN: %target-codesign %t/%target-library-name(ResilientImplLib)
65+
66+
// Run and verify output
67+
// RUN: %env-SWIFT_DUMP_ACCESSIBLE_FUNCTIONS=true %target-run %t/a.out \
68+
// RUN: %t/%target-library-name(FakeDistributedActorSystems) \
69+
// RUN: %t/%target-library-name(ResilientAPILib) \
70+
// RUN: %t/%target-library-name(ResilientImplLib) \
71+
// RUN: 2>&1 \
72+
// RUN: | %FileCheck %s --color --dump-input=always
73+
74+
// REQUIRES: executable_test
75+
// REQUIRES: concurrency
76+
// REQUIRES: distributed
77+
78+
// Locating the built libraries failed on Linux (construction of test case),
79+
// but we primarily care about macOS in this test
80+
// UNSUPPORTED: OS=linux-gnu
81+
82+
// %env does not seem to work on Windows
83+
// UNSUPPORTED: OS=windows-msvc
84+
85+
// UNSUPPORTED: use_os_stdlib
86+
// UNSUPPORTED: back_deployment_runtime
87+
// UNSUPPORTED: remote_run || device_run
88+
89+
90+
// FIXME: Also reproduces the following issue rdar://128284016
91+
//<unknown>:0: error: symbol '$s15ResilientAPILib30ServiceProtocolP8getArray2a12a2SayAA8ResponseVGSaySiG_SSSgtYaKFTj' (dispatch thunk of ResilientAPILib.ServiceProtocol.getArray(a1: Swift.Array<Swift.Int>, a2: Swift.Optional<Swift.String>) async throws -> Swift.Array<ResilientAPILib.Response>) is in generated IR file, but not in TBD file
92+
93+
//<unknown>:0: error: symbol '$s15ResilientAPILib30ServiceProtocolP8getArray2a12a2SayAA8ResponseVGSaySiG_SSSgtYaKFTjTu' (async function pointer to dispatch thunk of ResilientAPILib.ServiceProtocol.getArray(a1: Swift.Array<Swift.Int>, a2: Swift.Optional<Swift.String>) async throws -> Swift.Array<ResilientAPILib.Response>) is in generated IR file, but not in TBD file
94+
95+
//--- ResilientAPILib.swift
96+
97+
import Distributed
98+
import FakeDistributedActorSystems
99+
100+
@available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *)
101+
public struct Response: Codable {}
102+
103+
@Resolvable
104+
@available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *)
105+
public protocol ServiceProtocol: DistributedActor where ActorSystem == FakeRoundtripActorSystem {
106+
distributed func getArray(a1: [Int], a2: String?) -> [Response]
107+
}
108+
109+
//--- ResilientImplLib.swift
110+
111+
import ResilientAPILib
112+
113+
import Distributed
114+
import FakeDistributedActorSystems
115+
116+
@available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *)
117+
public distributed actor ServiceImpl: ServiceProtocol {
118+
public typealias ActorSystem = FakeRoundtripActorSystem
119+
120+
public distributed func getArray(a1: [Int], a2: String?) -> [Response] {
121+
[]
122+
}
123+
}
124+
125+
//--- Main.swift
126+
127+
import ResilientAPILib
128+
import ResilientImplLib
129+
130+
import Distributed
131+
import FakeDistributedActorSystems
132+
133+
@main
134+
struct Main {
135+
static func main() async throws {
136+
if #available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *) {
137+
let system = FakeRoundtripActorSystem()
138+
139+
let real: any ServiceProtocol = ServiceImpl(actorSystem: system)
140+
141+
let proxy: any ServiceProtocol =
142+
try $ServiceProtocol.resolve(id: real.id, using: system)
143+
144+
// just in order to see if we crash and trigger the accessible funcs printout
145+
_ = try await proxy.getArray(a1: [], a2: "")
146+
147+
// === We expect records for accessible functions from other modules as well,
148+
// and especially we want to see records for the `$` macro generated stubs,
149+
// including
150+
151+
// CHECK: ==== Accessible Function Records ====
152+
// CHECK: Record name: $s16ResilientImplLib07ServiceB0C8getArray2a12a2Say0A6APILib8ResponseVGSaySiG_SSSgtYaKFTE
153+
// CHECK: Demangled: distributed thunk ResilientImplLib.ServiceImpl.getArray(a1: Swift.Array<Swift.Int>, a2: Swift.Optional<Swift.String>) async throws -> Swift.Array<ResilientAPILib.Response>
154+
155+
// CHECK: Record name: $s15ResilientAPILib15ServiceProtocolPAA11Distributed01_E9ActorStubRzrlE8getArray2a12a2SayAA8ResponseVGSaySiG_SSSgtYaKFTE
156+
// CHECK: Demangled: distributed thunk (extension in ResilientAPILib):ResilientAPILib.ServiceProtocol< where A: Distributed._DistributedActorStub>.getArray(a1: Swift.Array<Swift.Int>, a2: Swift.Optional<Swift.String>) async throws -> Swift.Array<ResilientAPILib.Response>
157+
158+
// CHECK: Record name: $s15ResilientAPILib16$ServiceProtocolC8getArray2a12a2SayAA8ResponseVGSaySiG_SSSgtYaKFTE
159+
// CHECK: Demangled: distributed thunk ResilientAPILib.$ServiceProtocol.getArray(a1: Swift.Array<Swift.Int>, a2: Swift.Optional<Swift.String>) async throws -> Swift.Array<ResilientAPILib.Response>
160+
161+
// CHECK: Record name: $s4main15ServiceProtocolPAA11Distributed01_D9ActorStubRzrlE8getArray2a12a2SayAA8ResponseVGSaySiG_SSSgtYaKFTE
162+
// CHECK: Demangled: distributed thunk (extension in main):main.ServiceProtocol< where A: Distributed._DistributedActorStub>.getArray(a1: Swift.Array<Swift.Int>, a2: Swift.Optional<Swift.String>) async throws -> Swift.Array<main.Response>
163+
164+
// CHECK: Record name: $s4main11ServiceImplC8getArray2a12a2SayAA8ResponseVGSaySiG_SSSgtYaKFTE
165+
// CHECK: Demangled: distributed thunk main.ServiceImpl.getArray(a1: Swift.Array<Swift.Int>, a2: Swift.Optional<Swift.String>) async throws -> Swift.Array<main.Response>
166+
167+
// CHECK: Record name: $s4main16$ServiceProtocolC8getArray2a12a2SayAA8ResponseVGSaySiG_SSSgtYaKFTE
168+
// CHECK: Demangled: distributed thunk main.$ServiceProtocol.getArray(a1: Swift.Array<Swift.Int>, a2: Swift.Optional<Swift.String>) async throws -> Swift.Array<main.Response>
169+
170+
// We expect these to be the exact records we get, no other ones:
171+
// CHECK: Record count: 6
172+
173+
// CHECK: ==== End of Accessible Function Records ====
174+
175+
print("DONE") // CHECK: DONE
176+
}
177+
}
178+
}

test/TBD/distributed_library_evolution.swift

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
// RUN: -enable-library-evolution \
1010
// RUN: -disable-availability-checking \
1111
// RUN: -emit-ir -o %t/test.ll -emit-tbd \
12+
// RUN: -validate-tbd-against-ir=all \
1213
// RUN: -emit-tbd-path %t/library.tbd -I %t -tbd-install_name protocol
1314

1415
// RUN: %target-swift-frontend %t/library.swift \
@@ -18,9 +19,11 @@
1819
// RUN: -package-name Package \
1920
// RUN: -module-name Library \
2021
// RUN: -emit-module-path %t/Library.swiftmodule \
22+
// RUN: -validate-tbd-against-ir=all \
2123
// RUN: -emit-module-interface-path %t/Library.swiftinterface
2224

23-
// RUN: %target-swift-frontend %t/actor.swift -enable-library-evolution \
25+
// RUN: %target-swift-frontend %t/actor.swift \
26+
// RUN: -enable-library-evolution \
2427
// RUN: -disable-availability-checking -emit-ir -o %t/test.ll -emit-tbd \
2528
// RUN: -emit-tbd-path %t/actor.tbd -I %t -tbd-install_name actor
2629

@@ -31,7 +34,8 @@
3134
// RUN: -package-name Package \
3235
// RUN: -enable-library-evolution \
3336
// RUN: -module-name Client \
34-
// RUN: -emit-module-path %t/Client.swiftmodule \
37+
// RUN: -emit-module-path %t/Client.swiftmodule \
38+
// RUN: -validate-tbd-against-ir=all \
3539
// RUN: -emit-module-interface-path %t/Client.swiftinterface
3640

3741

0 commit comments

Comments
 (0)