@@ -322,18 +322,20 @@ static void maybeAddSameTypeRequirementForNestedType(
322322
323323bool ArchetypeBuilder::PotentialArchetype::addConformance (
324324 ProtocolDecl *proto,
325+ bool updateExistingSource,
325326 const RequirementSource &source,
326327 ArchetypeBuilder &builder) {
327328 auto rep = getRepresentative ();
328329 if (rep != this )
329- return rep->addConformance (proto, source, builder);
330+ return rep->addConformance (proto, updateExistingSource, source, builder);
330331
331332 // Check whether we already know about this conformance.
332333 auto known = ConformsTo.find (proto);
333334 if (known != ConformsTo.end ()) {
334335 // We already have this requirement. Update the requirement source
335336 // appropriately.
336- updateRequirementSource (known->second , source);
337+ if (updateExistingSource)
338+ updateRequirementSource (known->second , source);
337339 return false ;
338340 }
339341
@@ -963,7 +965,7 @@ bool ArchetypeBuilder::addConformanceRequirement(PotentialArchetype *PAT,
963965 auto T = PAT->getRepresentative ();
964966
965967 // Add the requirement, if we haven't done so already.
966- if (!T->addConformance (Proto, Source, *this ))
968+ if (!T->addConformance (Proto, /* updateExistingSource= */ true , Source, *this ))
967969 return false ;
968970
969971 RequirementSource InnerSource (RequirementSource::Protocol, Source.getLoc ());
@@ -1159,7 +1161,20 @@ bool ArchetypeBuilder::addSameTypeRequirementBetweenArchetypes(
11591161 T1->ArchetypeOrConcreteType = NestedType::forConcreteType (concrete2);
11601162 T1->SameTypeSource = T2->SameTypeSource ;
11611163 }
1162-
1164+
1165+ // Don't mark requirements as redundant if they come from one of our
1166+ // child archetypes. This is a targeted fix -- more general cases
1167+ // continue to break. In general, we need to detect cycles in the
1168+ // archetype graph and not propagate requirement source information
1169+ // along back edges.
1170+ bool creatingCycle = false ;
1171+ auto T2Parent = T2;
1172+ while (T2Parent != nullptr ) {
1173+ if (T2Parent->getRepresentative () == T1)
1174+ creatingCycle = true ;
1175+ T2Parent = T2Parent->getParent ();
1176+ }
1177+
11631178 // Make T1 the representative of T2, merging the equivalence classes.
11641179 T2->Representative = T1;
11651180 T2->SameTypeSource = Source;
@@ -1175,7 +1190,8 @@ bool ArchetypeBuilder::addSameTypeRequirementBetweenArchetypes(
11751190
11761191 // Add all of the protocol conformance requirements of T2 to T1.
11771192 for (auto conforms : T2->ConformsTo ) {
1178- T1->addConformance (conforms.first , conforms.second , *this );
1193+ T1->addConformance (conforms.first , /* updateExistingSource=*/ !creatingCycle,
1194+ conforms.second , *this );
11791195 }
11801196
11811197 // Recursively merge the associated types of T2 into T1.
@@ -1331,7 +1347,8 @@ bool ArchetypeBuilder::addAbstractTypeParamRequirements(
13311347 assocType->setInvalid ();
13321348
13331349 // FIXME: Drop this protocol.
1334- pa->addConformance (proto, RequirementSource (kind, loc), *this );
1350+ pa->addConformance (proto, /* updateExistingSource=*/ true ,
1351+ RequirementSource (kind, loc), *this );
13351352 };
13361353
13371354 // If the abstract type parameter already has an archetype assigned,
0 commit comments