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