@@ -900,6 +900,8 @@ getWitnessMethodSubstitutions(
900900 bool isSelfAbstract,
901901 ClassDecl *classWitness) {
902902
903+ auto &ctx = mod->getASTContext ();
904+
903905 if (witnessThunkSig.isNull ())
904906 return SubstitutionMap ();
905907
@@ -909,46 +911,100 @@ getWitnessMethodSubstitutions(
909911 assert (!conformanceRef.isAbstract ());
910912 auto conformance = conformanceRef.getConcrete ();
911913
914+ auto selfType = conformance->getProtocol ()->getSelfInterfaceType ();
915+
912916 // If `Self` maps to a bound generic type, this gives us the
913917 // substitutions for the concrete type's generic parameters.
914918 auto baseSubMap = conformance->getSubstitutions (mod);
915919
916920 unsigned baseDepth = 0 ;
917921 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 ;
944924
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+ });
9521008}
9531009
9541010SubstitutionMap
0 commit comments