@@ -3575,15 +3575,23 @@ SILGenFunction::emitVTableThunk(SILDeclRef derived,
35753575enum class WitnessDispatchKind {
35763576 Static,
35773577 Dynamic,
3578- Class
3578+ Class,
3579+ Witness
35793580};
35803581
3581- static WitnessDispatchKind getWitnessDispatchKind (SILDeclRef witness) {
3582+ static WitnessDispatchKind getWitnessDispatchKind (SILDeclRef witness,
3583+ bool isSelfConformance) {
35823584 auto *decl = witness.getDecl ();
35833585
3586+ if (isSelfConformance) {
3587+ assert (isa<ProtocolDecl>(decl->getDeclContext ()));
3588+ return WitnessDispatchKind::Witness;
3589+ }
3590+
35843591 ClassDecl *C = decl->getDeclContext ()->getSelfClassDecl ();
3585- if (!C)
3592+ if (!C) {
35863593 return WitnessDispatchKind::Static;
3594+ }
35873595
35883596 // If the witness is dynamic, go through dynamic dispatch.
35893597 if (decl->isObjCDynamic ()) {
@@ -3630,6 +3638,7 @@ getWitnessFunctionType(SILGenModule &SGM,
36303638 switch (witnessKind) {
36313639 case WitnessDispatchKind::Static:
36323640 case WitnessDispatchKind::Dynamic:
3641+ case WitnessDispatchKind::Witness:
36333642 return SGM.Types .getConstantInfo (witness).SILFnType ;
36343643 case WitnessDispatchKind::Class:
36353644 return SGM.Types .getConstantOverrideType (witness);
@@ -3638,18 +3647,36 @@ getWitnessFunctionType(SILGenModule &SGM,
36383647 llvm_unreachable (" Unhandled WitnessDispatchKind in switch." );
36393648}
36403649
3650+ static std::pair<CanType, ProtocolConformanceRef>
3651+ getSelfTypeAndConformanceForWitness (SILDeclRef witness, SubstitutionMap subs) {
3652+ auto protocol = cast<ProtocolDecl>(witness.getDecl ()->getDeclContext ());
3653+ auto selfParam = protocol->getProtocolSelfType ()->getCanonicalType ();
3654+ auto type = subs.getReplacementTypes ()[0 ];
3655+ auto conf = *subs.lookupConformance (selfParam, protocol);
3656+ return {type->getCanonicalType (), conf};
3657+ }
3658+
36413659static SILValue
36423660getWitnessFunctionRef (SILGenFunction &SGF,
36433661 SILDeclRef witness,
36443662 CanSILFunctionType witnessFTy,
36453663 WitnessDispatchKind witnessKind,
3664+ SubstitutionMap witnessSubs,
36463665 SmallVectorImpl<ManagedValue> &witnessParams,
36473666 SILLocation loc) {
36483667 switch (witnessKind) {
36493668 case WitnessDispatchKind::Static:
36503669 return SGF.emitGlobalFunctionRef (loc, witness);
36513670 case WitnessDispatchKind::Dynamic:
36523671 return SGF.emitDynamicMethodRef (loc, witness, witnessFTy).getValue ();
3672+ case WitnessDispatchKind::Witness: {
3673+ auto typeAndConf =
3674+ getSelfTypeAndConformanceForWitness (witness, witnessSubs);
3675+ return SGF.B .createWitnessMethod (loc, typeAndConf.first ,
3676+ typeAndConf.second ,
3677+ witness,
3678+ SILType::getPrimitiveObjectType (witnessFTy));
3679+ }
36533680 case WitnessDispatchKind::Class: {
36543681 SILValue selfPtr = witnessParams.back ().getValue ();
36553682 return SGF.emitClassMethodRef (loc, selfPtr, witness, witnessFTy);
@@ -3659,13 +3686,32 @@ getWitnessFunctionRef(SILGenFunction &SGF,
36593686 llvm_unreachable (" Unhandled WitnessDispatchKind in switch." );
36603687}
36613688
3689+ static ManagedValue
3690+ emitOpenExistentialInSelfConformance (SILGenFunction &SGF, SILLocation loc,
3691+ SILDeclRef witness,
3692+ SubstitutionMap subs, ManagedValue value,
3693+ SILParameterInfo destParameter) {
3694+ auto typeAndConf = getSelfTypeAndConformanceForWitness (witness, subs);
3695+ auto archetype = typeAndConf.first ->castTo <ArchetypeType>();
3696+ assert (archetype->isOpenedExistential ());
3697+
3698+ auto openedTy = destParameter.getSILStorageType ();
3699+ auto state = SGF.emitOpenExistential (loc, value, archetype, openedTy,
3700+ destParameter.isIndirectMutating ()
3701+ ? AccessKind::ReadWrite
3702+ : AccessKind::Read);
3703+
3704+ return state.Value ;
3705+ }
3706+
36623707void SILGenFunction::emitProtocolWitness (AbstractionPattern reqtOrigTy,
36633708 CanAnyFunctionType reqtSubstTy,
36643709 SILDeclRef requirement,
36653710 SubstitutionMap reqtSubs,
36663711 SILDeclRef witness,
36673712 SubstitutionMap witnessSubs,
3668- IsFreeFunctionWitness_t isFree) {
3713+ IsFreeFunctionWitness_t isFree,
3714+ bool isSelfConformance) {
36693715 // FIXME: Disable checks that the protocol witness carries debug info.
36703716 // Should we carry debug info for witnesses?
36713717 F.setBare (IsBare);
@@ -3679,7 +3725,7 @@ void SILGenFunction::emitProtocolWitness(AbstractionPattern reqtOrigTy,
36793725 FullExpr scope (Cleanups, cleanupLoc);
36803726 FormalEvaluationScope formalEvalScope (*this );
36813727
3682- auto witnessKind = getWitnessDispatchKind (witness);
3728+ auto witnessKind = getWitnessDispatchKind (witness, isSelfConformance );
36833729 auto thunkTy = F.getLoweredFunctionType ();
36843730
36853731 SmallVector<ManagedValue, 8 > origParams;
@@ -3704,9 +3750,24 @@ void SILGenFunction::emitProtocolWitness(AbstractionPattern reqtOrigTy,
37043750 ->getCanonicalType ());
37053751 }
37063752
3753+ // Get the lowered type of the witness.
3754+ auto origWitnessFTy = getWitnessFunctionType (SGM, witness, witnessKind);
3755+ auto witnessFTy = origWitnessFTy;
3756+ if (!witnessSubs.empty ())
3757+ witnessFTy = origWitnessFTy->substGenericArgs (SGM.M , witnessSubs);
3758+
37073759 auto reqtSubstParams = reqtSubstTy.getParams ();
37083760 auto witnessSubstParams = witnessSubstTy.getParams ();
37093761
3762+ // For a self-conformance, open the self parameter.
3763+ if (isSelfConformance) {
3764+ assert (!isFree && " shouldn't have a free witness for a self-conformance" );
3765+ origParams.back () =
3766+ emitOpenExistentialInSelfConformance (*this , loc, witness, witnessSubs,
3767+ origParams.back (),
3768+ witnessFTy->getSelfParameter ());
3769+ }
3770+
37103771 // For a free function witness, discard the 'self' parameter of the
37113772 // requirement.
37123773 if (isFree) {
@@ -3716,11 +3777,6 @@ void SILGenFunction::emitProtocolWitness(AbstractionPattern reqtOrigTy,
37163777
37173778 // Translate the argument values from the requirement abstraction level to
37183779 // the substituted signature of the witness.
3719- auto origWitnessFTy = getWitnessFunctionType (SGM, witness, witnessKind);
3720- auto witnessFTy = origWitnessFTy;
3721- if (!witnessSubs.empty ())
3722- witnessFTy = origWitnessFTy->substGenericArgs (SGM.M , witnessSubs);
3723-
37243780 SmallVector<ManagedValue, 8 > witnessParams;
37253781 AbstractionPattern witnessOrigTy (witnessInfo.LoweredType );
37263782 TranslateArguments (*this , loc,
@@ -3733,7 +3789,7 @@ void SILGenFunction::emitProtocolWitness(AbstractionPattern reqtOrigTy,
37333789
37343790 SILValue witnessFnRef = getWitnessFunctionRef (*this , witness,
37353791 origWitnessFTy,
3736- witnessKind,
3792+ witnessKind, witnessSubs,
37373793 witnessParams, loc);
37383794
37393795 auto coroutineKind =
0 commit comments