@@ -712,7 +712,8 @@ DevirtualizationResult swift::tryDevirtualizeClassMethod(FullApplySite AI,
712
712
// ===----------------------------------------------------------------------===//
713
713
714
714
static SubstitutionMap
715
- getSubstitutionsForProtocolConformance (ProtocolConformanceRef CRef) {
715
+ getSubstitutionsForProtocolConformance (ModuleDecl *M,
716
+ ProtocolConformanceRef CRef) {
716
717
auto C = CRef.getConcrete ();
717
718
718
719
// Walk down to the base NormalProtocolConformance.
@@ -746,8 +747,7 @@ getSubstitutionsForProtocolConformance(ProtocolConformanceRef CRef) {
746
747
747
748
if (Subs.empty ()) {
748
749
auto *DC = NormalC->getDeclContext ();
749
- return NormalC->getType ()
750
- ->getContextSubstitutionMap (DC->getParentModule (), DC);
750
+ return NormalC->getType ()->getContextSubstitutionMap (M, DC);
751
751
}
752
752
753
753
return NormalC->getGenericSignature ()->getSubstitutionMap (Subs);
@@ -764,17 +764,50 @@ getSubstitutionsForProtocolConformance(ProtocolConformanceRef CRef) {
764
764
// / are written in terms of the requirement's generic signature need
765
765
// / to be remapped to substitutions suitable for the witness signature.
766
766
// /
767
+ // / Supported remappings are:
768
+ // /
769
+ // / - (Concrete witness thunk) Original substitutions:
770
+ // / [Self := ConcreteType, R0 := X0, R1 := X1, ...]
771
+ // / - Requirement generic signature:
772
+ // / <Self : P, R0, R1, ...>
773
+ // / - Witness thunk generic signature:
774
+ // / <W0, W1, ...>
775
+ // / - Remapped substitutions:
776
+ // / [W0 := X0, W1 := X1, ...]
777
+ // /
778
+ // / - (Class witness thunk) Original substitutions:
779
+ // / [Self := C<A0, A1>, T0 := X0, T1 := X1, ...]
780
+ // / - Requirement generic signature:
781
+ // / <Self : P, R0, R1, ...>
782
+ // / - Witness thunk generic signature:
783
+ // / <Self : C<B0, B1>, B0, B1, W0, W1, ...>
784
+ // / - Remapped substitutions:
785
+ // / [Self := C<B0, B1>, B0 := A0, B1 := A1, W0 := X0, W1 := X1]
786
+ // /
787
+ // / - (Default witness thunk) Original substitutions:
788
+ // / [Self := ConcreteType, R0 := X0, R1 := X1, ...]
789
+ // / - Requirement generic signature:
790
+ // / <Self : P, R0, R1, ...>
791
+ // / - Witness thunk generic signature:
792
+ // / <Self : P, W0, W1, ...>
793
+ // / - Remapped substitutions:
794
+ // / [Self := ConcreteType, W0 := X0, W1 := X1, ...]
795
+ // /
767
796
// / \param conformanceRef The (possibly-specialized) conformance
768
797
// / \param requirementSig The generic signature of the requirement
769
798
// / \param witnessThunkSig The generic signature of the witness method
770
799
// / \param origSubs The substitutions from the call instruction
800
+ // / \param isDefaultWitness True if this is a default witness method
801
+ // / \param classWitness The ClassDecl if this is a class witness method
771
802
static SubstitutionMap
772
803
getWitnessMethodSubstitutions (
804
+ ModuleDecl *mod,
773
805
ProtocolConformanceRef conformanceRef,
774
806
GenericSignature *requirementSig,
775
807
GenericSignature *witnessThunkSig,
776
808
SubstitutionList origSubs,
777
- bool isDefaultWitness) {
809
+ bool isDefaultWitness,
810
+ ClassDecl *classWitness) {
778
811
779
812
if (witnessThunkSig == nullptr )
780
813
return SubstitutionMap ();
@@ -789,42 +822,67 @@ getWitnessMethodSubstitutions(
789
822
790
823
// If `Self` maps to a bound generic type, this gives us the
791
824
// substitutions for the concrete type's generic parameters.
792
- auto baseSubMap = getSubstitutionsForProtocolConformance (conformanceRef);
825
+ auto baseSubMap = getSubstitutionsForProtocolConformance (mod, conformanceRef);
793
826
794
827
unsigned baseDepth = 0 ;
795
828
auto *rootConformance = conformance->getRootNormalConformance ();
796
829
if (auto *witnessSig = rootConformance->getGenericSignature ())
797
830
baseDepth = witnessSig->getGenericParams ().back ()->getDepth () + 1 ;
798
831
799
- auto origDepth = 1 ;
832
+ // If the witness has a class-constrained 'Self' generic parameter,
833
+ // we have to build a new substitution map that shifts all generic
834
+ // parameters down by one.
835
+ if (classWitness != nullptr ) {
836
+ auto *proto = conformance->getProtocol ();
837
+ auto selfType = proto->getSelfInterfaceType ();
838
+
839
+ auto selfSubMap = SubstitutionMap::getProtocolSubstitutions (
840
+ proto, selfType.subst (origSubMap), conformanceRef);
841
+ if (baseSubMap.empty ()) {
842
+ assert (baseDepth == 0 );
843
+ baseSubMap = selfSubMap;
844
+ } else {
845
+ baseSubMap = SubstitutionMap::combineSubstitutionMaps (
846
+ selfSubMap,
847
+ baseSubMap,
848
+ CombineSubstitutionMaps::AtDepth,
849
+ /* firstDepth=*/ 1 ,
850
+ /* secondDepth=*/ 0 ,
851
+ witnessThunkSig);
852
+ }
853
+ baseDepth += 1 ;
854
+ }
800
855
801
856
return SubstitutionMap::combineSubstitutionMaps (
802
857
baseSubMap,
803
858
origSubMap,
804
859
CombineSubstitutionMaps::AtDepth,
805
- baseDepth,
806
- origDepth ,
860
+ /* firstDepth= */ baseDepth,
861
+ /* secondDepth= */ 1 ,
807
862
witnessThunkSig);
808
863
}
809
864
810
865
static SubstitutionMap
811
866
getWitnessMethodSubstitutions (SILModule &Module, ApplySite AI, SILFunction *F,
812
867
ProtocolConformanceRef CRef) {
868
+ auto witnessFnTy = F->getLoweredFunctionType ();
869
+ assert (witnessFnTy->getRepresentation () ==
870
+ SILFunctionTypeRepresentation::WitnessMethod);
871
+
813
872
auto requirementSig = AI.getOrigCalleeType ()->getGenericSignature ();
814
- auto witnessThunkSig = F-> getLoweredFunctionType () ->getGenericSignature ();
873
+ auto witnessThunkSig = witnessFnTy ->getGenericSignature ();
815
874
816
875
SubstitutionList origSubs = AI.getSubstitutions ();
817
876
877
+ auto *mod = Module.getSwiftModule ();
818
878
bool isDefaultWitness =
819
- F->getLoweredFunctionType ()->getRepresentation ()
820
- == SILFunctionTypeRepresentation::WitnessMethod &&
821
- F->getLoweredFunctionType ()->getDefaultWitnessMethodProtocol (
822
- *Module.getSwiftModule ())
823
- == CRef.getRequirement ();
879
+ (witnessFnTy->getDefaultWitnessMethodProtocol (*mod)
880
+ == CRef.getRequirement ());
881
+ auto *classWitness = witnessFnTy->getWitnessMethodClass (*mod);
824
882
825
883
return getWitnessMethodSubstitutions (
826
- CRef, requirementSig, witnessThunkSig,
827
- origSubs, isDefaultWitness);
884
+ mod, CRef, requirementSig, witnessThunkSig,
885
+ origSubs, isDefaultWitness, classWitness );
828
886
}
829
887
830
888
// / Generate a new apply of a function_ref to replace an apply of a
0 commit comments