Skip to content

Commit 863ee97

Browse files
committed
[Distributed] Also prevent mutating remoteCall impls
1 parent 8b569da commit 863ee97

File tree

3 files changed

+159
-28
lines changed

3 files changed

+159
-28
lines changed

lib/AST/DistributedDecl.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -431,6 +431,11 @@ bool AbstractFunctionDecl::isDistributedActorSystemRemoteCall(bool isVoidReturn)
431431
return false;
432432
}
433433

434+
auto *func = dyn_cast<FuncDecl>(this);
435+
if (!func) {
436+
return false;
437+
}
438+
434439
// === Structural Checks
435440
// -- Must be throwing
436441
if (!hasThrows()) {
@@ -442,6 +447,11 @@ bool AbstractFunctionDecl::isDistributedActorSystemRemoteCall(bool isVoidReturn)
442447
return false;
443448
}
444449

450+
// -- Must not be mutating, use classes to implement a system instead
451+
if (func->isMutating()) {
452+
return false;
453+
}
454+
445455
// === Check generics
446456
if (!isGeneric()) {
447457
return false;

lib/Sema/TypeCheckDistributed.cpp

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,7 @@ bool swift::checkDistributedActorSystemAdHocProtocolRequirements(
247247
decl->getDescriptiveKind(), decl->getName(), identifier);
248248
decl->diagnose(
249249
diag::note_distributed_actor_system_conformance_missing_adhoc_requirement,
250-
decl->getName(), identifier,
250+
Proto->getName(), identifier,
251251
"func remoteCall<Act, Err, Res>(\n"
252252
" on actor: Act,\n"
253253
" target: RemoteCallTarget,\n"
@@ -274,7 +274,7 @@ bool swift::checkDistributedActorSystemAdHocProtocolRequirements(
274274
decl->getDescriptiveKind(), decl->getName(), identifier);
275275
decl->diagnose(
276276
diag::note_distributed_actor_system_conformance_missing_adhoc_requirement,
277-
decl->getName(), identifier,
277+
Proto->getName(), identifier,
278278
"func remoteCallVoid<Act, Err>(\n"
279279
" on actor: Act,\n"
280280
" target: RemoteCallTarget,\n"
@@ -303,7 +303,7 @@ bool swift::checkDistributedActorSystemAdHocProtocolRequirements(
303303
diag::distributed_actor_system_conformance_missing_adhoc_requirement,
304304
decl->getDescriptiveKind(), decl->getName(), identifier);
305305
decl->diagnose(diag::note_distributed_actor_system_conformance_missing_adhoc_requirement,
306-
decl->getName(), identifier,
306+
Proto->getName(), identifier,
307307
"mutating func recordArgument<Value: SerializationRequirement>(_ argument: RemoteCallArgument<Value>) throws\n");
308308
anyMissingAdHocRequirements = true;
309309
}
@@ -318,7 +318,7 @@ bool swift::checkDistributedActorSystemAdHocProtocolRequirements(
318318
diag::distributed_actor_system_conformance_missing_adhoc_requirement,
319319
decl->getDescriptiveKind(), decl->getName(), identifier);
320320
decl->diagnose(diag::note_distributed_actor_system_conformance_missing_adhoc_requirement,
321-
decl->getName(), identifier,
321+
Proto->getName(), identifier,
322322
"mutating func recordReturnType<Res: SerializationRequirement>(_ resultType: Res.Type) throws\n");
323323
anyMissingAdHocRequirements = true;
324324
}
@@ -339,7 +339,7 @@ bool swift::checkDistributedActorSystemAdHocProtocolRequirements(
339339
diag::distributed_actor_system_conformance_missing_adhoc_requirement,
340340
decl->getDescriptiveKind(), decl->getName(), identifier);
341341
decl->diagnose(diag::note_distributed_actor_system_conformance_missing_adhoc_requirement,
342-
decl->getName(), identifier,
342+
Proto->getName(), identifier,
343343
"mutating func decodeNextArgument<Argument: SerializationRequirement>() throws -> Argument\n");
344344
anyMissingAdHocRequirements = true;
345345
}
@@ -360,10 +360,9 @@ bool swift::checkDistributedActorSystemAdHocProtocolRequirements(
360360
diag::distributed_actor_system_conformance_missing_adhoc_requirement,
361361
decl->getDescriptiveKind(), decl->getName(), identifier);
362362
decl->diagnose(
363-
diag::
364-
note_distributed_actor_system_conformance_missing_adhoc_requirement,
365-
decl->getName(), identifier,
366-
"mutating func onReturn<Success: SerializationRequirement>(value: "
363+
diag::note_distributed_actor_system_conformance_missing_adhoc_requirement,
364+
Proto->getName(), identifier,
365+
"func onReturn<Success: SerializationRequirement>(value: "
367366
"Success) async throws\n");
368367
anyMissingAdHocRequirements = true;
369368
}

test/Distributed/distributed_actor_system_missing_adhoc_requirement_impls.swift

Lines changed: 141 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@ import Distributed
88

99
struct MissingRemoteCall: DistributedActorSystem {
1010
// expected-error@-1{{struct 'MissingRemoteCall' is missing witness for protocol requirement 'remoteCall'}}
11-
// expected-note@-2{{protocol 'MissingRemoteCall' requires function 'remoteCall' with signature:}}
11+
// expected-note@-2{{protocol 'DistributedActorSystem' requires function 'remoteCall' with signature:}}
1212

1313
// expected-error@-4{{struct 'MissingRemoteCall' is missing witness for protocol requirement 'remoteCallVoid'}}
14-
// expected-note@-5{{protocol 'MissingRemoteCall' requires function 'remoteCallVoid' with signature:}}
14+
// expected-note@-5{{protocol 'DistributedActorSystem' requires function 'remoteCallVoid' with signature:}}
1515

1616
typealias ActorID = ActorAddress
1717
typealias InvocationDecoder = FakeInvocationDecoder
@@ -102,6 +102,128 @@ struct MissingRemoteCall_missingInout_on_encoder: DistributedActorSystem {
102102
}
103103
}
104104

105+
struct RemoteCallMutating: DistributedActorSystem {
106+
// expected-error@-1{{struct 'RemoteCallMutating' is missing witness for protocol requirement 'remoteCall'}}
107+
// expected-note@-2{{protocol 'DistributedActorSystem' requires function 'remoteCall' with signature:}}
108+
109+
// expected-error@-4{{struct 'RemoteCallMutating' is missing witness for protocol requirement 'remoteCallVoid'}}
110+
// expected-note@-5{{protocol 'DistributedActorSystem' requires function 'remoteCallVoid' with signature:}}
111+
112+
typealias ActorID = ActorAddress
113+
typealias InvocationDecoder = FakeInvocationDecoder
114+
typealias InvocationEncoder = FakeInvocationEncoder
115+
typealias SerializationRequirement = Codable
116+
typealias ResultHandler = FakeResultHandler
117+
118+
func resolve<Act>(id: ActorID, as actorType: Act.Type)
119+
throws -> Act? where Act: DistributedActor {
120+
return nil
121+
}
122+
123+
func assignID<Act>(_ actorType: Act.Type) -> ActorID
124+
where Act: DistributedActor {
125+
ActorAddress(parse: "fake://123")
126+
}
127+
128+
func actorReady<Act>(_ actor: Act)
129+
where Act: DistributedActor,
130+
Act.ID == ActorID {
131+
}
132+
133+
func resignID(_ id: ActorID) {
134+
}
135+
136+
mutating func remoteCall<Act, Err, Res>(
137+
on actor: Act,
138+
target: RemoteCallTarget,
139+
invocation: inout InvocationEncoder,
140+
throwing: Err.Type,
141+
returning: Res.Type
142+
) async throws -> Res
143+
where Act: DistributedActor,
144+
Act.ID == ActorID,
145+
Err: Error,
146+
Res: SerializationRequirement {
147+
fatalError("NOT IMPLEMENTED \(#function)")
148+
}
149+
150+
mutating func remoteCallVoid<Act, Err>(
151+
on actor: Act,
152+
target: RemoteCallTarget,
153+
invocation: inout InvocationEncoder,
154+
throwing: Err.Type
155+
) async throws
156+
where Act: DistributedActor,
157+
Act.ID == ActorID,
158+
Err: Error {
159+
fatalError("NOT IMPLEMENTED \(#function)")
160+
}
161+
162+
func makeInvocationEncoder() -> InvocationEncoder {
163+
}
164+
}
165+
166+
struct MissingRemoteCall_missingInout_on_encoder: DistributedActorSystem {
167+
// expected-error@-1{{struct 'MissingRemoteCall_missingInout_on_encoder' is missing witness for protocol requirement 'remoteCall'}}
168+
// expected-note@-2{{protocol 'DistributedActorSystem' requires function 'remoteCall' with signature:}}
169+
170+
// expected-error@-4{{struct 'MissingRemoteCall_missingInout_on_encoder' is missing witness for protocol requirement 'remoteCallVoid'}}
171+
// expected-note@-5{{protocol 'DistributedActorSystem' requires function 'remoteCallVoid' with signature:}}
172+
173+
typealias ActorID = ActorAddress
174+
typealias InvocationDecoder = FakeInvocationDecoder
175+
typealias InvocationEncoder = FakeInvocationEncoder
176+
typealias SerializationRequirement = Codable
177+
typealias ResultHandler = FakeResultHandler
178+
179+
func resolve<Act>(id: ActorID, as actorType: Act.Type)
180+
throws -> Act? where Act: DistributedActor {
181+
return nil
182+
}
183+
184+
func assignID<Act>(_ actorType: Act.Type) -> ActorID
185+
where Act: DistributedActor {
186+
ActorAddress(parse: "fake://123")
187+
}
188+
189+
func actorReady<Act>(_ actor: Act)
190+
where Act: DistributedActor,
191+
Act.ID == ActorID {
192+
}
193+
194+
func resignID(_ id: ActorID) {
195+
}
196+
197+
func remoteCall<Act, Err, Res>(
198+
on actor: Act,
199+
target: RemoteCallTarget,
200+
invocation: InvocationEncoder, // MISSING 'inout'
201+
throwing: Err.Type,
202+
returning: Res.Type
203+
) async throws -> Res
204+
where Act: DistributedActor,
205+
Act.ID == ActorID,
206+
Err: Error,
207+
Res: SerializationRequirement {
208+
fatalError("NOT IMPLEMENTED \(#function)")
209+
}
210+
211+
func remoteCallVoid<Act, Err>(
212+
on actor: Act,
213+
target: RemoteCallTarget,
214+
invocation: InvocationEncoder, // MISSING 'inout'
215+
throwing: Err.Type
216+
) async throws
217+
where Act: DistributedActor,
218+
Act.ID == ActorID,
219+
Err: Error {
220+
fatalError("NOT IMPLEMENTED \(#function)")
221+
}
222+
223+
func makeInvocationEncoder() -> InvocationEncoder {
224+
}
225+
}
226+
105227
struct MissingRemoteCall_missing_makeInvocationEncoder: DistributedActorSystem {
106228
// expected-error@-1{{type 'MissingRemoteCall_missing_makeInvocationEncoder' does not conform to protocol 'DistributedActorSystem'}}
107229

@@ -160,10 +282,10 @@ struct MissingRemoteCall_missing_makeInvocationEncoder: DistributedActorSystem {
160282

161283
struct Error_wrongReturn: DistributedActorSystem {
162284
// expected-error@-1{{struct 'Error_wrongReturn' is missing witness for protocol requirement 'remoteCall'}}
163-
// expected-note@-2{{protocol 'Error_wrongReturn' requires function 'remoteCall' with signature:}}
285+
// expected-note@-2{{protocol 'DistributedActorSystem' requires function 'remoteCall' with signature:}}
164286

165287
// expected-error@-4{{struct 'Error_wrongReturn' is missing witness for protocol requirement 'remoteCallVoid'}}
166-
// expected-note@-5{{protocol 'Error_wrongReturn' requires function 'remoteCallVoid' with signature:}}
288+
// expected-note@-5{{protocol 'DistributedActorSystem' requires function 'remoteCallVoid' with signature:}}
167289

168290
typealias ActorID = ActorAddress
169291
typealias InvocationDecoder = FakeInvocationDecoder
@@ -235,10 +357,10 @@ struct Error_wrongReturn: DistributedActorSystem {
235357

236358
struct BadRemoteCall_param: DistributedActorSystem {
237359
// expected-error@-1{{struct 'BadRemoteCall_param' is missing witness for protocol requirement 'remoteCall'}}
238-
// expected-note@-2{{protocol 'BadRemoteCall_param' requires function 'remoteCall' with signature:}}
360+
// expected-note@-2{{protocol 'DistributedActorSystem' requires function 'remoteCall' with signature:}}
239361

240362
// expected-error@-4{{struct 'BadRemoteCall_param' is missing witness for protocol requirement 'remoteCallVoid'}}
241-
// expected-note@-5{{protocol 'BadRemoteCall_param' requires function 'remoteCallVoid' with signature:}}
363+
// expected-note@-5{{protocol 'DistributedActorSystem' requires function 'remoteCallVoid' with signature:}}
242364

243365
typealias ActorID = ActorAddress
244366
typealias InvocationDecoder = FakeInvocationDecoder
@@ -345,7 +467,7 @@ public struct BadRemoteCall_notPublic: DistributedActorSystem {
345467

346468
public struct BadRemoteCall_badResultConformance: DistributedActorSystem {
347469
// expected-error@-1{{struct 'BadRemoteCall_badResultConformance' is missing witness for protocol requirement 'remoteCall'}}
348-
// expected-note@-2{{protocol 'BadRemoteCall_badResultConformance' requires function 'remoteCall' with signature:}}
470+
// expected-note@-2{{protocol 'DistributedActorSystem' requires function 'remoteCall' with signature:}}
349471

350472
public typealias ActorID = ActorAddress
351473
public typealias InvocationDecoder = PublicFakeInvocationDecoder
@@ -452,7 +574,7 @@ struct BadRemoteCall_largeSerializationRequirement: DistributedActorSystem {
452574

453575
struct BadRemoteCall_largeSerializationRequirementSlightlyOffInDefinition: DistributedActorSystem {
454576
// expected-error@-1{{struct 'BadRemoteCall_largeSerializationRequirementSlightlyOffInDefinition' is missing witness for protocol requirement 'remoteCall'}}
455-
// expected-note@-2{{protocol 'BadRemoteCall_largeSerializationRequirementSlightlyOffInDefinition' requires function 'remoteCall' with signature:}}
577+
// expected-note@-2{{protocol 'DistributedActorSystem' requires function 'remoteCall' with signature:}}
456578

457579
typealias ActorID = ActorAddress
458580
typealias InvocationDecoder = LargeSerializationReqFakeInvocationDecoder
@@ -608,7 +730,7 @@ public struct PublicFakeInvocationEncoder: DistributedTargetInvocationEncoder {
608730

609731
struct FakeInvocationEncoder_missing_recordArgument: DistributedTargetInvocationEncoder {
610732
//expected-error@-1{{struct 'FakeInvocationEncoder_missing_recordArgument' is missing witness for protocol requirement 'recordArgument'}}
611-
//expected-note@-2{{protocol 'FakeInvocationEncoder_missing_recordArgument' requires function 'recordArgument' with signature:}}
733+
//expected-note@-2{{protocol 'DistributedTargetInvocationEncoder' requires function 'recordArgument' with signature:}}
612734
typealias SerializationRequirement = Codable
613735

614736
mutating func recordGenericSubstitution<T>(_ type: T.Type) throws {}
@@ -620,7 +742,7 @@ struct FakeInvocationEncoder_missing_recordArgument: DistributedTargetInvocation
620742

621743
struct FakeInvocationEncoder_missing_recordArgument2: DistributedTargetInvocationEncoder {
622744
//expected-error@-1{{struct 'FakeInvocationEncoder_missing_recordArgument2' is missing witness for protocol requirement 'recordArgument'}}
623-
//expected-note@-2{{protocol 'FakeInvocationEncoder_missing_recordArgument2' requires function 'recordArgument' with signature:}}
745+
//expected-note@-2{{protocol 'DistributedTargetInvocationEncoder' requires function 'recordArgument' with signature:}}
624746
typealias SerializationRequirement = Codable
625747

626748
mutating func recordGenericSubstitution<T>(_ type: T.Type) throws {}
@@ -632,7 +754,7 @@ struct FakeInvocationEncoder_missing_recordArgument2: DistributedTargetInvocatio
632754

633755
struct FakeInvocationEncoder_missing_recordReturnType: DistributedTargetInvocationEncoder {
634756
//expected-error@-1{{struct 'FakeInvocationEncoder_missing_recordReturnType' is missing witness for protocol requirement 'recordReturnType'}}
635-
//expected-note@-2{{protocol 'FakeInvocationEncoder_missing_recordReturnType' requires function 'recordReturnType' with signature:}}
757+
//expected-note@-2{{protocol 'DistributedTargetInvocationEncoder' requires function 'recordReturnType' with signature:}}
636758
typealias SerializationRequirement = Codable
637759

638760
mutating func recordGenericSubstitution<T>(_ type: T.Type) throws {}
@@ -655,7 +777,7 @@ struct FakeInvocationEncoder_missing_recordErrorType: DistributedTargetInvocatio
655777

656778
struct FakeInvocationEncoder_recordArgument_wrongType: DistributedTargetInvocationEncoder {
657779
//expected-error@-1{{struct 'FakeInvocationEncoder_recordArgument_wrongType' is missing witness for protocol requirement 'recordArgument'}}
658-
//expected-note@-2{{protocol 'FakeInvocationEncoder_recordArgument_wrongType' requires function 'recordArgument' with signature:}}
780+
//expected-note@-2{{protocol 'DistributedTargetInvocationEncoder' requires function 'recordArgument' with signature:}}
659781
typealias SerializationRequirement = Codable
660782

661783
mutating func recordGenericSubstitution<T>(_ type: T.Type) throws {}
@@ -668,7 +790,7 @@ struct FakeInvocationEncoder_recordArgument_wrongType: DistributedTargetInvocati
668790
}
669791
struct FakeInvocationEncoder_recordArgument_missingMutating: DistributedTargetInvocationEncoder {
670792
//expected-error@-1{{struct 'FakeInvocationEncoder_recordArgument_missingMutating' is missing witness for protocol requirement 'recordArgument'}}
671-
//expected-note@-2{{protocol 'FakeInvocationEncoder_recordArgument_missingMutating' requires function 'recordArgument' with signature:}}
793+
//expected-note@-2{{protocol 'DistributedTargetInvocationEncoder' requires function 'recordArgument' with signature:}}
672794
typealias SerializationRequirement = Codable
673795

674796
mutating func recordGenericSubstitution<T>(_ type: T.Type) throws {}
@@ -680,7 +802,7 @@ struct FakeInvocationEncoder_recordArgument_missingMutating: DistributedTargetIn
680802

681803
struct FakeInvocationEncoder_recordResultType_wrongType: DistributedTargetInvocationEncoder {
682804
//expected-error@-1{{struct 'FakeInvocationEncoder_recordResultType_wrongType' is missing witness for protocol requirement 'recordReturnType'}}
683-
//expected-note@-2{{protocol 'FakeInvocationEncoder_recordResultType_wrongType' requires function 'recordReturnType' with signature:}}
805+
//expected-note@-2{{protocol 'DistributedTargetInvocationEncoder' requires function 'recordReturnType' with signature:}}
684806
typealias SerializationRequirement = Codable
685807

686808
mutating func recordGenericSubstitution<T>(_ type: T.Type) throws {}
@@ -757,7 +879,7 @@ public final class PublicFakeInvocationDecoder_badNotPublic: DistributedTargetIn
757879

758880
final class PublicFakeInvocationDecoder_badBadProtoRequirement: DistributedTargetInvocationDecoder {
759881
// expected-error@-1{{class 'PublicFakeInvocationDecoder_badBadProtoRequirement' is missing witness for protocol requirement 'decodeNextArgument'}}
760-
// expected-note@-2{{protocol 'PublicFakeInvocationDecoder_badBadProtoRequirement' requires function 'decodeNextArgument' with signature:}}
882+
// expected-note@-2{{protocol 'DistributedTargetInvocationDecoder' requires function 'decodeNextArgument' with signature:}}
761883
typealias SerializationRequirement = Codable
762884

763885
func decodeGenericSubstitutions() throws -> [Any.Type] { [] }
@@ -809,7 +931,7 @@ struct LargeSerializationReqFakeInvocationResultHandler: DistributedTargetInvoca
809931

810932
struct BadResultHandler_missingOnReturn: DistributedTargetInvocationResultHandler {
811933
// expected-error@-1{{struct 'BadResultHandler_missingOnReturn' is missing witness for protocol requirement 'onReturn'}}
812-
// expected-note@-2{{protocol 'BadResultHandler_missingOnReturn' requires function 'onReturn' with signature:}}
934+
// expected-note@-2{{protocol 'DistributedTargetInvocationResultHandler' requires function 'onReturn' with signature:}}
813935
typealias SerializationRequirement = Codable
814936

815937
// func onReturn<Res: SerializationRequirement>(value: Res) async throws {} // MISSING
@@ -819,7 +941,7 @@ struct BadResultHandler_missingOnReturn: DistributedTargetInvocationResultHandle
819941

820942
struct BadResultHandler_missingRequirement: DistributedTargetInvocationResultHandler {
821943
// expected-error@-1{{struct 'BadResultHandler_missingRequirement' is missing witness for protocol requirement 'onReturn'}}
822-
// expected-note@-2{{protocol 'BadResultHandler_missingRequirement' requires function 'onReturn' with signature:}}
944+
// expected-note@-2{{protocol 'DistributedTargetInvocationResultHandler' requires function 'onReturn' with signature:}}
823945
typealias SerializationRequirement = Codable
824946

825947
func onReturn<Success>(value: Success) async throws {} // MISSING : Codable
@@ -828,8 +950,8 @@ struct BadResultHandler_missingRequirement: DistributedTargetInvocationResultHan
828950
}
829951

830952
struct BadResultHandler_mutatingButShouldNotBe: DistributedTargetInvocationResultHandler {
831-
// expected-error@-1{{struct 'BadResultHandler_missingRequirement' is missing witness for protocol requirement 'onReturn'}}
832-
// expected-note@-2{{protocol 'BadResultHandler_missingRequirement' requires function 'onReturn' with signature:}}
953+
// expected-error@-1{{struct 'BadResultHandler_mutatingButShouldNotBe' is missing witness for protocol requirement 'onReturn'}}
954+
// expected-note@-2{{protocol 'DistributedTargetInvocationResultHandler' requires function 'onReturn' with signature:}}
833955
typealias SerializationRequirement = Codable
834956

835957
mutating func onReturn<Success: Codable>(value: Success) async throws {} // WRONG: can't be mutating

0 commit comments

Comments
 (0)