@@ -488,101 +488,103 @@ static void depthFirstSearch(
488
488
visitAdjacencies (node.getFixedBindings ());
489
489
}
490
490
491
- // / Perform a depth-first search.
492
- // /
493
- // / \param cg The constraint graph.
494
- // / \param typeVar The type variable we're searching from.
495
- // / \param preVisitNode Called before traversing a node. Must return \c
496
- // / false when the node has already been visited.
497
- // / \param visitConstraint Called before considering a constraint. If it
498
- // / returns \c false, that constraint will be skipped.
499
- static void depthFirstSearch (
500
- ConstraintGraph &cg,
491
+ // / Find the representative for the given type variable within the set
492
+ // / of representatives in a union-find data structure.
493
+ static TypeVariableType *findRepresentative (
501
494
TypeVariableType *typeVar,
502
- llvm::function_ref<bool (TypeVariableType *)> preVisitNode,
503
- llvm::function_ref<bool(Constraint *)> visitConstraint) {
504
- llvm::DenseSet<Constraint *> visitedConstraints;
505
- depthFirstSearch (cg, typeVar, preVisitNode, visitConstraint,
506
- visitedConstraints);
495
+ llvm::SmallDenseMap<TypeVariableType *, TypeVariableType *> &representatives) {
496
+ // If we don't have a record of this type variable, it is it's own
497
+ // representative.
498
+ auto known = representatives.find (typeVar);
499
+ if (known == representatives.end () || known->second == typeVar)
500
+ return typeVar;
501
+
502
+ // Find the representative of the parent.
503
+ auto parent = known->second ;
504
+ auto rep = findRepresentative (parent, representatives);
505
+ representatives[typeVar] = rep;
506
+
507
+ return rep;
507
508
}
508
509
509
510
unsigned ConstraintGraph::computeConnectedComponents (
510
511
std::vector<TypeVariableType *> &typeVars,
511
512
std::vector<unsigned > &components) {
512
- llvm::SmallDenseMap<TypeVariableType *, unsigned > componentsMap ;
513
+ llvm::SmallDenseMap<TypeVariableType *, TypeVariableType *> representatives ;
513
514
514
515
// Perform a depth-first search from each type variable to identify
515
516
// what component it is in.
516
- unsigned numComponents = 0 ;
517
+ llvm::DenseSet<Constraint *> visitedConstraints ;
517
518
for (auto typeVar : typeVars) {
518
- // If we've already assigned a component to this type variable, we're done.
519
- if (componentsMap.count (typeVar) > 0 )
519
+ // If we've already assigned a representative to this type variable,
520
+ // we're done.
521
+ if (representatives.count (typeVar) > 0 )
520
522
continue ;
521
523
522
- // Record this component.
523
- unsigned component = numComponents++;
524
-
525
524
// Perform a depth-first search to mark those type variables that are
526
525
// in the same component as this type variable.
527
526
depthFirstSearch (
528
527
*this , typeVar,
529
- [&](TypeVariableType *typeVar ) {
528
+ [&](TypeVariableType *found ) {
530
529
// If we have already seen this node, we're done.
531
- if (componentsMap.count (typeVar) > 0 ) {
532
- assert (componentsMap[typeVar] == component && " Wrong component?" );
533
- return false ;
534
- }
530
+ auto inserted = representatives.insert ({found, typeVar});
531
+ assert ((inserted.second || inserted.first ->second == typeVar) &&
532
+ " Wrong component?" );
535
533
536
- componentsMap[typeVar] = component;
537
- return true ;
534
+ return inserted.second ;
538
535
},
539
536
[&](Constraint *constraint) {
540
537
return true ;
541
- });
538
+ },
539
+ visitedConstraints);
542
540
}
543
541
544
- // Figure out which components have unbound type variables; these
545
- // are the only components and type variables we want to report.
546
- SmallVector< bool , 4 > componentHasUnboundTypeVar (numComponents, false ) ;
542
+ // Figure out which components have unbound type variables and/or constraints.
543
+ // These are the only components we want to report.
544
+ llvm::SmallDenseSet<TypeVariableType *> validComponents ;
547
545
for (auto typeVar : typeVars) {
548
546
// If this type variable has a fixed type, skip it.
549
547
if (CS.getFixedType (typeVar))
550
548
continue ;
551
549
552
- assert (componentsMap. count ( typeVar) > 0 );
553
- componentHasUnboundTypeVar[componentsMap[typeVar]] = true ;
550
+ auto rep = findRepresentative ( typeVar, representatives );
551
+ validComponents. insert (rep) ;
554
552
}
555
553
556
- // Renumber the old components to the new components.
557
- SmallVector<unsigned , 4 > componentRenumbering (numComponents, 0 );
558
- numComponents = 0 ;
559
- for (unsigned i : indices (componentRenumbering)) {
560
- // Skip components that have no unbound type variables.
561
- if (!componentHasUnboundTypeVar[i])
562
- continue ;
563
-
564
- componentRenumbering[i] = numComponents++;
554
+ for (auto constraint : visitedConstraints) {
555
+ for (auto typeVar : constraint->getTypeVariables ()) {
556
+ auto rep = findRepresentative (typeVar, representatives);
557
+ validComponents.insert (rep);
558
+ }
565
559
}
566
560
567
561
// Remove type variables in dead components and provide component
568
562
// numbers for those that remain.
563
+ llvm::SmallDenseMap<TypeVariableType *, unsigned > componentNumbers;
564
+ auto getComponentNumber = [&](TypeVariableType *typeVar) {
565
+ assert (typeVar == findRepresentative (typeVar, representatives));
566
+ auto inserted = componentNumbers.insert ({typeVar, componentNumbers.size ()});
567
+ return inserted.first ->second ;
568
+ };
569
+
569
570
typeVars.erase (
570
571
std::remove_if (
571
572
typeVars.begin (), typeVars.end (),
572
573
[&](TypeVariableType *typeVar) {
573
- assert (componentsMap. count ( typeVar) > 0 );
574
- unsigned component = componentsMap[typeVar];
574
+ auto rep = findRepresentative ( typeVar, representatives );
575
+
575
576
// Remove type variables in dead components.
576
- if (!componentHasUnboundTypeVar[component] )
577
+ if (validComponents. count (rep) == 0 )
577
578
return true ;
578
579
579
580
// Record the (renumbered) component.
580
- components.push_back (componentRenumbering[component] );
581
+ components.push_back (getComponentNumber (rep) );
581
582
return false ;
582
583
}),
583
584
typeVars.end ());
584
585
585
- return numComponents + getOrphanedConstraints ().size ();
586
+ assert (typeVars.size () == components.size ());
587
+ return componentNumbers.size () + getOrphanedConstraints ().size ();
586
588
}
587
589
588
590
0 commit comments