@@ -472,26 +472,66 @@ GetDistributedActorArgumentDecodingMethodRequest::evaluate(Evaluator &evaluator,
472
472
auto members = TypeChecker::lookupMember (actor->getDeclContext (), decoderTy,
473
473
DeclNameRef (ctx.Id_decodeNextArgument ));
474
474
475
+ // typealias SerializationRequirement = any ...
476
+ auto serializerType = getAssociatedTypeOfDistributedSystem (
477
+ actor, ctx.Id_SerializationRequirement )
478
+ ->castTo <ExistentialType>()
479
+ ->getConstraintType ()
480
+ ->getDesugaredType ();
481
+
482
+ llvm::SmallPtrSet<ProtocolDecl *, 2 > serializationReqs;
483
+ if (auto composition = serializerType->getAs <ProtocolCompositionType>()) {
484
+ for (auto member : composition->getMembers ()) {
485
+ if (auto *protocol = member->getAs <ProtocolType>())
486
+ serializationReqs.insert (protocol->getDecl ());
487
+ }
488
+ } else {
489
+ auto protocol = serializerType->castTo <ProtocolType>()->getDecl ();
490
+ serializationReqs.insert (protocol);
491
+ }
492
+
475
493
SmallVector<FuncDecl *, 2 > candidates;
476
- // Looking for `decodeNextArgument<Arg>() throws -> Arg`
494
+ // Looking for `decodeNextArgument<Arg: <SerializationReq> >() throws -> Arg`
477
495
for (auto &member : members) {
478
496
auto *FD = dyn_cast<FuncDecl>(member.getValueDecl ());
479
497
if (!FD || FD->hasAsync () || !FD->hasThrows ())
480
498
continue ;
481
499
482
500
auto *params = FD->getParameters ();
501
+ // No arguemnts.
483
502
if (params->size () != 0 )
484
503
continue ;
485
504
486
505
auto genericParamList = FD->getGenericParams ();
487
- if (genericParamList->size () == 1 ) {
488
- auto paramTy = genericParamList->getParams ()[0 ]
489
- ->getInterfaceType ()
490
- ->getMetatypeInstanceType ();
506
+ // A single generic parameter.
507
+ if (genericParamList->size () != 1 )
508
+ continue ;
491
509
492
- if (FD->getResultInterfaceType ()->isEqual (paramTy))
493
- candidates.push_back (FD);
494
- }
510
+ auto paramTy = genericParamList->getParams ()[0 ]
511
+ ->getInterfaceType ()
512
+ ->getMetatypeInstanceType ();
513
+
514
+ // `decodeNextArgument` should return its generic parameter value
515
+ if (!FD->getResultInterfaceType ()->isEqual (paramTy))
516
+ continue ;
517
+
518
+ // Let's find out how many serialization requirements does this method cover
519
+ // e.g. `Codable` is two requirements - `Encodable` and `Decodable`.
520
+ unsigned numSerializationReqsCovered = llvm::count_if (
521
+ FD->getGenericRequirements (), [&](const Requirement &requirement) {
522
+ if (!(requirement.getFirstType ()->isEqual (paramTy) &&
523
+ requirement.getKind () == RequirementKind::Conformance))
524
+ return 0 ;
525
+
526
+ return serializationReqs.count (requirement.getProtocolDecl ()) ? 1 : 0 ;
527
+ });
528
+
529
+ // If the current method covers all of the serialization requirements,
530
+ // it's a match. Note that it might also have other requirements, but
531
+ // we let that go as long as there are no two candidates that differ
532
+ // only in generic requirements.
533
+ if (numSerializationReqsCovered == serializationReqs.size ())
534
+ candidates.push_back (FD);
495
535
}
496
536
497
537
// Type-checker should reject any definition of invocation decoder
0 commit comments