@@ -5381,61 +5381,57 @@ void GenericSignatureBuilder::checkConformanceConstraints(
5381
5381
}
5382
5382
}
5383
5383
5384
- // / Perform a depth-first search from the given potential archetype through
5385
- // / the *implicit* same-type constraints.
5386
- // /
5387
- // / \param pa The potential archetype to visit.
5388
- // / \param paToComponent A mapping from each potential archetype to its
5389
- // / component number.
5390
- // / \param component The component number we're currently visiting.
5391
- // /
5392
- // / \returns the best archetype anchor seen so far.
5393
- static PotentialArchetype *sameTypeDFS (PotentialArchetype *pa,
5394
- unsigned component,
5395
- llvm::SmallDenseMap<PotentialArchetype *, unsigned > &paToComponent) {
5396
- PotentialArchetype *anchor = pa;
5397
-
5398
- // If we've already visited this potential archetype, we're done.
5399
- if (!paToComponent.insert ({pa, component}).second ) return anchor;
5400
-
5401
- // Visit its adjacent potential archetypes.
5402
- for (const auto &constraint : pa->getSameTypeConstraints ()) {
5403
- // Treat nested-type-name-match constraints specially.
5404
- if (constraint.source ->getRoot ()->kind ==
5405
- RequirementSource::NestedTypeNameMatch)
5406
- continue ;
5407
-
5408
- // Skip non-derived constraints.
5409
- if (!constraint.source ->isDerivedRequirement ()) continue ;
5410
-
5411
- auto newAnchor =
5412
- sameTypeDFS (constraint.value , component, paToComponent);
5413
-
5414
- // If this type is better than the anchor, use it for the anchor.
5415
- if (compareDependentTypes (&newAnchor, &anchor) < 0 )
5416
- anchor = newAnchor;
5417
- }
5418
-
5419
- return anchor;
5420
- }
5421
-
5422
5384
namespace swift {
5423
5385
bool operator <(const DerivedSameTypeComponent &lhs,
5424
5386
const DerivedSameTypeComponent &rhs) {
5425
5387
return compareDependentTypes (&lhs.anchor , &rhs.anchor ) < 0 ;
5426
5388
}
5427
5389
} // namespace swift
5428
5390
5391
+ // / Find the representative in a simple union-find data structure of
5392
+ // / integral values.
5393
+ static unsigned findRepresentative (SmallVectorImpl<unsigned > &parents,
5394
+ unsigned index) {
5395
+ if (parents[index] == index) return index;
5396
+
5397
+ return parents[index] = findRepresentative (parents, parents[index]);
5398
+ }
5399
+
5400
+ // / Union the same-type components denoted by \c index1 and \c index2.
5401
+ // /
5402
+ // / \param successThreshold Returns true when two sets have been joined
5403
+ // / and both representatives are below the threshold. The default of 0
5404
+ // / is equivalent to \c successThreshold == parents.size().
5405
+ // /
5406
+ // / \returns \c true if the two components were separate and have now
5407
+ // / been joined; \c false if they were already in the same set.
5408
+ static bool unionSets (SmallVectorImpl<unsigned > &parents,
5409
+ unsigned index1, unsigned index2,
5410
+ unsigned successThreshold = 0 ) {
5411
+ // Find the representatives of each component class.
5412
+ unsigned rep1 = findRepresentative (parents, index1);
5413
+ unsigned rep2 = findRepresentative (parents, index2);
5414
+ if (rep1 == rep2) return false ;
5415
+
5416
+ // Point at the lowest-numbered representative.
5417
+ if (rep1 < rep2)
5418
+ parents[rep2] = rep1;
5419
+ else
5420
+ parents[rep1] = rep2;
5421
+
5422
+ return (successThreshold == 0 ) ||
5423
+ (rep1 < successThreshold && rep2 < successThreshold);
5424
+ }
5425
+
5429
5426
// / Computes the ordered set of archetype anchors required to form a minimum
5430
5427
// / spanning tree among the connected components formed by only the derived
5431
- // / same-type requirements within the equivalence class of \c rep .
5428
+ // / same-type requirements within the equivalence class \c equivClass .
5432
5429
// /
5433
- // / The equivalence class of the given representative potential archetype
5434
- // / (\c rep) contains all potential archetypes that are made equivalent by
5435
- // / the known set of same-type constraints, which includes both directly-
5436
- // / stated same-type constraints (e.g., \c T.A == T.B) as well as same-type
5437
- // / constraints that are implied either because the names coincide (e.g.,
5438
- // / \c T[.P1].A == T[.P2].A) or due to a requirement in a protocol.
5430
+ // / The equivalence class contains all potential archetypes that are made
5431
+ // / equivalent by the known set of same-type constraints, which includes both
5432
+ // / directly-stated same-type constraints (e.g., \c T.A == T.B) as well as
5433
+ // / same-type constraints that are implied either because the names coincide
5434
+ // / (e.g., \c T[.P1].A == T[.P2].A) or due to a requirement in a protocol.
5439
5435
// /
5440
5436
// / The equivalence class of the given representative potential archetype
5441
5437
// / (\c rep) is formed from a graph whose vertices are the potential archetypes
@@ -5464,21 +5460,68 @@ namespace swift {
5464
5460
// / canonical edges connects vertex i to vertex i+1 for i in 0..<size-1.
5465
5461
static void computeDerivedSameTypeComponents (
5466
5462
GenericSignatureBuilder &builder,
5467
- PotentialArchetype *rep ,
5463
+ EquivalenceClass *equivClass ,
5468
5464
llvm::SmallDenseMap<PotentialArchetype *, unsigned > &componentOf){
5469
- // Perform a depth-first search to identify the components.
5470
- auto equivClass = rep->getOrCreateEquivalenceClass (builder);
5465
+ // Set up the array of "parents" in the union-find data structure.
5466
+ llvm::SmallDenseMap<CanType, unsigned > parentIndices;
5467
+ SmallVector<unsigned , 4 > parents;
5468
+ for (unsigned i : indices (equivClass->members )) {
5469
+ Type depType = equivClass->members [i]->getDependentType ({ });
5470
+ parentIndices[depType->getCanonicalType ()] = parents.size ();
5471
+ parents.push_back (i);
5472
+ }
5473
+
5474
+ // Walk all of the same-type constraints, performing a union-find operation.
5475
+ for (const auto &entry : equivClass->sameTypeConstraints ) {
5476
+ for (const auto &constraint : entry.second ) {
5477
+ // Treat nested-type-name-match constraints specially.
5478
+ if (constraint.source ->getRoot ()->kind ==
5479
+ RequirementSource::NestedTypeNameMatch)
5480
+ continue ;
5481
+
5482
+ // Skip non-derived constraints.
5483
+ if (!constraint.source ->isDerivedRequirement ()) continue ;
5484
+
5485
+ CanType source =
5486
+ constraint.getSubjectDependentType ({ })->getCanonicalType ();
5487
+ CanType target =
5488
+ constraint.value ->getDependentType ({ })->getCanonicalType ();
5489
+
5490
+ assert (parentIndices.count (source) == 1 && " Missing source" );
5491
+ assert (parentIndices.count (target) == 1 && " Missing target" );
5492
+ unionSets (parents, parentIndices[source], parentIndices[target]);
5493
+ }
5494
+ }
5495
+
5496
+ // Compute and record the components.
5471
5497
auto &components = equivClass->derivedSameTypeComponents ;
5472
- for (auto pa : rep->getEquivalenceClassMembers ()) {
5473
- // If we've already seen this potential archetype, there's nothing else to
5474
- // do.
5475
- if (componentOf.count (pa) != 0 ) continue ;
5498
+ for (unsigned i : indices (equivClass->members )) {
5499
+ auto pa = equivClass->members [i];
5500
+ CanType depType = pa->getDependentType ({ })->getCanonicalType ();
5501
+
5502
+ // Find the representative of this set.
5503
+ assert (parentIndices.count (depType) == 1 && " Unknown member?" );
5504
+ unsigned index = parentIndices[depType];
5505
+ unsigned representative = findRepresentative (parents, index);
5506
+
5507
+ // If this is the representative, add a component for it.
5508
+ if (representative == index) {
5509
+ componentOf[pa] = components.size ();
5510
+ components.push_back (DerivedSameTypeComponent{pa, nullptr });
5511
+ continue ;
5512
+ }
5476
5513
5477
- // Find all of the potential archetypes within this connected component.
5478
- auto anchor = sameTypeDFS (pa, components.size (), componentOf);
5514
+ // This is not the representative; point at the component of the
5515
+ // representative.
5516
+ auto representativePA = equivClass->members [representative];
5517
+ assert (componentOf.count (representativePA) == 1 &&
5518
+ " Missing representative component?" );
5519
+ unsigned componentIndex = componentOf[representativePA];
5520
+ componentOf[pa] = componentIndex;
5479
5521
5480
- // Record the anchor.
5481
- components.push_back ({anchor, nullptr });
5522
+ // If this is a better anchor, record it.
5523
+ if (compareDependentTypes (&pa, &components[componentIndex].anchor ) < 0 )
5524
+ components[componentIndex].anchor = pa;
5482
5525
}
5483
5526
5484
5527
// If there is a concrete type, figure out the best concrete type anchor
@@ -5554,42 +5597,6 @@ void IntercomponentEdge::dump() const {
5554
5597
llvm::errs () << " \n " ;
5555
5598
}
5556
5599
5557
- // / Find the representative in a simple union-find data structure of
5558
- // / integral values.
5559
- static unsigned findRepresentative (SmallVectorImpl<unsigned > &parents,
5560
- unsigned index) {
5561
- if (parents[index] == index) return index;
5562
-
5563
- return parents[index] = findRepresentative (parents, parents[index]);
5564
- }
5565
-
5566
-
5567
- // / Union the same-type components denoted by \c index1 and \c index2.
5568
- // /
5569
- // / \param successThreshold Returns true when two sets have been joined
5570
- // / and both representatives are below the threshold. The default of 0
5571
- // / is equivalent to \c successThreshold == parents.size().
5572
- // /
5573
- // / \returns \c true if the two components were separate and have now
5574
- // / been joined; \c false if they were already in the same set.
5575
- static bool unionSets (SmallVectorImpl<unsigned > &parents,
5576
- unsigned index1, unsigned index2,
5577
- unsigned successThreshold = 0 ) {
5578
- // Find the representatives of each component class.
5579
- unsigned rep1 = findRepresentative (parents, index1);
5580
- unsigned rep2 = findRepresentative (parents, index2);
5581
- if (rep1 == rep2) return false ;
5582
-
5583
- // Point at the lowest-numbered representative.
5584
- if (rep1 < rep2)
5585
- parents[rep2] = rep1;
5586
- else
5587
- parents[rep1] = rep2;
5588
-
5589
- return (successThreshold == 0 ) ||
5590
- (rep1 < successThreshold && rep2 < successThreshold);
5591
- }
5592
-
5593
5600
// / Determine whether the removal of the given edge will disconnect the
5594
5601
// / nodes \c from and \c to within the given equivalence class.
5595
5602
static bool removalDisconnectsEquivalenceClass (
@@ -5883,7 +5890,7 @@ void GenericSignatureBuilder::checkSameTypeConstraints(
5883
5890
// Compute the components in the subgraph of the same-type constraint graph
5884
5891
// that includes only derived constraints.
5885
5892
llvm::SmallDenseMap<PotentialArchetype *, unsigned > componentOf;
5886
- computeDerivedSameTypeComponents (*this , pa , componentOf);
5893
+ computeDerivedSameTypeComponents (*this , equivClass , componentOf);
5887
5894
5888
5895
// Go through all of the same-type constraints, collecting all of the
5889
5896
// non-derived constraints to put them into bins: intra-component and
0 commit comments