@@ -886,8 +886,7 @@ void AssociatedTypeInference::collectAbstractTypeWitnesses(
886886 if (auto genericSig = dc->getGenericSignatureOfContext ()) {
887887 for (auto *gp : genericSig.getInnermostGenericParams ()) {
888888 if (gp->getName () == assocType->getName ()) {
889- system.addTypeWitness (assocType->getName (),
890- dc->mapTypeIntoContext (gp));
889+ system.addTypeWitness (assocType->getName (), gp);
891890 }
892891 }
893892 }
@@ -1153,39 +1152,130 @@ AssociatedTypeDecl *AssociatedTypeInference::inferAbstractTypeWitnesses(
11531152
11541153 // Check each abstract type witness against the generic requirements on the
11551154 // corresponding associated type.
1155+ //
1156+ // FIXME: Consider checking non-dependent type witnesses first. Checking in
1157+ // default order can lead to the creation and exposure of malformed types in
1158+ // diagnostics. For example, we would diagnose that 'G<Never>' (!) does not
1159+ // conform to 'Sequence' in the below.
1160+ //
1161+ // struct G<S: Sequence> {}
1162+ // protocol P {
1163+ // associatedtype A: Sequence = G<B>
1164+ // associatedtype B: Sequence = Never
1165+ // }
11561166 const auto substOptions = getSubstOptionsWithCurrentTypeWitnesses ();
11571167 for (auto *const assocType : unresolvedAssocTypes) {
11581168 Type type = system.getResolvedTypeWitness (assocType->getName ());
1169+ // Replace type parameters with other known or tentative type witnesses.
11591170 if (type->hasTypeParameter ()) {
1160- // Replace type parameters with other known or tentative type witnesses.
1161- type = type.subst (
1162- [&](SubstitutableType *type) {
1163- if (type->isEqual (proto->getSelfInterfaceType ()))
1164- return adoptee;
1171+ // FIXME: We should find a better way to detect and reason about these
1172+ // cyclic solutions so that we can spot them earlier and express them in
1173+ // diagnostics.
1174+ llvm::SmallPtrSet<AssociatedTypeDecl *, 4 > circularityCheck;
1175+ circularityCheck.insert (assocType);
1176+
1177+ std::function<Type (Type)> substCurrentTypeWitnesses;
1178+ substCurrentTypeWitnesses = [&](Type ty) -> Type {
1179+ if (auto *gp = ty->getAs <GenericTypeParamType>()) {
1180+ if (isa<ProtocolDecl>(gp->getDecl ()->getDeclContext ()->getAsDecl ())) {
1181+ return adoptee;
1182+ }
11651183
1166- return Type ();
1167- },
1168- LookUpConformanceInModule (dc->getParentModule ()), substOptions);
1184+ return ty;
1185+ }
11691186
1170- // If the substitution produced an error, give up.
1171- if (type->hasError ())
1172- return assocType;
1187+ auto *const dmt = ty->getAs <DependentMemberType>();
1188+ if (!dmt) {
1189+ return ty;
1190+ }
11731191
1174- // FIXME: We should find a better way to detect and reason about these
1175- // cyclic solutions.
1176- // If mapping into context yields an error, or we still have a type
1177- // parameter despite not having a generic environment, then a type
1178- // parameter was sent to a tentative type witness that itself is a type
1179- // parameter, and the solution is cyclic, e.g { A := B.A, B := A.B };
1180- // bail out in these cases.
1181- if (dc->isGenericContext ()) {
1182- type = dc->mapTypeIntoContext (type);
1183-
1184- if (type->hasError ())
1185- return assocType;
1186- } else if (type->hasTypeParameter ()) {
1192+ const auto substBase =
1193+ dmt->getBase ().transform (substCurrentTypeWitnesses);
1194+ if (!substBase) {
1195+ return nullptr ;
1196+ }
1197+
1198+ // If the transformed base has the same nominal as the adoptee, we may
1199+ // need to look up a tentative type witness. Otherwise, just substitute
1200+ // the base.
1201+ if (substBase->getAnyNominal () != adoptee->getAnyNominal ()) {
1202+ return dmt->substBaseType (dc->getParentModule (), substBase);
1203+ }
1204+
1205+ auto *assocTy = dmt->getAssocType ();
1206+ assert (
1207+ assocTy &&
1208+ " found structural DependentMemberType in tentative type witness" );
1209+
1210+ // Intercept recursive solutions.
1211+ if (!circularityCheck.insert (assocTy).second ) {
1212+ return nullptr ;
1213+ }
1214+ SWIFT_DEFER { circularityCheck.erase (dmt->getAssocType ()); };
1215+
1216+ if (assocTy->getProtocol () == proto) {
1217+ // We have the associated type we need.
1218+ } else if (proto->inheritsFrom (assocTy->getProtocol ())) {
1219+ // See if there is an associated type with the same name in our
1220+ // protocol. If there isn't, keep the original associated type:
1221+ // we'll be falling back to a base substitution.
1222+ if (auto *decl = proto->getAssociatedType (assocTy->getName ())) {
1223+ assocTy = decl;
1224+ }
1225+ }
1226+
1227+ // Find the type witness for this associated type.
1228+ Type tyWitness;
1229+ if (assocTy->getProtocol () == proto && typeWitnesses.count (assocTy)) {
1230+ tyWitness = typeWitnesses.begin (assocTy)->first ;
1231+
1232+ // A tentative type witness may contain a 'Self'-rooted type
1233+ // parameter,
1234+ // FIXME: or a weird concrete-type-rooted dependent member type
1235+ // coming from inference via a value witness. Make sure we sort these
1236+ // out so that we don't break any subst() invariants.
1237+ if (tyWitness->hasTypeParameter () ||
1238+ tyWitness->hasDependentMember ()) {
1239+ tyWitness = tyWitness.transform (substCurrentTypeWitnesses);
1240+ }
1241+
1242+ if (tyWitness) {
1243+ // HACK: Those inferred via value witnesses are eagerly mapped into
1244+ // context. For now, do the same for abstract type witnesses and
1245+ // handle archetypes.
1246+ if (tyWitness->hasArchetype ()) {
1247+ tyWitness = tyWitness->mapTypeOutOfContext ();
1248+ }
1249+
1250+ // If the transformed base is specialized, apply substitutions.
1251+ if (tyWitness->hasTypeParameter ()) {
1252+ const auto conf = dc->getParentModule ()->lookupConformance (
1253+ substBase, assocTy->getProtocol (), /* allowMissing=*/ true );
1254+ if (auto *specialized = dyn_cast<SpecializedProtocolConformance>(
1255+ conf.getConcrete ())) {
1256+ tyWitness = tyWitness.subst (specialized->getSubstitutionMap ());
1257+ }
1258+ }
1259+ }
1260+ } else {
1261+ // The associated type has a recorded type witness, or comes from a
1262+ // different, possibly unrelated protocol; fall back to a base
1263+ // substitution to find the type witness.
1264+ tyWitness =
1265+ DependentMemberType::get (proto->getSelfInterfaceType (), assocTy)
1266+ ->substBaseType (dc->getParentModule (), substBase);
1267+ }
1268+
1269+ return tyWitness;
1270+ };
1271+
1272+ type = type.transform (substCurrentTypeWitnesses);
1273+
1274+ // If substitution failed, give up.
1275+ if (!type || type->hasError ())
11871276 return assocType;
1188- }
1277+
1278+ type = dc->mapTypeIntoContext (type);
11891279 }
11901280
11911281 if (const auto failed =
0 commit comments