Skip to content

Commit 0fec1b3

Browse files
committed
[Distributed] Implement ad-hoc checks for
DistributedTargetInvocationEncoder
1 parent c7e3af8 commit 0fec1b3

File tree

5 files changed

+79
-49
lines changed

5 files changed

+79
-49
lines changed

lib/AST/DistributedDecl.cpp

Lines changed: 7 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -252,8 +252,6 @@ bool AbstractFunctionDecl::isDistributedActorSystemRemoteCall(bool isVoidReturn)
252252
auto &C = getASTContext();
253253
auto module = getParentModule();
254254

255-
auto decl = dyn_cast<NominalTypeDecl>(getParent());
256-
257255
fprintf(stderr, "[%s:%d] (%s) ====================================================\n", __FILE__, __LINE__, __FUNCTION__);
258256
fprintf(stderr, "[%s:%d] (%s) ====================================================\n", __FILE__, __LINE__, __FUNCTION__);
259257
fprintf(stderr, "[%s:%d] (%s) ====================================================\n", __FILE__, __LINE__, __FUNCTION__);
@@ -318,7 +316,7 @@ bool AbstractFunctionDecl::isDistributedActorSystemRemoteCall(bool isVoidReturn)
318316

319317
// -- Check number of generic requirements
320318
size_t expectedRequirementsNum = 3;
321-
auto serializationRequirementsNum = 0;
319+
size_t serializationRequirementsNum = 0;
322320
if (!isVoidReturn) {
323321
serializationRequirementsNum = requirementProtos.size();
324322
expectedRequirementsNum += serializationRequirementsNum;
@@ -337,37 +335,32 @@ bool AbstractFunctionDecl::isDistributedActorSystemRemoteCall(bool isVoidReturn)
337335
// --- Check parameter: on: Actor
338336
auto actorParam = params->get(0);
339337
if (actorParam->getArgumentName() != C.Id_on) {
340-
fprintf(stderr, "[%s:%d] (%s) if (actorParam->getArgumentName() != C.Id_on)\n", __FILE__, __LINE__, __FUNCTION__);
341338
return false;
342339
}
343340

344341
// --- Check parameter: target RemoteCallTarget
345342
auto targetParam = params->get(1);
346343
if (targetParam->getArgumentName() != C.Id_target) {
347-
fprintf(stderr, "[%s:%d] (%s) if (targetParam->getArgumentName() != C.Id_target)\n", __FILE__, __LINE__, __FUNCTION__);
348344
return false;
349345
}
350346

351347
// --- Check parameter: invocation InvocationEncoder
352348
// FIXME: NOT INOUT, but we crash today if not
353349
auto invocationParam = params->get(2);
354350
if (invocationParam->getArgumentName() != C.Id_invocation) {
355-
fprintf(stderr, "[%s:%d] (%s) if (invocationParam->getArgumentName() != C.Id_invocation) {\n", __FILE__, __LINE__, __FUNCTION__);
356351
return false;
357352
}
358353

359354
// --- Check parameter: throwing: Err.Type
360355
auto thrownTypeParam = params->get(3);
361356
if (thrownTypeParam->getArgumentName() != C.Id_throwing) {
362-
fprintf(stderr, "[%s:%d] (%s) if (thrownTypeParam->getArgumentName() != C.Id_throwing) {\n", __FILE__, __LINE__, __FUNCTION__);
363357
return false;
364358
}
365359

366360
// --- Check parameter: returning: Res.Type
367361
if (!isVoidReturn) {
368362
auto returnedTypeParam = params->get(4);
369363
if (returnedTypeParam->getArgumentName() != C.Id_returning) {
370-
fprintf(stderr, "[%s:%d] (%s) if (thrownTypeParam->getArgumentName() != C.Id_throwing) {\n", __FILE__, __LINE__, __FUNCTION__);
371364
return false;
372365
}
373366
}
@@ -384,7 +377,6 @@ bool AbstractFunctionDecl::isDistributedActorSystemRemoteCall(bool isVoidReturn)
384377
mapTypeIntoContext(ActParam->getDeclaredInterfaceType()),
385378
C.getProtocol(KnownProtocolKind::DistributedActor));
386379
if (ActConformance.isInvalid()) {
387-
fprintf(stderr, "[%s:%d] (%s) if (ActConformance.isInvalid()) {\n", __FILE__, __LINE__, __FUNCTION__);
388380
return false;
389381
}
390382

@@ -394,7 +386,6 @@ bool AbstractFunctionDecl::isDistributedActorSystemRemoteCall(bool isVoidReturn)
394386
mapTypeIntoContext(ErrParam->getDeclaredInterfaceType()),
395387
C.getProtocol(KnownProtocolKind::Error));
396388
if (ErrConformance.isInvalid()) {
397-
fprintf(stderr, "[%s:%d] (%s) if (ErrConformance.isInvalid())\n", __FILE__, __LINE__, __FUNCTION__);
398389
return false;
399390
}
400391

@@ -419,9 +410,6 @@ bool AbstractFunctionDecl::isDistributedActorSystemRemoteCall(bool isVoidReturn)
419410
}
420411

421412
if (requirements.size() != expectedRequirementsNum) {
422-
fprintf(stderr, "[%s:%d] (%s) requirements.size() = %d\n", __FILE__, __LINE__, __FUNCTION__, requirements.size());
423-
fprintf(stderr, "[%s:%d] (%s) expectedRequirementsNum = %d\n", __FILE__, __LINE__, __FUNCTION__, expectedRequirementsNum);
424-
fprintf(stderr, "[%s:%d] (%s) if (requirements.size() != expectedRequirementsNum)\n", __FILE__, __LINE__, __FUNCTION__);
425413
return false;
426414
}
427415

@@ -441,11 +429,9 @@ bool AbstractFunctionDecl::isDistributedActorSystemRemoteCall(bool isVoidReturn)
441429
->getInterfaceType()
442430
->getMetatypeInstanceType();
443431
if (actorReq.getKind() != RequirementKind::Conformance) {
444-
fprintf(stderr, "[%s:%d] (%s) if (actorReq.getKind() != RequirementKind::Conformance) {\n", __FILE__, __LINE__, __FUNCTION__);
445432
return false;
446433
}
447434
if (!actorReq.getSecondType()->isEqual(distActorTy)) {
448-
fprintf(stderr, "[%s:%d] (%s) if (actorReq.getSecondType()->isEqual(distActorTy)) {\n", __FILE__, __LINE__, __FUNCTION__);
449435
return false;
450436
}
451437

@@ -455,47 +441,35 @@ bool AbstractFunctionDecl::isDistributedActorSystemRemoteCall(bool isVoidReturn)
455441
->getInterfaceType()
456442
->getMetatypeInstanceType();
457443
if (errorReq.getKind() != RequirementKind::Conformance) {
458-
fprintf(stderr, "[%s:%d] (%s) if (errorReq.getKind() != RequirementKind::Conformance) {\n", __FILE__, __LINE__, __FUNCTION__);
459444
return false;
460445
}
461446
if (!errorReq.getSecondType()->isEqual(errorTy)) {
462-
fprintf(stderr, "[%s:%d] (%s) if (errorReq.getSecondType()->isEqual(errorTy)) {\n", __FILE__, __LINE__, __FUNCTION__);
463447
return false;
464448
}
465449

466450
// --- Check requirement: Res either Void or all SerializationRequirements
467451
if (isVoidReturn) {
468452
if (auto func = dyn_cast<FuncDecl>(this)) {
469453
if (!func->getResultInterfaceType()->isVoid()) {
470-
fprintf(stderr, "[%s:%d] (%s) if (!func->getResultInterfaceType()->isVoid()) {\n", __FILE__, __LINE__, __FUNCTION__);
471454
return false;
472455
}
473456
}
474457
} else if (ResParam) {
475-
// FIXME(distributed): implement checking return type for serialization requirement
476458
assert(ResParam && "Non void function, yet no Res generic parameter found");
477459
if (auto func = dyn_cast<FuncDecl>(this)) {
478-
auto resultType = func->mapTypeIntoContext(func->getResultInterfaceType());
460+
auto resultType = func->mapTypeIntoContext(func->getResultInterfaceType())
461+
->getMetatypeInstanceType()
462+
->getDesugaredType();
463+
auto resultParamType = func->mapTypeIntoContext(
464+
ResParam->getInterfaceType()->getMetatypeInstanceType());
479465
// The result of the function must be the `Res` generic argument.
480-
if (!resultType->getMetatypeInstanceType()->getDesugaredType()->isEqual(
481-
func->mapTypeIntoContext(ResParam->getInterfaceType()->getMetatypeInstanceType()))) {
482-
fprintf(stderr, "[%s:%d] (%s) resultType->getMetatypeInstanceType()\n", __FILE__, __LINE__, __FUNCTION__);
483-
resultType->getMetatypeInstanceType().dump();
484-
fprintf(stderr, "[%s:%d] (%s) ResParam->getInterfaceType()->getMetatypeInstanceType()\n", __FILE__, __LINE__, __FUNCTION__);
485-
ResParam->getInterfaceType()->getMetatypeInstanceType().dump();
486-
487-
fprintf(stderr, "[%s:%d] (%s) if (!resultType->getMetatypeInstanceType()->isEqual(ResParam->getInterfaceType()->getMetatypeInstanceType()))\n", __FILE__, __LINE__, __FUNCTION__);
466+
if (!resultType->isEqual(resultParamType)) {
488467
return false;
489468
}
490469

491-
// FIXME: look at requirements
492-
493470
for (auto requirementProto : requirementProtos) {
494471
auto conformance = module->lookupConformance(resultType, requirementProto);
495472
if (conformance.isInvalid()) {
496-
// fprintf(stderr, "[%s:%d] (%s) %s missing conformance to %s\n", __FILE__, __LINE__, __FUNCTION__,
497-
// resultType->getAnyNominal()->getNameStr().str().c_str(),
498-
// requirementProto->getInterfaceType()->getAnyNominal()->getNameStr().str().c_str());
499473
return false;
500474
}
501475
}
@@ -505,18 +479,15 @@ bool AbstractFunctionDecl::isDistributedActorSystemRemoteCall(bool isVoidReturn)
505479
// -- Check requirement: same_type Actor.ID Self.ActorID
506480
auto actorIdReq = requirements.back();
507481
if (actorIdReq.getKind() != RequirementKind::SameType) {
508-
fprintf(stderr, "[%s:%d] (%s) if (actorIdReq.getKind() != RequirementKind::SameType){ \n", __FILE__, __LINE__, __FUNCTION__);
509482
return false;
510483
}
511484
auto expectedActorIdTy =
512485
getDistributedActorSystemActorIDRequirementType(systemNominal);
513486
actorIdReq.dump();
514487
if (!actorIdReq.getSecondType()->isEqual(expectedActorIdTy)) {
515-
fprintf(stderr, "[%s:%d] (%s) if (!actorIdReq.getSecondType()->isEqual(expectedActorIdTy)) {\n", __FILE__, __LINE__, __FUNCTION__);
516488
return false;
517489
}
518490

519-
fprintf(stderr, "[%s:%d] (%s) OKEY!!!! %s.%s\n", __FILE__, __LINE__, __FUNCTION__, decl->getNameStr().str().c_str(), getNameStr().str().c_str());
520491
return true;
521492
}
522493

lib/Sema/TypeCheckDistributed.cpp

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ bool swift::checkDistributedActorSystemAdHocProtocolRequirements(
147147
// ==== ----------------------------------------------------------------------
148148
// Check the ad-hoc requirements of 'DistributedActorSystem":
149149
// - remoteCall
150+
// - remoteCallVoid
150151
if (Proto->isSpecificProtocol(KnownProtocolKind::DistributedActorSystem)) {
151152
auto systemProto = C.getProtocol(KnownProtocolKind::DistributedActorSystem);
152153

@@ -202,31 +203,39 @@ bool swift::checkDistributedActorSystemAdHocProtocolRequirements(
202203
}
203204

204205
// ==== ----------------------------------------------------------------------
205-
// Check the ad-hoc requirements of 'DistributedTargetInvocation'
206-
if (Proto->isSpecificProtocol(KnownProtocolKind::DistributedTargetInvocationDecoder)) {
207-
// FIXME(distributed): implement finding this the requirements here
208-
206+
// Check the ad-hoc requirements of 'DistributedTargetInvocationEncoder'
207+
// -
208+
if (Proto->isSpecificProtocol(KnownProtocolKind::DistributedTargetInvocationEncoder)) {
209+
// - recordArgument
209210
if (!C.getRecordArgumentOnDistributedInvocationEncoder(decl)) {
210211
decl->diagnose(
211212
diag::distributed_actor_system_conformance_missing_adhoc_requirement,
212213
decl->getDescriptiveKind(), decl->getName(), C.Id_recordArgument);
213-
// TODO: add note to add signature
214+
decl->diagnose(diag::note_distributed_actor_system_conformance_missing_adhoc_requirement,
215+
decl->getName(), C.Id_recordArgument,
216+
"mutating func recordArgument<Argument: SerializationRequirement>(_ argument: Argument) throws");
214217
anyMissingAdHocRequirements = true;
215218
}
216219

220+
// - recordErrorType
217221
if (!C.getRecordErrorTypeOnDistributedInvocationEncoder(decl)) {
218222
decl->diagnose(
219223
diag::distributed_actor_system_conformance_missing_adhoc_requirement,
220224
decl->getDescriptiveKind(), decl->getName(), C.Id_recordErrorType);
221-
// TODO: add note to add signature
225+
decl->diagnose(diag::note_distributed_actor_system_conformance_missing_adhoc_requirement,
226+
decl->getName(), C.Id_recordErrorType,
227+
"mutating func recordErrorType<Err: Error>(_ errorType: Err.Type) throws");
222228
anyMissingAdHocRequirements = true;
223229
}
224230

231+
// - recordReturnType
225232
if (!C.getRecordReturnTypeOnDistributedInvocationEncoder(decl)) {
226233
decl->diagnose(
227234
diag::distributed_actor_system_conformance_missing_adhoc_requirement,
228235
decl->getDescriptiveKind(), decl->getName(), C.Id_recordReturnType);
229-
// TODO: add note to add signature
236+
decl->diagnose(diag::note_distributed_actor_system_conformance_missing_adhoc_requirement,
237+
decl->getName(), C.Id_recordReturnType,
238+
"mutating func recordReturnType<Res: SerializationRequirement>(_ resultType: Res.Type) throws");
230239
anyMissingAdHocRequirements = true;
231240
}
232241

@@ -235,11 +244,17 @@ bool swift::checkDistributedActorSystemAdHocProtocolRequirements(
235244
}
236245

237246
// ==== ----------------------------------------------------------------------
238-
// Check the ad-hoc requirements of 'DistributedTargetInvocationArgumentDecoder'
239-
if (Proto->isSpecificProtocol(KnownProtocolKind::DistributedTargetInvocationResultHandler)) {
247+
// Check the ad-hoc requirements of 'DistributedTargetInvocationDecoder'
248+
// - decodeNextArgument
249+
if (Proto->isSpecificProtocol(KnownProtocolKind::DistributedTargetInvocationDecoder)) {
240250
// FIXME(distributed): implement finding this the requirements here
241-
//
242-
// return true;
251+
}
252+
253+
// === -----------------------------------------------------------------------
254+
// Check the ad-hoc requirements of 'DistributedTargetInvocationResultHandler'
255+
// - onReturn
256+
if (Proto->isSpecificProtocol(KnownProtocolKind::DistributedTargetInvocationResultHandler)) {
257+
243258
}
244259

245260
return false;

lib/Sema/TypeCheckProtocol.cpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5098,8 +5098,15 @@ void ConformanceChecker::resolveValueWitnesses() {
50985098
}
50995099
}
51005100

5101-
// Finally, check some ad-hoc protocol requirements
5102-
if (Proto->isSpecificProtocol(KnownProtocolKind::DistributedActorSystem)) {
5101+
// Finally, check some ad-hoc protocol requirements.
5102+
//
5103+
// These protocol requirements are not expressible in Swift today, but as
5104+
// the type system gains the required abilities, we should strive to move
5105+
// them to plain-old protocol requirements.
5106+
if (Proto->isSpecificProtocol(KnownProtocolKind::DistributedActorSystem) ||
5107+
Proto->isSpecificProtocol(KnownProtocolKind::DistributedTargetInvocationEncoder) ||
5108+
Proto->isSpecificProtocol(KnownProtocolKind::DistributedTargetInvocationDecoder) ||
5109+
Proto->isSpecificProtocol(KnownProtocolKind::DistributedTargetInvocationResultHandler)) {
51035110
checkDistributedActorSystemAdHocProtocolRequirements(
51045111
Context, Proto, Conformance, Adoptee, /*diagnose=*/true);
51055112
}

stdlib/public/Distributed/DistributedActorSystem.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -451,6 +451,7 @@ public protocol DistributedTargetInvocationResultHandler {
451451

452452
// FIXME(distributed): these must be ad-hoc protocol requirements, because Res: SerializationRequirement !!!
453453
func onReturn<Res>(value: Res) async throws
454+
// FIXME: onReturnVoid
454455
func onThrow<Err: Error>(error: Err) async throws
455456
}
456457

test/Distributed/distributed_actor_system_missing_adhoc_requirement_impls.swift

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -481,6 +481,42 @@ public struct PublicFakeInvocationEncoder: DistributedTargetInvocationEncoder {
481481
public mutating func doneRecording() throws {}
482482
}
483483

484+
struct FakeInvocationEncoder_missing_recordArgument: DistributedTargetInvocationEncoder {
485+
//expected-error@-1{{struct 'FakeInvocationEncoder_missing_recordArgument' is missing witness for protocol requirement 'recordArgument'}}
486+
//expected-note@-2{{protocol 'FakeInvocationEncoder_missing_recordArgument' requires function 'recordArgument' with signature:}}
487+
typealias SerializationRequirement = Codable
488+
489+
mutating func recordGenericSubstitution<T>(_ type: T.Type) throws {}
490+
// MISSING: mutating func recordArgument<Argument: SerializationRequirement>(_ argument: Argument) throws {}
491+
mutating func recordReturnType<R: SerializationRequirement>(_ type: R.Type) throws {}
492+
mutating func recordErrorType<E: Error>(_ type: E.Type) throws {}
493+
mutating func doneRecording() throws {}
494+
}
495+
496+
struct FakeInvocationEncoder_missing_recordReturnType: DistributedTargetInvocationEncoder {
497+
//expected-error@-1{{struct 'FakeInvocationEncoder_missing_recordReturnType' is missing witness for protocol requirement 'recordReturnType'}}
498+
//expected-note@-2{{protocol 'FakeInvocationEncoder_missing_recordReturnType' requires function 'recordReturnType' with signature:}}
499+
typealias SerializationRequirement = Codable
500+
501+
mutating func recordGenericSubstitution<T>(_ type: T.Type) throws {}
502+
mutating func recordArgument<Argument: SerializationRequirement>(_ argument: Argument) throws {}
503+
// MISSING: mutating func recordReturnType<R: SerializationRequirement>(_ type: R.Type) throws {}
504+
mutating func recordErrorType<E: Error>(_ type: E.Type) throws {}
505+
mutating func doneRecording() throws {}
506+
}
507+
508+
struct FakeInvocationEncoder_missing_recordErrorType: DistributedTargetInvocationEncoder {
509+
//expected-error@-1{{struct 'FakeInvocationEncoder_missing_recordErrorType' is missing witness for protocol requirement 'recordErrorType'}}
510+
//expected-note@-2{{protocol 'FakeInvocationEncoder_missing_recordErrorType' requires function 'recordErrorType' with signature:}}
511+
typealias SerializationRequirement = Codable
512+
513+
mutating func recordGenericSubstitution<T>(_ type: T.Type) throws {}
514+
mutating func recordArgument<Argument: SerializationRequirement>(_ argument: Argument) throws {}
515+
mutating func recordReturnType<R: SerializationRequirement>(_ type: R.Type) throws {}
516+
// MISSING: mutating func recordErrorType<E: Error>(_ type: E.Type) throws {}
517+
mutating func doneRecording() throws {}
518+
}
519+
484520
class FakeInvocationDecoder: DistributedTargetInvocationDecoder {
485521
typealias SerializationRequirement = Codable
486522

0 commit comments

Comments
 (0)