@@ -3574,15 +3574,23 @@ SILGenFunction::emitVTableThunk(SILDeclRef derived,
35743574enum class WitnessDispatchKind {
35753575 Static,
35763576 Dynamic,
3577- Class
3577+ Class,
3578+ Witness
35783579};
35793580
3580- static WitnessDispatchKind getWitnessDispatchKind (SILDeclRef witness) {
3581+ static WitnessDispatchKind getWitnessDispatchKind (SILDeclRef witness,
3582+ bool isSelfConformance) {
35813583 auto *decl = witness.getDecl ();
35823584
3585+ if (isSelfConformance) {
3586+ assert (isa<ProtocolDecl>(decl->getDeclContext ()));
3587+ return WitnessDispatchKind::Witness;
3588+ }
3589+
35833590 ClassDecl *C = decl->getDeclContext ()->getSelfClassDecl ();
3584- if (!C)
3591+ if (!C) {
35853592 return WitnessDispatchKind::Static;
3593+ }
35863594
35873595 // If the witness is dynamic, go through dynamic dispatch.
35883596 if (decl->isObjCDynamic ()) {
@@ -3629,6 +3637,7 @@ getWitnessFunctionType(SILGenModule &SGM,
36293637 switch (witnessKind) {
36303638 case WitnessDispatchKind::Static:
36313639 case WitnessDispatchKind::Dynamic:
3640+ case WitnessDispatchKind::Witness:
36323641 return SGM.Types .getConstantInfo (witness).SILFnType ;
36333642 case WitnessDispatchKind::Class:
36343643 return SGM.Types .getConstantOverrideType (witness);
@@ -3637,18 +3646,36 @@ getWitnessFunctionType(SILGenModule &SGM,
36373646 llvm_unreachable (" Unhandled WitnessDispatchKind in switch." );
36383647}
36393648
3649+ static std::pair<CanType, ProtocolConformanceRef>
3650+ getSelfTypeAndConformanceForWitness (SILDeclRef witness, SubstitutionMap subs) {
3651+ auto protocol = cast<ProtocolDecl>(witness.getDecl ()->getDeclContext ());
3652+ auto selfParam = protocol->getProtocolSelfType ()->getCanonicalType ();
3653+ auto type = subs.getReplacementTypes ()[0 ];
3654+ auto conf = *subs.lookupConformance (selfParam, protocol);
3655+ return {type->getCanonicalType (), conf};
3656+ }
3657+
36403658static SILValue
36413659getWitnessFunctionRef (SILGenFunction &SGF,
36423660 SILDeclRef witness,
36433661 CanSILFunctionType witnessFTy,
36443662 WitnessDispatchKind witnessKind,
3663+ SubstitutionMap witnessSubs,
36453664 SmallVectorImpl<ManagedValue> &witnessParams,
36463665 SILLocation loc) {
36473666 switch (witnessKind) {
36483667 case WitnessDispatchKind::Static:
36493668 return SGF.emitGlobalFunctionRef (loc, witness);
36503669 case WitnessDispatchKind::Dynamic:
36513670 return SGF.emitDynamicMethodRef (loc, witness, witnessFTy).getValue ();
3671+ case WitnessDispatchKind::Witness: {
3672+ auto typeAndConf =
3673+ getSelfTypeAndConformanceForWitness (witness, witnessSubs);
3674+ return SGF.B .createWitnessMethod (loc, typeAndConf.first ,
3675+ typeAndConf.second ,
3676+ witness,
3677+ SILType::getPrimitiveObjectType (witnessFTy));
3678+ }
36523679 case WitnessDispatchKind::Class: {
36533680 SILValue selfPtr = witnessParams.back ().getValue ();
36543681 return SGF.emitClassMethodRef (loc, selfPtr, witness, witnessFTy);
@@ -3658,13 +3685,32 @@ getWitnessFunctionRef(SILGenFunction &SGF,
36583685 llvm_unreachable (" Unhandled WitnessDispatchKind in switch." );
36593686}
36603687
3688+ static ManagedValue
3689+ emitOpenExistentialInSelfConformance (SILGenFunction &SGF, SILLocation loc,
3690+ SILDeclRef witness,
3691+ SubstitutionMap subs, ManagedValue value,
3692+ SILParameterInfo destParameter) {
3693+ auto typeAndConf = getSelfTypeAndConformanceForWitness (witness, subs);
3694+ auto archetype = typeAndConf.first ->castTo <ArchetypeType>();
3695+ assert (archetype->isOpenedExistential ());
3696+
3697+ auto openedTy = destParameter.getSILStorageType ();
3698+ auto state = SGF.emitOpenExistential (loc, value, archetype, openedTy,
3699+ destParameter.isIndirectMutating ()
3700+ ? AccessKind::ReadWrite
3701+ : AccessKind::Read);
3702+
3703+ return state.Value ;
3704+ }
3705+
36613706void SILGenFunction::emitProtocolWitness (AbstractionPattern reqtOrigTy,
36623707 CanAnyFunctionType reqtSubstTy,
36633708 SILDeclRef requirement,
36643709 SubstitutionMap reqtSubs,
36653710 SILDeclRef witness,
36663711 SubstitutionMap witnessSubs,
3667- IsFreeFunctionWitness_t isFree) {
3712+ IsFreeFunctionWitness_t isFree,
3713+ bool isSelfConformance) {
36683714 // FIXME: Disable checks that the protocol witness carries debug info.
36693715 // Should we carry debug info for witnesses?
36703716 F.setBare (IsBare);
@@ -3678,7 +3724,7 @@ void SILGenFunction::emitProtocolWitness(AbstractionPattern reqtOrigTy,
36783724 FullExpr scope (Cleanups, cleanupLoc);
36793725 FormalEvaluationScope formalEvalScope (*this );
36803726
3681- auto witnessKind = getWitnessDispatchKind (witness);
3727+ auto witnessKind = getWitnessDispatchKind (witness, isSelfConformance );
36823728 auto thunkTy = F.getLoweredFunctionType ();
36833729
36843730 SmallVector<ManagedValue, 8 > origParams;
@@ -3703,9 +3749,24 @@ void SILGenFunction::emitProtocolWitness(AbstractionPattern reqtOrigTy,
37033749 ->getCanonicalType ());
37043750 }
37053751
3752+ // Get the lowered type of the witness.
3753+ auto origWitnessFTy = getWitnessFunctionType (SGM, witness, witnessKind);
3754+ auto witnessFTy = origWitnessFTy;
3755+ if (!witnessSubs.empty ())
3756+ witnessFTy = origWitnessFTy->substGenericArgs (SGM.M , witnessSubs);
3757+
37063758 auto reqtSubstParams = reqtSubstTy.getParams ();
37073759 auto witnessSubstParams = witnessSubstTy.getParams ();
37083760
3761+ // For a self-conformance, open the self parameter.
3762+ if (isSelfConformance) {
3763+ assert (!isFree && " shouldn't have a free witness for a self-conformance" );
3764+ origParams.back () =
3765+ emitOpenExistentialInSelfConformance (*this , loc, witness, witnessSubs,
3766+ origParams.back (),
3767+ witnessFTy->getSelfParameter ());
3768+ }
3769+
37093770 // For a free function witness, discard the 'self' parameter of the
37103771 // requirement.
37113772 if (isFree) {
@@ -3715,11 +3776,6 @@ void SILGenFunction::emitProtocolWitness(AbstractionPattern reqtOrigTy,
37153776
37163777 // Translate the argument values from the requirement abstraction level to
37173778 // the substituted signature of the witness.
3718- auto origWitnessFTy = getWitnessFunctionType (SGM, witness, witnessKind);
3719- auto witnessFTy = origWitnessFTy;
3720- if (!witnessSubs.empty ())
3721- witnessFTy = origWitnessFTy->substGenericArgs (SGM.M , witnessSubs);
3722-
37233779 SmallVector<ManagedValue, 8 > witnessParams;
37243780 AbstractionPattern witnessOrigTy (witnessInfo.LoweredType );
37253781 TranslateArguments (*this , loc,
@@ -3732,7 +3788,7 @@ void SILGenFunction::emitProtocolWitness(AbstractionPattern reqtOrigTy,
37323788
37333789 SILValue witnessFnRef = getWitnessFunctionRef (*this , witness,
37343790 origWitnessFTy,
3735- witnessKind,
3791+ witnessKind, witnessSubs,
37363792 witnessParams, loc);
37373793
37383794 auto coroutineKind =
0 commit comments