Skip to content

Commit 197466b

Browse files
committed
[DistributedProtocolMacro] Correct handling empty protocols
1 parent bf52e6b commit 197466b

File tree

3 files changed

+45
-24
lines changed

3 files changed

+45
-24
lines changed

lib/Macros/Sources/SwiftMacros/DistributedProtocolMacro.swift

Lines changed: 43 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,12 @@ extension DistributedProtocolMacro {
3636
in context: some MacroExpansionContext
3737
) throws -> [ExtensionDeclSyntax] {
3838
guard let proto = declaration.as(ProtocolDeclSyntax.self) else {
39+
// we diagnose here, only once
40+
try throwIllegalTargetDecl(node: node, declaration)
41+
}
42+
43+
guard !proto.memberBlock.members.isEmpty else {
44+
// ok, the protocol has no requirements so we no-op it
3945
return []
4046
}
4147

@@ -44,17 +50,7 @@ extension DistributedProtocolMacro {
4450
member.trimmed
4551
}
4652
let requirementStubs = requirements
47-
.map { req in
48-
"""
49-
\(req) {
50-
if #available(SwiftStdlib 6.0, *) {
51-
Distributed._distributedStubFatalError()
52-
} else {
53-
fatalError()
54-
}
55-
}
56-
"""
57-
}.joined(separator: "\n ")
53+
.map(stubMethod).joined(separator: "\n ")
5854

5955
let extensionDecl: DeclSyntax =
6056
"""
@@ -64,6 +60,24 @@ extension DistributedProtocolMacro {
6460
"""
6561
return [extensionDecl.cast(ExtensionDeclSyntax.self)]
6662
}
63+
64+
static func stubMethod(_ requirementDeclaration: MemberBlockItemListSyntax.Element) -> String {
65+
"""
66+
\(requirementDeclaration) {
67+
\(stubFunctionBody())
68+
}
69+
"""
70+
}
71+
72+
static func stubFunctionBody() -> DeclSyntax {
73+
"""
74+
if #available(SwiftStdlib 6.0, *) {
75+
Distributed._distributedStubFatalError()
76+
} else {
77+
fatalError()
78+
}
79+
"""
80+
}
6781
}
6882

6983
// ===== -----------------------------------------------------------------------
@@ -76,15 +90,30 @@ extension DistributedProtocolMacro {
7690
in context: some MacroExpansionContext
7791
) throws -> [DeclSyntax] {
7892
guard let proto = declaration.as(ProtocolDeclSyntax.self) else {
79-
try throwIllegalTargetDecl(node: node, declaration)
93+
// don't diagnose here (again),
94+
// we'll already report an error here from the other macro role
95+
return []
8096
}
8197

8298
var isGenericStub = false
8399
var specificActorSystemRequirement: TypeSyntax?
84100
// FIXME must detect this off the protocol
85101
let serializationRequirementType: String = "Codable"
86102

87-
for req in proto.genericWhereClause?.requirements ?? [] {
103+
guard let genericWhereClause = proto.genericWhereClause else {
104+
guard !proto.memberBlock.members.isEmpty else {
105+
// ok, the protocol has no requirements so we no-op it
106+
return []
107+
}
108+
throw DiagnosticsError(
109+
syntax: node,
110+
message: """
111+
Distributed protocol must declare actor system with SerializationRequirement, for example:
112+
protocol Greeter<ActorSystem>: DistributedActor where ActorSystem: DistributedActorSystem<any Codable>
113+
""", id: .invalidApplication)
114+
}
115+
116+
for req in genericWhereClause.requirements {
88117
print("req.requirement: \(req.requirement)")
89118
switch req.requirement {
90119
case .conformanceRequirement(let conformanceReq)
@@ -125,7 +154,7 @@ extension DistributedProtocolMacro {
125154
} else {
126155
throw DiagnosticsError(
127156
syntax: node,
128-
message: "'@DistributedProtocolMacro' cannot be applied to ", id: .invalidApplication)
157+
message: "'@DistributedProtocol' cannot be applied to ", id: .invalidApplication)
129158
}
130159

131160
return [stubActorDecl]

test/Distributed/Macros/distributed_macro_expansion_DistributedProtocol_errors.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
// RUN: %empty-directory(%t-scratch)
99

1010
// RUN: %target-swift-frontend-emit-module -emit-module-path %t/FakeDistributedActorSystems.swiftmodule -module-name FakeDistributedActorSystems -disable-availability-checking %S/../Inputs/FakeDistributedActorSystems.swift
11-
// RUN: %target-swift-frontend -typecheck -verify -disable-availability-checking -plugin-path %swift-plugin-dir -parse-as-library -I %t %S/../Inputs/FakeDistributedActorSystems.swift -dump-macro-expansions %s -dump-macro-expansions 2>&1
11+
// RUN: %target-swift-frontend -typecheck -verify -disable-availability-checking -plugin-path %swift-plugin-dir -parse-as-library -I %t %S/../Inputs/FakeDistributedActorSystems.swift -dump-macro-expansions %s 2>&1
1212

1313
import Distributed
1414

test/Distributed/Macros/distributed_macro_expansion_DistributedProtocol_inheritance.swift

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,8 @@ typealias System = LocalTestingDistributedActorSystem
1717
protocol EmptyBase {}
1818

1919
// @_DistributedProtocol ->
20-
//
21-
// CHECK: distributed actor $EmptyBase<ActorSystem>: EmptyBase,
22-
// CHECK: Distributed._DistributedActorStub
23-
// CHECK: where ActorSystem: DistributedActorSystem<any Codable>,
24-
// CHECK: ActorSystem.ActorID: Codable
25-
// CHECK: {
26-
// CHECK: }
2720

28-
// CHECK: extension EmptyBase where Self: Distributed._DistributedActorStub {
29-
// CHECK: }
21+
// nothing, no-op
3022

3123
// ==== ------------------------------------------------------------------------
3224

0 commit comments

Comments
 (0)