@@ -3574,15 +3574,23 @@ SILGenFunction::emitVTableThunk(SILDeclRef derived,
3574
3574
enum class WitnessDispatchKind {
3575
3575
Static,
3576
3576
Dynamic,
3577
- Class
3577
+ Class,
3578
+ Witness
3578
3579
};
3579
3580
3580
- static WitnessDispatchKind getWitnessDispatchKind (SILDeclRef witness) {
3581
+ static WitnessDispatchKind getWitnessDispatchKind (SILDeclRef witness,
3582
+ bool isSelfConformance) {
3581
3583
auto *decl = witness.getDecl ();
3582
3584
3585
+ if (isSelfConformance) {
3586
+ assert (isa<ProtocolDecl>(decl->getDeclContext ()));
3587
+ return WitnessDispatchKind::Witness;
3588
+ }
3589
+
3583
3590
ClassDecl *C = decl->getDeclContext ()->getSelfClassDecl ();
3584
- if (!C)
3591
+ if (!C) {
3585
3592
return WitnessDispatchKind::Static;
3593
+ }
3586
3594
3587
3595
// If the witness is dynamic, go through dynamic dispatch.
3588
3596
if (decl->isObjCDynamic ()) {
@@ -3629,6 +3637,7 @@ getWitnessFunctionType(SILGenModule &SGM,
3629
3637
switch (witnessKind) {
3630
3638
case WitnessDispatchKind::Static:
3631
3639
case WitnessDispatchKind::Dynamic:
3640
+ case WitnessDispatchKind::Witness:
3632
3641
return SGM.Types .getConstantInfo (witness).SILFnType ;
3633
3642
case WitnessDispatchKind::Class:
3634
3643
return SGM.Types .getConstantOverrideType (witness);
@@ -3637,18 +3646,36 @@ getWitnessFunctionType(SILGenModule &SGM,
3637
3646
llvm_unreachable (" Unhandled WitnessDispatchKind in switch." );
3638
3647
}
3639
3648
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
+
3640
3658
static SILValue
3641
3659
getWitnessFunctionRef (SILGenFunction &SGF,
3642
3660
SILDeclRef witness,
3643
3661
CanSILFunctionType witnessFTy,
3644
3662
WitnessDispatchKind witnessKind,
3663
+ SubstitutionMap witnessSubs,
3645
3664
SmallVectorImpl<ManagedValue> &witnessParams,
3646
3665
SILLocation loc) {
3647
3666
switch (witnessKind) {
3648
3667
case WitnessDispatchKind::Static:
3649
3668
return SGF.emitGlobalFunctionRef (loc, witness);
3650
3669
case WitnessDispatchKind::Dynamic:
3651
3670
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
+ }
3652
3679
case WitnessDispatchKind::Class: {
3653
3680
SILValue selfPtr = witnessParams.back ().getValue ();
3654
3681
return SGF.emitClassMethodRef (loc, selfPtr, witness, witnessFTy);
@@ -3658,13 +3685,32 @@ getWitnessFunctionRef(SILGenFunction &SGF,
3658
3685
llvm_unreachable (" Unhandled WitnessDispatchKind in switch." );
3659
3686
}
3660
3687
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
+
3661
3706
void SILGenFunction::emitProtocolWitness (AbstractionPattern reqtOrigTy,
3662
3707
CanAnyFunctionType reqtSubstTy,
3663
3708
SILDeclRef requirement,
3664
3709
SubstitutionMap reqtSubs,
3665
3710
SILDeclRef witness,
3666
3711
SubstitutionMap witnessSubs,
3667
- IsFreeFunctionWitness_t isFree) {
3712
+ IsFreeFunctionWitness_t isFree,
3713
+ bool isSelfConformance) {
3668
3714
// FIXME: Disable checks that the protocol witness carries debug info.
3669
3715
// Should we carry debug info for witnesses?
3670
3716
F.setBare (IsBare);
@@ -3678,7 +3724,7 @@ void SILGenFunction::emitProtocolWitness(AbstractionPattern reqtOrigTy,
3678
3724
FullExpr scope (Cleanups, cleanupLoc);
3679
3725
FormalEvaluationScope formalEvalScope (*this );
3680
3726
3681
- auto witnessKind = getWitnessDispatchKind (witness);
3727
+ auto witnessKind = getWitnessDispatchKind (witness, isSelfConformance );
3682
3728
auto thunkTy = F.getLoweredFunctionType ();
3683
3729
3684
3730
SmallVector<ManagedValue, 8 > origParams;
@@ -3703,9 +3749,24 @@ void SILGenFunction::emitProtocolWitness(AbstractionPattern reqtOrigTy,
3703
3749
->getCanonicalType ());
3704
3750
}
3705
3751
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
+
3706
3758
auto reqtSubstParams = reqtSubstTy.getParams ();
3707
3759
auto witnessSubstParams = witnessSubstTy.getParams ();
3708
3760
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
+
3709
3770
// For a free function witness, discard the 'self' parameter of the
3710
3771
// requirement.
3711
3772
if (isFree) {
@@ -3715,11 +3776,6 @@ void SILGenFunction::emitProtocolWitness(AbstractionPattern reqtOrigTy,
3715
3776
3716
3777
// Translate the argument values from the requirement abstraction level to
3717
3778
// 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
-
3723
3779
SmallVector<ManagedValue, 8 > witnessParams;
3724
3780
AbstractionPattern witnessOrigTy (witnessInfo.LoweredType );
3725
3781
TranslateArguments (*this , loc,
@@ -3732,7 +3788,7 @@ void SILGenFunction::emitProtocolWitness(AbstractionPattern reqtOrigTy,
3732
3788
3733
3789
SILValue witnessFnRef = getWitnessFunctionRef (*this , witness,
3734
3790
origWitnessFTy,
3735
- witnessKind,
3791
+ witnessKind, witnessSubs,
3736
3792
witnessParams, loc);
3737
3793
3738
3794
auto coroutineKind =
0 commit comments