@@ -2125,50 +2125,104 @@ AssociatedTypeDecl *swift::findDefaultedAssociatedType(
2125
2125
return results.size () == 1 ? results.front () : nullptr ;
2126
2126
}
2127
2127
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
+
2128
2140
Type AssociatedTypeInference::computeFixedTypeWitness (
2129
2141
AssociatedTypeDecl *assocType) {
2130
2142
Type resultType;
2131
2143
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 ;
2140
2159
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 ;
2147
2163
2148
- auto selfTy = conformedProto->getSelfInterfaceType ();
2149
- if (!sig->requiresProtocol (selfTy, assocType->getProtocol ()))
2150
- continue ;
2164
+ const auto ty = sig.getReducedType (structuralTy);
2151
2165
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
+ }
2154
2174
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;
2161
2177
continue ;
2162
- }
2178
+ }
2163
2179
2164
- if (!resultType) {
2165
- resultType = ty;
2166
- continue ;
2180
+ // FIXME: Bailing out on ambiguity.
2181
+ if (!resultType-> isEqual (ty))
2182
+ return Type () ;
2167
2183
}
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
+ }
2168
2221
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
+ }
2172
2226
}
2173
2227
2174
2228
return resultType;
@@ -2359,18 +2413,6 @@ AssociatedTypeInference::computeAbstractTypeWitness(
2359
2413
return llvm::None;
2360
2414
}
2361
2415
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
-
2374
2416
void AssociatedTypeInference::collectAbstractTypeWitnesses (
2375
2417
TypeWitnessSystem &system,
2376
2418
ArrayRef<AssociatedTypeDecl *> unresolvedAssocTypes) const {
0 commit comments