@@ -2125,50 +2125,104 @@ AssociatedTypeDecl *swift::findDefaultedAssociatedType(
21252125 return results.size () == 1 ? results.front () : nullptr ;
21262126}
21272127
2128+ static SmallVector<ProtocolConformance *, 2 >
2129+ getPeerConformances (NormalProtocolConformance *conformance) {
2130+ auto *dc = conformance->getDeclContext ();
2131+ IterableDeclContext *idc = dyn_cast<ExtensionDecl>(dc);
2132+ if (!idc)
2133+ idc = cast<NominalTypeDecl>(dc);
2134+
2135+ // NonStructural skips the Sendable synthesis which can cycle, and Sendable
2136+ // doesn't have associated types anyway.
2137+ return idc->getLocalConformances (ConformanceLookupKind::NonStructural);
2138+ }
2139+
21282140Type AssociatedTypeInference::computeFixedTypeWitness (
21292141 AssociatedTypeDecl *assocType) {
21302142 Type resultType;
21312143
2132- // Look at all of the inherited protocols to determine whether they
2133- // require a fixed type for this associated type.
2134- for (auto conformedProto : dc->getSelfNominalTypeDecl ()->getAllProtocols ()) {
2135- if (conformedProto != assocType->getProtocol () &&
2136- !conformedProto->inheritsFrom (assocType->getProtocol ()))
2137- continue ;
2138-
2139- auto sig = conformedProto->getGenericSignature ();
2144+ if (ctx.LangOpts .EnableExperimentalAssociatedTypeInference ) {
2145+ auto selfTy = assocType->getProtocol ()->getSelfInterfaceType ();
2146+
2147+ // Look through other local conformances of our declaration context to see if
2148+ // any fix this associated type to a concrete type.
2149+ for (auto conformance : getPeerConformances (conformance)) {
2150+ auto *conformedProto = conformance->getProtocol ();
2151+ auto sig = conformedProto->getGenericSignature ();
2152+
2153+ // FIXME: The RequirementMachine will assert on re-entrant construction.
2154+ // We should find a more principled way of breaking this cycle.
2155+ if (ctx.isRecursivelyConstructingRequirementMachine (sig.getCanonicalSignature ()) ||
2156+ ctx.isRecursivelyConstructingRequirementMachine (conformedProto) ||
2157+ conformedProto->isComputingRequirementSignature ())
2158+ continue ;
21402159
2141- // FIXME: The RequirementMachine will assert on re-entrant construction.
2142- // We should find a more principled way of breaking this cycle.
2143- if (ctx.isRecursivelyConstructingRequirementMachine (sig.getCanonicalSignature ()) ||
2144- ctx.isRecursivelyConstructingRequirementMachine (conformedProto) ||
2145- conformedProto->isComputingRequirementSignature ())
2146- continue ;
2160+ auto structuralTy = DependentMemberType::get (selfTy, assocType->getName ());
2161+ if (!sig->isValidTypeParameter (structuralTy))
2162+ continue ;
21472163
2148- auto selfTy = conformedProto->getSelfInterfaceType ();
2149- if (!sig->requiresProtocol (selfTy, assocType->getProtocol ()))
2150- continue ;
2164+ const auto ty = sig.getReducedType (structuralTy);
21512165
2152- auto structuralTy = DependentMemberType::get (selfTy, assocType->getName ());
2153- const auto ty = sig.getReducedType (structuralTy);
2166+ // A dependent member type with an identical base and name indicates that
2167+ // the protocol does not same-type constrain it in any way; move on to
2168+ // the next protocol.
2169+ if (auto *const memberTy = ty->getAs <DependentMemberType>()) {
2170+ if (memberTy->getBase ()->isEqual (selfTy) &&
2171+ memberTy->getName () == assocType->getName ())
2172+ continue ;
2173+ }
21542174
2155- // A dependent member type with an identical base and name indicates that
2156- // the protocol does not same-type constrain it in any way; move on to
2157- // the next protocol.
2158- if (auto *const memberTy = ty->getAs <DependentMemberType>()) {
2159- if (memberTy->getBase ()->isEqual (selfTy) &&
2160- memberTy->getName () == assocType->getName ())
2175+ if (!resultType) {
2176+ resultType = ty;
21612177 continue ;
2162- }
2178+ }
21632179
2164- if (!resultType) {
2165- resultType = ty;
2166- continue ;
2180+ // FIXME: Bailing out on ambiguity.
2181+ if (!resultType-> isEqual (ty))
2182+ return Type () ;
21672183 }
2184+ } else {
2185+ // Look at all of the inherited protocols to determine whether they
2186+ // require a fixed type for this associated type.
2187+ for (auto conformedProto : dc->getSelfNominalTypeDecl ()->getAllProtocols ()) {
2188+ if (conformedProto != assocType->getProtocol () &&
2189+ !conformedProto->inheritsFrom (assocType->getProtocol ()))
2190+ continue ;
2191+
2192+ auto sig = conformedProto->getGenericSignature ();
2193+
2194+ // FIXME: The RequirementMachine will assert on re-entrant construction.
2195+ // We should find a more principled way of breaking this cycle.
2196+ if (ctx.isRecursivelyConstructingRequirementMachine (sig.getCanonicalSignature ()) ||
2197+ ctx.isRecursivelyConstructingRequirementMachine (conformedProto) ||
2198+ conformedProto->isComputingRequirementSignature ())
2199+ continue ;
2200+
2201+ auto selfTy = conformedProto->getSelfInterfaceType ();
2202+ if (!sig->requiresProtocol (selfTy, assocType->getProtocol ()))
2203+ continue ;
2204+
2205+ auto structuralTy = DependentMemberType::get (selfTy, assocType->getName ());
2206+ const auto ty = sig.getReducedType (structuralTy);
2207+
2208+ // A dependent member type with an identical base and name indicates that
2209+ // the protocol does not same-type constrain it in any way; move on to
2210+ // the next protocol.
2211+ if (auto *const memberTy = ty->getAs <DependentMemberType>()) {
2212+ if (memberTy->getBase ()->isEqual (selfTy) &&
2213+ memberTy->getName () == assocType->getName ())
2214+ continue ;
2215+ }
2216+
2217+ if (!resultType) {
2218+ resultType = ty;
2219+ continue ;
2220+ }
21682221
2169- // FIXME: Bailing out on ambiguity.
2170- if (!resultType->isEqual (ty))
2171- return Type ();
2222+ // FIXME: Bailing out on ambiguity.
2223+ if (!resultType->isEqual (ty))
2224+ return Type ();
2225+ }
21722226 }
21732227
21742228 return resultType;
@@ -2359,18 +2413,6 @@ AssociatedTypeInference::computeAbstractTypeWitness(
23592413 return llvm::None;
23602414}
23612415
2362- static SmallVector<ProtocolConformance *, 2 >
2363- getPeerConformances (NormalProtocolConformance *conformance) {
2364- auto *dc = conformance->getDeclContext ();
2365- IterableDeclContext *idc = dyn_cast<ExtensionDecl>(dc);
2366- if (!idc)
2367- idc = cast<NominalTypeDecl>(dc);
2368-
2369- // NonStructural skips the Sendable synthesis which can cycle, and Sendable
2370- // doesn't have associated types anyway.
2371- return idc->getLocalConformances (ConformanceLookupKind::NonStructural);
2372- }
2373-
23742416void AssociatedTypeInference::collectAbstractTypeWitnesses (
23752417 TypeWitnessSystem &system,
23762418 ArrayRef<AssociatedTypeDecl *> unresolvedAssocTypes) const {
0 commit comments