@@ -81,44 +81,48 @@ struct ArgumentDecoderInfo {
8181 // / The type of `decodeNextArgument` method.
8282 CanSILFunctionType MethodType;
8383
84- // / Protocol requirements associated with the generic
85- // / parameter `Argument` of this decode method.
86- GenericSignature::RequiredProtocols ProtocolRequirements;
87-
88- // Witness metadata for conformance to DistributedTargetInvocationDecoder
89- // protocol.
84+ // / Witness metadata for conformance to DistributedTargetInvocationDecoder
85+ // / protocol.
9086 WitnessMetadata Witness;
9187
88+ // / Indicates whether `decodeNextArgument` is referenced through
89+ // / a protocol witness thunk.
90+ bool UsesWitnessDispatch;
91+
9292 ArgumentDecoderInfo (llvm::Value *decoder, llvm::Value *decoderType,
9393 llvm::Value *decoderWitnessTable,
9494 FunctionPointer decodeNextArgumentPtr,
95- CanSILFunctionType decodeNextArgumentTy)
95+ CanSILFunctionType decodeNextArgumentTy,
96+ bool usesWitnessDispatch)
9697 : Decoder(decoder), MethodPtr(decodeNextArgumentPtr),
9798 MethodType (decodeNextArgumentTy),
98- ProtocolRequirements(findProtocolRequirements(decodeNextArgumentTy) ) {
99+ UsesWitnessDispatch(usesWitnessDispatch ) {
99100 Witness.SelfMetadata = decoderType;
100101 Witness.SelfWitnessTable = decoderWitnessTable;
101102 }
102103
103104 CanSILFunctionType getMethodType () const { return MethodType; }
104105
105- ArrayRef<ProtocolDecl *> getProtocolRequirements () const {
106- return ProtocolRequirements ;
106+ WitnessMetadata * getWitnessMetadata () const {
107+ return const_cast <WitnessMetadata *>(&Witness) ;
107108 }
108109
109- // / Form a callee to a decode method - `decodeNextArgument`.
110- Callee getCallee () const ;
110+ // / Protocol requirements associated with the generic
111+ // / parameter `Argument` of this decode method.
112+ GenericSignature::RequiredProtocols getProtocolRequirements () const {
113+ if (UsesWitnessDispatch)
114+ return {};
111115
112- private:
113- static GenericSignature::RequiredProtocols
114- findProtocolRequirements (CanSILFunctionType decodeMethodTy) {
115- auto signature = decodeMethodTy->getInvocationGenericSignature ();
116+ auto signature = MethodType->getInvocationGenericSignature ();
116117 auto genericParams = signature.getGenericParams ();
117118
118119 // func decodeNextArgument<Arg : #SerializationRequirement#>() throws -> Arg
119120 assert (genericParams.size () == 1 );
120121 return signature->getRequiredProtocols (genericParams.front ());
121122 }
123+
124+ // / Form a callee to a decode method - `decodeNextArgument`.
125+ Callee getCallee () const ;
122126};
123127
124128class DistributedAccessor {
@@ -415,7 +419,8 @@ void DistributedAccessor::decodeArgument(unsigned argumentIdx,
415419 emission->begin ();
416420 {
417421 emission->setArgs (decodeArgs, /* isOutlined=*/ false ,
418- /* witnessMetadata=*/ nullptr );
422+ decoder.UsesWitnessDispatch ? decoder.getWitnessMetadata ()
423+ : nullptr );
419424
420425 Explosion result;
421426 emission->emitToExplosion (result, /* isOutlined=*/ false );
@@ -519,6 +524,9 @@ void DistributedAccessor::decodeArgument(unsigned argumentIdx,
519524void DistributedAccessor::lookupWitnessTables (
520525 llvm::Value *value, ArrayRef<ProtocolDecl *> protocols,
521526 Explosion &witnessTables) {
527+ if (protocols.empty ())
528+ return ;
529+
522530 auto conformsToProtocol = IGM.getConformsToProtocolFunctionPointer ();
523531
524532 for (auto *protocol : protocols) {
@@ -785,11 +793,32 @@ DistributedAccessor::getCalleeForDistributedTarget(llvm::Value *self) const {
785793
786794ArgumentDecoderInfo DistributedAccessor::findArgumentDecoder (
787795 llvm::Value *decoder, llvm::Value *decoderTy, llvm::Value *witnessTable) {
796+ auto &C = IGM.Context ;
788797 auto *actor = getDistributedActorOf (Target);
789798 auto expansionContext = IGM.getMaximalTypeExpansionContext ();
790799
791- auto *decodeFn = IGM.Context .getDistributedActorArgumentDecodingMethod (actor);
792- assert (decodeFn && " no suitable decoder?" );
800+ auto *decodeFn = C.getDistributedActorArgumentDecodingMethod (actor);
801+
802+ // If distributed actor is generic over actor system, we have to
803+ // use witness to reference `decodeNextArgument`.
804+ if (!decodeFn) {
805+ auto decoderProtocol = C.getDistributedTargetInvocationDecoderDecl ();
806+ auto decodeNextArgRequirement =
807+ decoderProtocol->getSingleRequirement (C.Id_decodeNextArgument );
808+ assert (decodeNextArgRequirement);
809+ SILDeclRef decodeNextArgumentRef (decodeNextArgRequirement);
810+
811+ llvm::Constant *fnPtr =
812+ IGM.getAddrOfDispatchThunk (decodeNextArgumentRef, NotForDefinition);
813+ auto fnType = IGM.getSILTypes ().getConstantFunctionType (
814+ IGM.getMaximalTypeExpansionContext (), decodeNextArgumentRef);
815+
816+ auto sig = IGM.getSignature (fnType);
817+ auto fn = FunctionPointer::forDirect (fnType, fnPtr,
818+ /* secondaryValue=*/ nullptr , sig, true );
819+ return {decoder, decoderTy, witnessTable,
820+ fn, fnType, /* usesWitnessDispatch=*/ true };
821+ }
793822
794823 auto methodTy = IGM.getSILTypes ().getConstantFunctionType (
795824 expansionContext, SILDeclRef (decodeFn));
@@ -848,7 +877,8 @@ ArgumentDecoderInfo DistributedAccessor::findArgumentDecoder(
848877 /* secondaryValue=*/ nullptr , signature);
849878 }
850879
851- return {decoder, decoderTy, witnessTable, methodPtr, methodTy};
880+ return {decoder, decoderTy, witnessTable,
881+ methodPtr, methodTy, /* usesWitnessDispatch=*/ false };
852882}
853883
854884SILType DistributedAccessor::getResultType () const {
0 commit comments