@@ -794,8 +794,22 @@ Type AssociatedTypeInference::computeFixedTypeWitness(
794794 auto genericSig = conformedProto->getGenericSignature ();
795795 if (!genericSig) return Type ();
796796
797- Type concreteType = genericSig->getConcreteType (dependentType);
798- if (!concreteType) continue ;
797+ Type concreteType;
798+ if (auto optType = genericSig->maybeGetConcreteType (dependentType)) {
799+ if (optType.getValue ()) {
800+ concreteType = optType.getValue ();
801+
802+ // If this associated type has a same-type constraint
803+ // with Self, the fixed type is the adoptee.
804+ } else if (genericSig->areSameTypeParameterInContext (
805+ dependentType, proto->getSelfInterfaceType ())) {
806+ concreteType = adoptee;
807+ } else {
808+ continue ;
809+ }
810+ } else {
811+ continue ;
812+ }
799813
800814 if (!resultType) {
801815 resultType = concreteType;
@@ -936,9 +950,16 @@ Type AssociatedTypeInference::substCurrentTypeWitnesses(Type type) {
936950 llvm::DenseSet<AssociatedTypeDecl *> recursionCheck;
937951 foldDependentMemberTypes = [&](Type type) -> Type {
938952 if (auto depMemTy = type->getAs <DependentMemberType>()) {
939- auto baseTy = depMemTy->getBase ().transform (foldDependentMemberTypes);
940- if (baseTy.isNull () || baseTy->hasTypeParameter ())
941- return nullptr ;
953+ Type baseTy;
954+ if (depMemTy->getBase ()->is <GenericTypeParamType>()) {
955+ // The base type is Self.
956+ baseTy = depMemTy->getBase ();
957+ } else {
958+ baseTy = depMemTy->getBase ().transform (foldDependentMemberTypes);
959+
960+ if (baseTy.isNull () || baseTy->hasTypeParameter ())
961+ return nullptr ;
962+ }
942963
943964 auto assocType = depMemTy->getAssocType ();
944965 if (!assocType)
@@ -949,21 +970,26 @@ Type AssociatedTypeInference::substCurrentTypeWitnesses(Type type) {
949970
950971 SWIFT_DEFER { recursionCheck.erase (assocType); };
951972
952- // Try to substitute into the base type.
953- Type result = depMemTy->substBaseType (dc->getParentModule (), baseTy);
954- if (!result->hasError ())
955- return result;
956-
957- // If that failed, check whether it's because of the conformance we're
958- // evaluating.
959- auto localConformance
960- = TypeChecker::conformsToProtocol (
961- baseTy, assocType->getProtocol (), dc,
962- ConformanceCheckFlags::SkipConditionalRequirements);
963- if (localConformance.isInvalid () || localConformance.isAbstract () ||
964- (localConformance.getConcrete ()->getRootConformance () !=
965- conformance)) {
966- return nullptr ;
973+ // If the base type is Self, we are folding a fixed type witness, which
974+ // is to say, a witness through same-type constraints on protocols;
975+ // substituting into the base and conformance lookup are irrelevant.
976+ if (!baseTy->is <GenericTypeParamType>()) {
977+ // Try to substitute into the base type.
978+ Type result = depMemTy->substBaseType (dc->getParentModule (), baseTy);
979+ if (!result->hasError ())
980+ return result;
981+
982+ // If that failed, check whether it's because of the conformance we're
983+ // evaluating.
984+ auto localConformance
985+ = TypeChecker::conformsToProtocol (
986+ baseTy, assocType->getProtocol (), dc,
987+ ConformanceCheckFlags::SkipConditionalRequirements);
988+ if (localConformance.isInvalid () || localConformance.isAbstract () ||
989+ (localConformance.getConcrete ()->getRootConformance () !=
990+ conformance)) {
991+ return nullptr ;
992+ }
967993 }
968994
969995 // Find the tentative type witness for this associated type.
@@ -974,10 +1000,13 @@ Type AssociatedTypeInference::substCurrentTypeWitnesses(Type type) {
9741000 return known->first .transform (foldDependentMemberTypes);
9751001 }
9761002
977- // The presence of a generic type parameter indicates that we
978- // cannot use this type binding.
979- if (type->is <GenericTypeParamType>()) {
980- return nullptr ;
1003+ if (const auto genParam = type->getAs <GenericTypeParamType>()) {
1004+ bool isProtocolSelf = true ;
1005+ if (const auto gpDecl = genParam->getDecl ())
1006+ if (adoptee->getAnyNominal () == gpDecl->getDeclContext ())
1007+ isProtocolSelf = false ;
1008+ if (isProtocolSelf)
1009+ return adoptee;
9811010 }
9821011
9831012 return type;
0 commit comments