@@ -271,6 +271,144 @@ bool RequirementSource::isSelfDerivedSource(PotentialArchetype *pa) const {
271
271
return false ;
272
272
}
273
273
274
+ // / Replace 'Self' in the given dependent type (\c depTy) with the given
275
+ // / potential archetype, producing a new potential archetype that refers to
276
+ // / the nested type. This limited operation makes sure that it does not
277
+ // / create any new potential archetypes along the way, so it should only be
278
+ // / used in cases where we're reconstructing something that we know exists.
279
+ static PotentialArchetype *replaceSelfWithPotentialArchetype (
280
+ PotentialArchetype *selfPA, Type depTy) {
281
+ if (auto depMemTy = depTy->getAs <DependentMemberType>()) {
282
+ // Recurse to produce the potential archetype for the base.
283
+ auto basePA = replaceSelfWithPotentialArchetype (selfPA,
284
+ depMemTy->getBase ());
285
+
286
+ PotentialArchetype *nestedPAByName = nullptr ;
287
+
288
+ auto assocType = depMemTy->getAssocType ();
289
+ auto name = depMemTy->getName ();
290
+ auto findNested = [&](PotentialArchetype *pa) -> PotentialArchetype * {
291
+ const auto &nested = pa->getNestedTypes ();
292
+ auto found = nested.find (name);
293
+
294
+ if (found == nested.end ()) return nullptr ;
295
+ if (found->second .empty ()) return nullptr ;
296
+
297
+ // Note that we've found a nested PA by name.
298
+ if (!nestedPAByName) {
299
+ nestedPAByName = found->second .front ();
300
+ }
301
+
302
+ // If we don't have an associated type to look for, we're done.
303
+ if (!assocType) return nestedPAByName;
304
+
305
+ // Look for a nested PA matching the associated type.
306
+ for (auto nestedPA : found->second ) {
307
+ if (nestedPA->getResolvedAssociatedType () == assocType)
308
+ return nestedPA;
309
+ }
310
+
311
+ return nullptr ;
312
+ };
313
+
314
+ // First, look in the base potential archetype for the member we want.
315
+ if (auto result = findNested (basePA))
316
+ return result;
317
+
318
+ // Otherwise, look elsewhere in the equivalence class of the base potential
319
+ // archetype.
320
+ for (auto otherBasePA : basePA->getEquivalenceClassMembers ()) {
321
+ if (otherBasePA == basePA) continue ;
322
+
323
+ if (auto result = findNested (otherBasePA))
324
+ return result;
325
+ }
326
+
327
+ assert (nestedPAByName && " Didn't find the associated type we wanted" );
328
+ return nestedPAByName;
329
+ }
330
+
331
+ assert (depTy->is <GenericTypeParamType>() && " missing Self?" );
332
+ return selfPA;
333
+ }
334
+
335
+ bool RequirementSource::isSelfDerivedConformance (PotentialArchetype *currentPA,
336
+ ProtocolDecl *proto) const {
337
+ // / Keep track of all of the requirements we've seen along the way. If
338
+ // / we see the same requirement twice, it's a self-derived conformance.
339
+ llvm::DenseSet<std::pair<PotentialArchetype *, ProtocolDecl *>>
340
+ constraintsSeen;
341
+
342
+ // Note that we've now seen a new constraint, returning true if we've seen
343
+ // it before.
344
+ auto addConstraint = [&](PotentialArchetype *pa, ProtocolDecl *proto) {
345
+ return !constraintsSeen.insert ({pa->getRepresentative (), proto}).second ;
346
+ };
347
+
348
+ // Insert our end state.
349
+ constraintsSeen.insert ({currentPA->getRepresentative (), proto});
350
+
351
+ // Follow from the root of the
352
+ std::function<PotentialArchetype *(const RequirementSource *source)>
353
+ followFromRoot;
354
+
355
+ bool sawProtocolRequirement = false ;
356
+ followFromRoot = [&](const RequirementSource *source) -> PotentialArchetype *{
357
+ // Handle protocol requirements.
358
+ if (source->kind == ProtocolRequirement) {
359
+ sawProtocolRequirement = true ;
360
+
361
+ // Compute the base potential archetype.
362
+ auto basePA = followFromRoot (source->parent );
363
+ if (!basePA) return nullptr ;
364
+
365
+ // The base potential archetype must conform to the protocol in which
366
+ // this requirement results.
367
+ if (addConstraint (basePA, source->getProtocolDecl ()))
368
+ return nullptr ;
369
+
370
+ // If there's no stored type, return the base.
371
+ if (!source->getStoredType ()) return basePA;
372
+
373
+ // Follow the dependent type in the protocol requirement.
374
+ return replaceSelfWithPotentialArchetype (basePA, source->getStoredType ());
375
+ }
376
+
377
+ if (source->kind == Parent) {
378
+ // Compute the base potential archetype.
379
+ auto basePA = followFromRoot (source->parent );
380
+ if (!basePA) return nullptr ;
381
+
382
+ // Add on this associated type.
383
+ return replaceSelfWithPotentialArchetype (
384
+ basePA,
385
+ source->getAssociatedType ()->getDeclaredInterfaceType ());
386
+ }
387
+
388
+ if (source->parent )
389
+ return followFromRoot (source->parent );
390
+
391
+ // We are at a root, so the root potential archetype is our result.
392
+ auto rootPA = source->getRootPotentialArchetype ();
393
+
394
+ // If we haven't seen a protocol requirement, we're done.
395
+ if (!sawProtocolRequirement) return rootPA;
396
+
397
+ // The root archetype might be a nested type, which implies constraints
398
+ // for each of the protocols of the associated types referenced (if any).
399
+ for (auto pa = rootPA; pa->getParent (); pa = pa->getParent ()) {
400
+ if (auto assocType = pa->getResolvedAssociatedType ()) {
401
+ if (addConstraint (pa->getParent (), assocType->getProtocol ()))
402
+ return nullptr ;
403
+ }
404
+ }
405
+
406
+ return rootPA;
407
+ };
408
+
409
+ return followFromRoot (this ) == nullptr ;
410
+ }
411
+
274
412
#define REQUIREMENT_SOURCE_FACTORY_BODY (ProfileArgs, ConstructorArgs, \
275
413
NumProtocolDecls, WrittenReq) \
276
414
llvm::FoldingSetNodeID nodeID; \
@@ -3312,7 +3450,18 @@ void GenericSignatureBuilder::checkConformanceConstraints(
3312
3450
return ;
3313
3451
3314
3452
for (auto &entry : equivClass->conformsTo ) {
3315
- checkConstraintList<ProtocolDecl *>(
3453
+ // Remove self-derived constraints.
3454
+ assert (!entry.second .empty () && " No constraints to work with?" );
3455
+ entry.second .erase (
3456
+ std::remove_if (entry.second .begin (), entry.second .end (),
3457
+ [&](const Constraint<ProtocolDecl *> &constraint) {
3458
+ return constraint.source ->isSelfDerivedConformance (
3459
+ constraint.archetype , entry.first );
3460
+ }),
3461
+ entry.second .end ());
3462
+ assert (!entry.second .empty () && " All constraints were self-derived!" );
3463
+
3464
+ checkConstraintList<ProtocolDecl *, ProtocolDecl *>(
3316
3465
genericParams, entry.second ,
3317
3466
[](const Constraint<ProtocolDecl *> &constraint) {
3318
3467
return true ;
@@ -3323,7 +3472,9 @@ void GenericSignatureBuilder::checkConformanceConstraints(
3323
3472
},
3324
3473
None,
3325
3474
diag::redundant_conformance_constraint,
3326
- diag::redundant_conformance_here);
3475
+ diag::redundant_conformance_here,
3476
+ [](ProtocolDecl *proto) { return proto; },
3477
+ /* removeSelfDerived=*/ false );
3327
3478
}
3328
3479
}
3329
3480
0 commit comments