@@ -234,6 +234,55 @@ bool RequirementSource::isDerivedViaConcreteConformance() const {
234
234
return false ;
235
235
}
236
236
237
+ bool RequirementSource::isSelfDerivedSource (PotentialArchetype *pa) const {
238
+ // If it's not a derived requirement, it's not self-derived.
239
+ if (!isDerivedRequirement ()) return false ;
240
+
241
+ // Collect the path of associated types from the root pa.
242
+ SmallVector<AssociatedTypeDecl *, 4 > assocTypes;
243
+ PotentialArchetype *currentPA = nullptr ;
244
+ for (auto source = this ; source; source = source->parent ) {
245
+ switch (source->kind ) {
246
+ case RequirementSource::Parent:
247
+ assocTypes.push_back (source->getAssociatedType ());
248
+ break ;
249
+
250
+ case RequirementSource::NestedTypeNameMatch:
251
+ return false ;
252
+
253
+ case RequirementSource::Explicit:
254
+ case RequirementSource::Inferred:
255
+ case RequirementSource::RequirementSignatureSelf:
256
+ currentPA = source->getRootPotentialArchetype ();
257
+ break ;
258
+
259
+ case RequirementSource::Concrete:
260
+ case RequirementSource::ProtocolRequirement:
261
+ case RequirementSource::Superclass:
262
+ break ;
263
+ }
264
+ }
265
+
266
+ assert (currentPA && " Missing root potential archetype" );
267
+
268
+ // Check whether anything of the potential archetypes in the path are
269
+ // equivalent to the end of the path.
270
+ auto rep = pa->getRepresentative ();
271
+ for (auto assocType : reversed (assocTypes)) {
272
+ // Check whether this potential archetype is in the same equivalence class.
273
+ if (currentPA->getRepresentative () == rep) return true ;
274
+
275
+ // Get the next nested type, but only if we've seen it before.
276
+ // FIXME: Feels hacky.
277
+ auto knownNested = currentPA->NestedTypes .find (assocType->getName ());
278
+ if (knownNested == currentPA->NestedTypes .end ()) return false ;
279
+ currentPA = knownNested->second .front ();
280
+ }
281
+
282
+ // FIXME: currentPA == pa?
283
+ return false ;
284
+ }
285
+
237
286
#define REQUIREMENT_SOURCE_FACTORY_BODY ( \
238
287
SourceKind, Parent, Storage, ExtraStorage, \
239
288
NumPotentialArchetypes) \
@@ -2836,10 +2885,18 @@ void GenericSignatureBuilder::checkRedundantConcreteTypeConstraints(
2836
2885
Type concreteType = representative->getConcreteType ();
2837
2886
assert (concreteType && " No concrete type to check" );
2838
2887
2839
- // Sort the concrete constraints, so we get a deterministic ordering of
2840
- // diagnostics.
2888
+ // Remove any self-derived constraints.
2841
2889
auto equivClass = representative->getOrCreateEquivalenceClass ();
2842
2890
auto &concreteConstraints = equivClass->concreteTypeConstraints ;
2891
+ concreteConstraints.erase (
2892
+ std::remove_if (concreteConstraints.begin (), concreteConstraints.end (),
2893
+ [&](const ConcreteConstraint &constraint) {
2894
+ return constraint.source ->isSelfDerivedSource (constraint.archetype );
2895
+ }),
2896
+ concreteConstraints.end ());
2897
+
2898
+ // Sort the concrete constraints, so we get a deterministic ordering of
2899
+ // diagnostics.
2843
2900
llvm::array_pod_sort (concreteConstraints.begin (), concreteConstraints.end ());
2844
2901
2845
2902
// Find a representative constraint to use for diagnostics.
@@ -2893,6 +2950,9 @@ void GenericSignatureBuilder::checkRedundantConcreteTypeConstraints(
2893
2950
representativeConstraint->archetype ->
2894
2951
getDependentType (genericParams, /* allowUnresolved=*/ true ),
2895
2952
representativeConstraint->concreteType );
2953
+
2954
+ (void )representativeConstraint->source ->isSelfDerivedSource (
2955
+ representativeConstraint->archetype );
2896
2956
};
2897
2957
2898
2958
// Go through the concrete constraints looking for redundancies.
0 commit comments