@@ -900,6 +900,8 @@ getWitnessMethodSubstitutions(
900
900
bool isSelfAbstract,
901
901
ClassDecl *classWitness) {
902
902
903
+ auto &ctx = mod->getASTContext ();
904
+
903
905
if (witnessThunkSig.isNull ())
904
906
return SubstitutionMap ();
905
907
@@ -909,46 +911,100 @@ getWitnessMethodSubstitutions(
909
911
assert (!conformanceRef.isAbstract ());
910
912
auto conformance = conformanceRef.getConcrete ();
911
913
914
+ auto selfType = conformance->getProtocol ()->getSelfInterfaceType ();
915
+
912
916
// If `Self` maps to a bound generic type, this gives us the
913
917
// substitutions for the concrete type's generic parameters.
914
918
auto baseSubMap = conformance->getSubstitutions (mod);
915
919
916
920
unsigned baseDepth = 0 ;
917
921
auto *rootConformance = conformance->getRootConformance ();
918
- if (auto witnessSig = rootConformance->getGenericSignature ())
919
- baseDepth = witnessSig.getGenericParams ().back ()->getDepth () + 1 ;
920
-
921
- // If the witness has a class-constrained 'Self' generic parameter,
922
- // we have to build a new substitution map that shifts all generic
923
- // parameters down by one.
924
- if (classWitness != nullptr ) {
925
- auto *proto = conformance->getProtocol ();
926
- auto selfType = proto->getSelfInterfaceType ();
927
-
928
- auto selfSubMap = SubstitutionMap::getProtocolSubstitutions (
929
- proto, selfType.subst (origSubMap), conformanceRef);
930
- if (baseSubMap.empty ()) {
931
- assert (baseDepth == 0 );
932
- baseSubMap = selfSubMap;
933
- } else {
934
- baseSubMap = SubstitutionMap::combineSubstitutionMaps (
935
- selfSubMap,
936
- baseSubMap,
937
- CombineSubstitutionMaps::AtDepth,
938
- /* firstDepth=*/ 1 ,
939
- /* secondDepth=*/ 0 ,
940
- witnessThunkSig);
941
- }
942
- baseDepth += 1 ;
943
- }
922
+ if (auto conformingTypeSig = rootConformance->getGenericSignature ())
923
+ baseDepth = conformingTypeSig.getGenericParams ().back ()->getDepth () + 1 ;
944
924
945
- return SubstitutionMap::combineSubstitutionMaps (
946
- baseSubMap,
947
- origSubMap,
948
- CombineSubstitutionMaps::AtDepth,
949
- /* firstDepth=*/ baseDepth,
950
- /* secondDepth=*/ 1 ,
951
- witnessThunkSig);
925
+ // witnessThunkSig begins with the optional class 'Self', followed by the
926
+ // generic parameters of the concrete conforming type, followed by the
927
+ // generic parameters of the protocol requirement, if any.
928
+ //
929
+ // - The 'Self' parameter is replaced with the conforming type.
930
+ // - The conforming type's generic parameters are replaced by the
931
+ // conformance substitutions.
932
+ // - The protocol requirement's generic parameters are replaced from the
933
+ // substitution map at the call site.
934
+ return SubstitutionMap::get (
935
+ witnessThunkSig,
936
+ [&](SubstitutableType *type) {
937
+ auto *paramType = type->castTo <GenericTypeParamType>();
938
+ unsigned depth = paramType->getDepth ();
939
+
940
+ if (classWitness != nullptr ) {
941
+ if (depth == 0 ) {
942
+ assert (paramType->getIndex () == 0 );
943
+ return selfType.subst (origSubMap);
944
+ }
945
+
946
+ --depth;
947
+ }
948
+
949
+ if (depth < baseDepth) {
950
+ paramType = GenericTypeParamType::get (
951
+ paramType->isTypeSequence (),
952
+ depth, paramType->getIndex (), ctx);
953
+
954
+ return Type (paramType).subst (baseSubMap);
955
+ }
956
+
957
+ depth = depth - baseDepth + 1 ;
958
+
959
+ paramType = GenericTypeParamType::get (
960
+ paramType->isTypeSequence (),
961
+ depth, paramType->getIndex (), ctx);
962
+ return Type (paramType).subst (origSubMap);
963
+ },
964
+ [&](CanType type, Type substType, ProtocolDecl *proto) {
965
+ auto *paramType = type->getRootGenericParam ();
966
+ unsigned depth = paramType->getDepth ();
967
+
968
+ if (classWitness != nullptr ) {
969
+ if (depth == 0 ) {
970
+ assert (type->isEqual (paramType));
971
+ assert (paramType->getIndex () == 0 );
972
+ return conformanceRef;
973
+ }
974
+
975
+ --depth;
976
+ }
977
+
978
+ if (depth < baseDepth) {
979
+ type = CanType (type.transform ([&](Type t) -> Type {
980
+ if (t->isEqual (paramType)) {
981
+ return GenericTypeParamType::get (
982
+ paramType->isTypeSequence (),
983
+ depth, paramType->getIndex (), ctx);
984
+ }
985
+
986
+ assert (!t->is <GenericTypeParamType>());
987
+ return t;
988
+ }));
989
+
990
+ return baseSubMap.lookupConformance (type, proto);
991
+ }
992
+
993
+ depth = depth - baseDepth + 1 ;
994
+
995
+ type = CanType (type.transform ([&](Type t) -> Type {
996
+ if (t->isEqual (paramType)) {
997
+ return GenericTypeParamType::get (
998
+ paramType->isTypeSequence (),
999
+ depth, paramType->getIndex (), ctx);
1000
+ }
1001
+
1002
+ assert (!t->is <GenericTypeParamType>());
1003
+ return t;
1004
+ }));
1005
+
1006
+ return origSubMap.lookupConformance (type, proto);
1007
+ });
952
1008
}
953
1009
954
1010
SubstitutionMap
0 commit comments