@@ -296,50 +296,8 @@ bool RequirementSource::isDerivedRequirement() const {
296
296
297
297
bool RequirementSource::isSelfDerivedSource (PotentialArchetype *pa,
298
298
bool &derivedViaConcrete) const {
299
- derivedViaConcrete = false ;
300
-
301
- // If it's not a derived requirement, it's not self-derived.
302
- if (!isDerivedRequirement ()) return false ;
303
-
304
- // / Keep track of all of the protocol requirements we've seen along the way.
305
- // / If we see the same requirement twice, we have a self-derived source.
306
- llvm::DenseSet<std::pair<PotentialArchetype *, ProtocolDecl *>>
307
- constraintsSeen;
308
-
309
- // Note that we've now seen a new conformance constraint, returning true if
310
- // we've seen it before.
311
- auto addConstraint = [&](PotentialArchetype *pa, ProtocolDecl *proto) {
312
- return !constraintsSeen.insert ({pa->getRepresentative (), proto}).second ;
313
- };
314
-
315
- return visitPotentialArchetypesAlongPath (
316
- [&](PotentialArchetype *currentPA, const RequirementSource *source) {
317
- switch (source->kind ) {
318
- case RequirementSource::Explicit:
319
- case RequirementSource::Inferred:
320
- case RequirementSource::QuietlyInferred:
321
- case RequirementSource::RequirementSignatureSelf:
322
- return false ;
323
-
324
- case RequirementSource::Parent:
325
- return currentPA->isInSameEquivalenceClassAs (pa);
326
-
327
- case RequirementSource::ProtocolRequirement:
328
- case RequirementSource::InferredProtocolRequirement:
329
- // Note whether we saw derivation through a concrete type.
330
- if (currentPA->isConcreteType ())
331
- derivedViaConcrete = true ;
332
-
333
- return addConstraint (currentPA, source->getProtocolDecl ());
334
-
335
- case RequirementSource::NestedTypeNameMatch:
336
- case RequirementSource::ConcreteTypeBinding:
337
- case RequirementSource::Concrete:
338
- case RequirementSource::Superclass:
339
- case RequirementSource::Derived:
340
- return false ;
341
- }
342
- }) == nullptr ;
299
+ return getMinimalConformanceSource (pa, /* proto=*/ nullptr , derivedViaConcrete)
300
+ != this ;
343
301
}
344
302
345
303
// / Replace 'Self' in the given dependent type (\c depTy) with the given
@@ -435,7 +393,7 @@ const RequirementSource *RequirementSource::getMinimalConformanceSource(
435
393
PotentialArchetype *rootPA = nullptr ;
436
394
Optional<std::pair<const RequirementSource *, const RequirementSource *>>
437
395
redundantSubpath;
438
- ( void ) visitPotentialArchetypesAlongPath (
396
+ bool isSelfDerived = visitPotentialArchetypesAlongPath (
439
397
[&](PotentialArchetype *parentPA, const RequirementSource *source) {
440
398
switch (source->kind ) {
441
399
case ProtocolRequirement:
@@ -459,9 +417,12 @@ const RequirementSource *RequirementSource::getMinimalConformanceSource(
459
417
return true ;
460
418
}
461
419
420
+ case Parent:
421
+ // FIXME: Ad hoc detection of recursive same-type constraints.
422
+ return !proto && parentPA->isInSameEquivalenceClassAs (currentPA);
423
+
462
424
case Concrete:
463
425
case Superclass:
464
- case Parent:
465
426
case Derived:
466
427
return false ;
467
428
case Explicit:
@@ -473,26 +434,31 @@ const RequirementSource *RequirementSource::getMinimalConformanceSource(
473
434
rootPA = parentPA;
474
435
return false ;
475
436
}
476
- });
437
+ }) == nullptr ;
477
438
478
439
// If we didn't already find a redundancy, check our end state.
479
440
if (!redundantSubpath && proto) {
480
441
if (auto startOfPath = addConstraint (currentPA, proto, this )) {
481
442
redundantSubpath = { startOfPath, this };
482
443
assert (startOfPath != this );
444
+ isSelfDerived = true ;
483
445
}
484
446
}
485
447
486
-
487
448
// If we saw a constraint twice, it's self-derived.
488
449
if (redundantSubpath) {
450
+ assert (isSelfDerived && " Not considered self-derived?" );
489
451
auto shorterSource =
490
452
withoutRedundantSubpath (redundantSubpath->first ,
491
453
redundantSubpath->second );
492
454
return shorterSource
493
455
->getMinimalConformanceSource (currentPA, proto, derivedViaConcrete);
494
456
}
495
457
458
+ // It's self-derived but we don't have a redundant subpath to eliminate.
459
+ if (isSelfDerived)
460
+ return nullptr ;
461
+
496
462
// If we haven't seen a protocol requirement, we're done.
497
463
if (!sawProtocolRequirement) return this ;
498
464
@@ -687,12 +653,14 @@ const RequirementSource *RequirementSource::withoutRedundantSubpath(
687
653
case ProtocolRequirement:
688
654
return parent->withoutRedundantSubpath (start, end)
689
655
->viaProtocolRequirement (builder, getStoredType (),
690
- getProtocolDecl (), /* inferred=*/ false );
656
+ getProtocolDecl (), /* inferred=*/ false ,
657
+ getWrittenRequirementLoc ());
691
658
692
659
case InferredProtocolRequirement:
693
660
return parent->withoutRedundantSubpath (start, end)
694
661
->viaProtocolRequirement (builder, getStoredType (),
695
- getProtocolDecl (), /* inferred=*/ true );
662
+ getProtocolDecl (), /* inferred=*/ true ,
663
+ getWrittenRequirementLoc ());
696
664
697
665
case Concrete:
698
666
return parent->withoutRedundantSubpath (start, end)
@@ -4273,37 +4241,72 @@ namespace {
4273
4241
// / \returns true if any derived-via-concrete constraints were found.
4274
4242
template <typename T>
4275
4243
bool removeSelfDerived (std::vector<Constraint<T>> &constraints,
4244
+ ProtocolDecl *proto,
4276
4245
bool dropDerivedViaConcrete = true ) {
4277
4246
bool anyDerivedViaConcrete = false ;
4278
- // Remove self-derived constraints.
4279
4247
Optional<Constraint<T>> remainingConcrete;
4248
+ SmallVector<Constraint<T>, 4 > minimalSources;
4280
4249
constraints.erase (
4281
4250
std::remove_if (constraints.begin (), constraints.end (),
4282
- [&](const Constraint<T> &constraint) {
4283
- bool derivedViaConcrete;
4284
- if (constraint.source ->isSelfDerivedSource (
4285
- constraint.archetype , derivedViaConcrete)) {
4286
- ++NumSelfDerived;
4287
- return true ;
4288
- }
4251
+ [&](const Constraint<T> &constraint) {
4252
+ bool derivedViaConcrete;
4253
+ auto minimalSource =
4254
+ constraint.source ->getMinimalConformanceSource (constraint.archetype ,
4255
+ proto,
4256
+ derivedViaConcrete);
4257
+ if (minimalSource != constraint.source ) {
4258
+ // The minimal source is smaller than the original source, so the
4259
+ // original source is self-derived.
4260
+ ++NumSelfDerived;
4261
+
4262
+ // FIXME: "proto" check means we don't do this for same-type
4263
+ // constraints, where we still seem to get minimization wrong.
4264
+ if (minimalSource && proto) {
4265
+ // Record a constraint with a minimized source.
4266
+ minimalSources.push_back (
4267
+ {constraint.archetype ,
4268
+ constraint.value ,
4269
+ minimalSource});
4270
+ }
4289
4271
4290
- if (!derivedViaConcrete)
4291
- return false ;
4272
+ return true ;
4273
+ }
4292
4274
4293
- anyDerivedViaConcrete = true ;
4275
+ if (!derivedViaConcrete)
4276
+ return false ;
4294
4277
4295
- if (!dropDerivedViaConcrete)
4296
- return false ;
4278
+ anyDerivedViaConcrete = true ;
4297
4279
4298
- // Drop derived-via-concrete requirements.
4299
- if (!remainingConcrete)
4300
- remainingConcrete = constraint;
4280
+ if (!dropDerivedViaConcrete)
4281
+ return false ;
4301
4282
4302
- ++NumSelfDerived;
4303
- return true ;
4304
- }),
4283
+ // Drop derived-via-concrete requirements.
4284
+ if (!remainingConcrete)
4285
+ remainingConcrete = constraint;
4286
+
4287
+ ++NumSelfDerived;
4288
+ return true ;
4289
+ }),
4305
4290
constraints.end ());
4306
4291
4292
+ // If we found any minimal sources, add them now, avoiding introducing any
4293
+ // redundant sources.
4294
+ if (!minimalSources.empty ()) {
4295
+ // Collect the sources we already know about.
4296
+ SmallPtrSet<const RequirementSource *, 4 > sources;
4297
+ for (const auto &constraint : constraints) {
4298
+ sources.insert (constraint.source );
4299
+ }
4300
+
4301
+ // Add any minimal sources we didn't know about.
4302
+ for (const auto &minimalSource : minimalSources) {
4303
+ if (sources.insert (minimalSource.source ).second ) {
4304
+ constraints.push_back (minimalSource);
4305
+ }
4306
+ }
4307
+ }
4308
+
4309
+ // If we only had concrete conformances, put one back.
4307
4310
if (constraints.empty () && remainingConcrete)
4308
4311
constraints.push_back (*remainingConcrete);
4309
4312
@@ -4329,7 +4332,7 @@ Constraint<T> GenericSignatureBuilder::checkConstraintList(
4329
4332
bool removeSelfDerived) {
4330
4333
assert (!constraints.empty () && " No constraints?" );
4331
4334
if (removeSelfDerived) {
4332
- ::removeSelfDerived (constraints);
4335
+ ::removeSelfDerived (constraints, /* proto= */ nullptr );
4333
4336
}
4334
4337
4335
4338
// Sort the constraints, so we get a deterministic ordering of diagnostics.
@@ -4483,73 +4486,8 @@ void GenericSignatureBuilder::checkConformanceConstraints(
4483
4486
// Remove self-derived constraints.
4484
4487
assert (!entry.second .empty () && " No constraints to work with?" );
4485
4488
4486
- // Local function to establish whether a conformance constraint is
4487
- // self-derived.
4488
- Optional<Constraint<ProtocolDecl *>> remainingConcrete;
4489
- SmallVector<Constraint<ProtocolDecl *>, 4 > minimalSources;
4490
- auto isSelfDerived =
4491
- [&](const Constraint<ProtocolDecl *> &constraint) {
4492
- // Determine whether there is a subpath of this requirement source that
4493
- // derives the same conformance.
4494
- bool derivedViaConcrete;
4495
- auto minimalSource =
4496
- constraint.source ->getMinimalConformanceSource (constraint.archetype ,
4497
- entry.first ,
4498
- derivedViaConcrete);
4499
- if (minimalSource != constraint.source ) {
4500
- // The minimal source is smaller than the original source, so the
4501
- // original source is self-derived.
4502
- ++NumSelfDerived;
4503
-
4504
- if (minimalSource && minimalSource->isDerivedRequirement ()) {
4505
- // Record a constraint with a minimized source.
4506
- minimalSources.push_back (
4507
- {minimalSource->getAffectedPotentialArchetype (),
4508
- constraint.value ,
4509
- minimalSource});
4510
- }
4511
-
4512
- return true ;
4513
- }
4514
-
4515
- if (!derivedViaConcrete)
4516
- return false ;
4517
-
4518
- // Drop derived-via-concrete requirements.
4519
- if (!remainingConcrete)
4520
- remainingConcrete = constraint;
4521
-
4522
- ++NumSelfDerived;
4523
- return true ;
4524
- };
4525
-
4526
- // Erase all self-derived constraints.
4527
- entry.second .erase (
4528
- std::remove_if (entry.second .begin (), entry.second .end (), isSelfDerived),
4529
- entry.second .end ());
4530
-
4531
- // If we found any mininal sources, add them now, avoiding introducing any
4532
- // redundant sources.
4533
- if (!minimalSources.empty ()) {
4534
- // Collect the sources we already know about.
4535
- SmallPtrSet<const RequirementSource *, 4 > sources;
4536
- for (const auto &constraint : entry.second ) {
4537
- sources.insert (constraint.source );
4538
- }
4539
-
4540
- // Add any minimal sources we didn't know about.
4541
- for (const auto &minimalSource : minimalSources) {
4542
- if (sources.insert (minimalSource.source ).second ) {
4543
- entry.second .push_back (minimalSource);
4544
- }
4545
- }
4546
- }
4547
-
4548
- // If we only had concrete conformances, put one back.
4549
- if (entry.second .empty () && remainingConcrete)
4550
- entry.second .push_back (*remainingConcrete);
4551
-
4552
- assert (!entry.second .empty () && " All constraints were self-derived!" );
4489
+ // Remove any self-derived constraints.
4490
+ removeSelfDerived (entry.second , entry.first );
4553
4491
4554
4492
checkConstraintList<ProtocolDecl *, ProtocolDecl *>(
4555
4493
genericParams, entry.second ,
@@ -4788,7 +4726,8 @@ void GenericSignatureBuilder::checkSameTypeConstraints(
4788
4726
auto &constraints = entry.second ;
4789
4727
4790
4728
// Remove self-derived constraints.
4791
- if (removeSelfDerived (constraints, /* dropDerivedViaConcrete=*/ false ))
4729
+ if (removeSelfDerived (constraints, /* proto=*/ nullptr ,
4730
+ /* dropDerivedViaConcrete=*/ false ))
4792
4731
anyDerivedViaConcrete = true ;
4793
4732
4794
4733
// Sort the constraints, so we get a deterministic ordering of diagnostics.
@@ -4872,7 +4811,7 @@ void GenericSignatureBuilder::checkSameTypeConstraints(
4872
4811
auto &constraints = entry.second ;
4873
4812
4874
4813
// Remove derived-via-concrete constraints.
4875
- (void )removeSelfDerived (constraints);
4814
+ (void )removeSelfDerived (constraints, /* proto= */ nullptr );
4876
4815
anyDerivedViaConcrete = true ;
4877
4816
}
4878
4817
}
0 commit comments