@@ -322,18 +322,20 @@ static void maybeAddSameTypeRequirementForNestedType(
322
322
323
323
bool ArchetypeBuilder::PotentialArchetype::addConformance (
324
324
ProtocolDecl *proto,
325
+ bool updateExistingSource,
325
326
const RequirementSource &source,
326
327
ArchetypeBuilder &builder) {
327
328
auto rep = getRepresentative ();
328
329
if (rep != this )
329
- return rep->addConformance (proto, source, builder);
330
+ return rep->addConformance (proto, updateExistingSource, source, builder);
330
331
331
332
// Check whether we already know about this conformance.
332
333
auto known = ConformsTo.find (proto);
333
334
if (known != ConformsTo.end ()) {
334
335
// We already have this requirement. Update the requirement source
335
336
// appropriately.
336
- updateRequirementSource (known->second , source);
337
+ if (updateExistingSource)
338
+ updateRequirementSource (known->second , source);
337
339
return false ;
338
340
}
339
341
@@ -963,7 +965,7 @@ bool ArchetypeBuilder::addConformanceRequirement(PotentialArchetype *PAT,
963
965
auto T = PAT->getRepresentative ();
964
966
965
967
// 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 ))
967
969
return false ;
968
970
969
971
RequirementSource InnerSource (RequirementSource::Protocol, Source.getLoc ());
@@ -1159,7 +1161,20 @@ bool ArchetypeBuilder::addSameTypeRequirementBetweenArchetypes(
1159
1161
T1->ArchetypeOrConcreteType = NestedType::forConcreteType (concrete2);
1160
1162
T1->SameTypeSource = T2->SameTypeSource ;
1161
1163
}
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
+
1163
1178
// Make T1 the representative of T2, merging the equivalence classes.
1164
1179
T2->Representative = T1;
1165
1180
T2->SameTypeSource = Source;
@@ -1175,7 +1190,8 @@ bool ArchetypeBuilder::addSameTypeRequirementBetweenArchetypes(
1175
1190
1176
1191
// Add all of the protocol conformance requirements of T2 to T1.
1177
1192
for (auto conforms : T2->ConformsTo ) {
1178
- T1->addConformance (conforms.first , conforms.second , *this );
1193
+ T1->addConformance (conforms.first , /* updateExistingSource=*/ !creatingCycle,
1194
+ conforms.second , *this );
1179
1195
}
1180
1196
1181
1197
// Recursively merge the associated types of T2 into T1.
@@ -1331,7 +1347,8 @@ bool ArchetypeBuilder::addAbstractTypeParamRequirements(
1331
1347
assocType->setInvalid ();
1332
1348
1333
1349
// FIXME: Drop this protocol.
1334
- pa->addConformance (proto, RequirementSource (kind, loc), *this );
1350
+ pa->addConformance (proto, /* updateExistingSource=*/ true ,
1351
+ RequirementSource (kind, loc), *this );
1335
1352
};
1336
1353
1337
1354
// If the abstract type parameter already has an archetype assigned,
0 commit comments