@@ -277,22 +277,17 @@ struct SynthesizedExtensionAnalyzer::Implementation {
277277 using MergeGroupVector = std::vector<ExtensionMergeGroup>;
278278
279279 NominalTypeDecl *Target;
280- Type BaseType;
281280 DeclContext *DC;
282281 bool IncludeUnconditional;
283282 PrintOptions Options;
284283 MergeGroupVector AllGroups;
285284 ExtensionInfoMap InfoMap;
286285
287- Implementation (NominalTypeDecl *Target,
288- bool IncludeUnconditional,
289- PrintOptions &&Options):
290- Target (Target),
291- BaseType (Target->getDeclaredInterfaceType ()),
292- DC(Target),
293- IncludeUnconditional(IncludeUnconditional),
294- Options(std::move(Options)), AllGroups(MergeGroupVector()),
295- InfoMap(collectSynthesizedExtensionInfo(AllGroups)) {}
286+ Implementation (NominalTypeDecl *Target, bool IncludeUnconditional,
287+ PrintOptions &&Options)
288+ : Target(Target), DC(Target), IncludeUnconditional(IncludeUnconditional),
289+ Options (std::move(Options)), AllGroups(MergeGroupVector()),
290+ InfoMap(collectSynthesizedExtensionInfo(AllGroups)) {}
296291
297292 unsigned countInherits (ExtensionDecl *ED) {
298293 SmallVector<InheritedEntry, 4 > Results;
@@ -316,19 +311,24 @@ struct SynthesizedExtensionAnalyzer::Implementation {
316311 // extension SomeType: SomeProtocol where T: SomeProtocol {}. The former is
317312 // Ext and the latter is EnablingExt/Conf. Either of these can be
318313 // conditional in ways that need to be considered when merging.
319- auto conformanceIsConditional =
320- Conf && !Conf->getConditionalRequirements ().empty ();
321- if (!Ext->isConstrainedExtension () && !conformanceIsConditional ) {
314+ auto isConditionalEnablingExt =
315+ Conf && EnablingExt && !Conf->getConditionalRequirements ().empty ();
316+ if (!Ext->isConstrainedExtension () && !isConditionalEnablingExt ) {
322317 if (IncludeUnconditional)
323318 Result.Ext = Ext;
324319 return {Result, MergeInfo};
325320 }
326321
327- auto handleRequirements = [&](SubstitutionMap subMap,
328- ExtensionDecl *OwningExt,
322+ auto handleRequirements = [&](ExtensionDecl *OwningExt,
329323 ArrayRef<Requirement> Reqs) {
330- ProtocolDecl *BaseProto = OwningExt->getInnermostDeclContext ()
331- ->getSelfProtocolDecl ();
324+ ProtocolDecl *BaseProto = OwningExt->getSelfProtocolDecl ();
325+ // Substitute the base conforming type into a protocol's generic signature
326+ // if needed.
327+ SubstitutionMap subMap;
328+ if (Conf && BaseProto) {
329+ subMap = SubstitutionMap::getProtocolSubstitutions (
330+ ProtocolConformanceRef (Conf));
331+ }
332332 for (auto Req : Reqs) {
333333 // Skip protocol's Self : <Protocol> requirement.
334334 if (BaseProto &&
@@ -337,10 +337,13 @@ struct SynthesizedExtensionAnalyzer::Implementation {
337337 Req.getProtocolDecl () == BaseProto)
338338 continue ;
339339
340- if (!BaseType-> isExistentialType () ) {
340+ if (subMap ) {
341341 // Apply any substitutions we need to map the requirements from a
342- // a protocol extension to an extension on the conforming type.
343- Req = Req.subst (subMap);
342+ // a protocol extension to an extension on the conforming type. We
343+ // need to lookup conformances outside of the substitution map since
344+ // the extension may introduce new conformance constraints.
345+ Req = Req.subst (QuerySubstitutionMap{subMap},
346+ LookUpConformanceInModule ());
344347 if (Req.hasError ()) {
345348 // Substitution with interface type bases can only fail
346349 // if a concrete type fails to conform to a protocol.
@@ -353,6 +356,14 @@ struct SynthesizedExtensionAnalyzer::Implementation {
353356 if (Req.getKind () != RequirementKind::Layout)
354357 assert (!Req.getSecondType ()->hasArchetype ());
355358
359+ // FIXME: This doesn't correctly handle conformance requirements, e.g:
360+ //
361+ // extension P where X: Q, X.Y == Int {}
362+ //
363+ // Since the archetype we have for `X` doesn't necessarily have a
364+ // conformance to `Q` in the conforming type's generic environment. This
365+ // results in a substitution failure for `X.Y`.
366+ // https://github.com/swiftlang/swift/issues/83564
356367 auto *env = Target->getGenericEnvironment ();
357368 SmallVector<Requirement, 2 > subReqs;
358369 subReqs.push_back (
@@ -385,30 +396,14 @@ struct SynthesizedExtensionAnalyzer::Implementation {
385396 };
386397
387398 if (Ext->isConstrainedExtension ()) {
388- // Get the substitutions from the generic signature of
389- // the extension to the interface types of the base type's
390- // declaration.
391- SubstitutionMap subMap;
392- if (!BaseType->isExistentialType ()) {
393- if (auto *NTD = Ext->getExtendedNominal ())
394- subMap = BaseType->getContextSubstitutionMap (NTD);
395- }
396-
397399 assert (Ext->getGenericSignature () && " No generic signature." );
398400 auto GenericSig = Ext->getGenericSignature ();
399- if (handleRequirements (subMap, Ext, GenericSig.getRequirements ()))
401+ if (handleRequirements (Ext, GenericSig.getRequirements ()))
400402 return {Result, MergeInfo};
401403 }
402404
403- if (Conf) {
404- SubstitutionMap subMap;
405- if (!BaseType->isExistentialType ()) {
406- if (auto *NTD = EnablingExt->getExtendedNominal ())
407- subMap = BaseType->getContextSubstitutionMap (NTD);
408- }
409- if (handleRequirements (subMap,
410- EnablingExt,
411- Conf->getConditionalRequirements ()))
405+ if (isConditionalEnablingExt) {
406+ if (handleRequirements (EnablingExt, Conf->getConditionalRequirements ()))
412407 return {Result, MergeInfo};
413408 }
414409
@@ -479,7 +474,6 @@ struct SynthesizedExtensionAnalyzer::Implementation {
479474
480475 ExtensionInfoMap InfoMap;
481476 ExtensionMergeInfoMap MergeInfoMap;
482- std::vector<NominalTypeDecl*> Unhandled;
483477
484478 auto handleExtension = [&](ExtensionDecl *E, bool Synthesized,
485479 ExtensionDecl *EnablingE,
@@ -500,31 +494,17 @@ struct SynthesizedExtensionAnalyzer::Implementation {
500494 }
501495 };
502496
503- // We want to visit the protocols of any normal conformances we see, but
504- // we have to avoid doing this to self-conformances or we can end up with
505- // a cycle. Otherwise this is cycle-proof on valid code.
506- // We also want to ignore inherited conformances. Members from these will
507- // be included in the class they were inherited from.
508- auto addConformance = [&](ProtocolConformance *Conf) {
509- if (isa<InheritedProtocolConformance>(Conf))
510- return ;
511- auto RootConf = Conf->getRootConformance ();
512- if (isa<NormalProtocolConformance>(RootConf))
513- Unhandled.push_back (RootConf->getProtocol ());
514- };
497+ for (auto *LocalConf : Target->getLocalConformances ()) {
498+ if (isa<InheritedProtocolConformance>(LocalConf))
499+ continue ;
515500
516- for (auto *Conf : Target->getLocalConformances ()) {
517- addConformance (Conf);
518- }
519- while (!Unhandled.empty ()) {
520- NominalTypeDecl* Back = Unhandled.back ();
521- Unhandled.pop_back ();
522- for (ExtensionDecl *E : Back->getExtensions ()) {
523- handleExtension (E, true , nullptr , nullptr );
524- }
525- for (auto *Conf : Back->getLocalConformances ()) {
526- addConformance (Conf);
527- }
501+ auto RootConf = LocalConf->getRootConformance ();
502+ auto *Conf = dyn_cast<NormalProtocolConformance>(RootConf);
503+ if (!Conf)
504+ continue ;
505+
506+ for (auto *E : Conf->getProtocol ()->getExtensions ())
507+ handleExtension (E, true , nullptr , Conf);
528508 }
529509
530510 // Merge with actual extensions.
0 commit comments