@@ -171,35 +171,39 @@ AssociatedTypeInference::inferTypeWitnessesViaValueWitnesses(
171
171
172
172
InferredAssociatedTypesByWitnesses result;
173
173
174
- auto isExtensionUsableForInference = [&](ExtensionDecl *extension) -> bool {
175
-
176
- // The extension where the conformance being checked is declared.
177
- auto conformanceExtension = checker.Conformance ->
178
- getDeclContext ()->getAsDecl ();
179
- if (extension == conformanceExtension)
174
+ auto isExtensionUsableForInference = [&](const ExtensionDecl *extension) {
175
+ // The context the conformance being checked is declared on.
176
+ const auto conformanceCtx = checker.Conformance ->getDeclContext ();
177
+ if (extension == conformanceCtx)
180
178
return true ;
181
179
182
- auto *extendedNominal = extension->getExtendedNominal ();
183
-
184
180
// Invalid case.
181
+ const auto extendedNominal = extension->getExtendedNominal ();
185
182
if (extendedNominal == nullptr )
186
183
return true ;
187
-
188
- // Assume unconstrained concrete extensions we found witnesses in are
189
- // always viable.
190
- if (!isa<ProtocolDecl>(extendedNominal))
191
- return !extension->isConstrainedExtension ();
192
-
184
+
193
185
// FIXME: The extension may not have a generic signature set up yet as
194
186
// resolving signatures may trigger associated type inference. This cycle
195
187
// is now detectable and we should look into untangling it
196
188
// - see rdar://55263708
197
189
if (!extension->hasComputedGenericSignature ())
198
190
return true ;
199
191
200
- // Build a generic signature.
201
- auto extensionSig = extension->getGenericSignature ();
202
-
192
+ // Retrieve the generic signature of the extension.
193
+ const auto extensionSig = extension->getGenericSignature ();
194
+
195
+ // If the extension is bound to the nominal the conformance is
196
+ // declared on, it is viable for inference when its conditional
197
+ // requirements are satisfied by those of the conformance context.
198
+ if (!isa<ProtocolDecl>(extendedNominal)) {
199
+ // Extensions of non-generic nominals are always viable for inference.
200
+ if (!extensionSig)
201
+ return true ;
202
+
203
+ return extensionSig->requirementsNotSatisfiedBy (
204
+ conformanceCtx->getGenericSignatureOfContext ()).empty ();
205
+ }
206
+
203
207
// The condition here is a bit more fickle than
204
208
// `isExtensionApplied`. That check would prematurely reject
205
209
// extensions like `P where AssocType == T` if we're relying on a
@@ -413,9 +417,7 @@ AssociatedTypeInference::inferTypeWitnessesViaValueWitnesses(
413
417
InferredAssociatedTypes result;
414
418
for (auto member : proto->getMembers ()) {
415
419
auto req = dyn_cast<ValueDecl>(member);
416
- if (!req)
417
- continue ;
418
- if (!req->isProtocolRequirement ())
420
+ if (!req || !req->isProtocolRequirement ())
419
421
continue ;
420
422
421
423
// Infer type witnesses for associated types.
@@ -449,19 +451,14 @@ AssociatedTypeInference::inferTypeWitnessesViaValueWitnesses(
449
451
450
452
// Check whether any of the associated types we care about are
451
453
// referenced in this value requirement.
452
- bool anyAssocTypeMatches = false ;
453
- for ( auto assocType : checker.getReferencedAssociatedTypes (req)) {
454
- if (assocTypes. count (assocType) > 0 ) {
455
- anyAssocTypeMatches = true ;
456
- break ;
457
- }
454
+ {
455
+ const auto referenced = checker.getReferencedAssociatedTypes (req);
456
+ if (llvm::find_if (referenced, [&](AssociatedTypeDecl * const assocType ) {
457
+ return assocTypes. count (assocType) ;
458
+ }) == referenced. end ())
459
+ continue ;
458
460
}
459
461
460
- // We cannot deduce anything from the witnesses of this
461
- // requirement; skip it.
462
- if (!anyAssocTypeMatches)
463
- continue ;
464
-
465
462
// Infer associated types from the potential value witnesses for
466
463
// this requirement.
467
464
auto reqInferred =
0 commit comments