@@ -536,22 +536,31 @@ void ConstraintGraph::gatherConstraints(
536
536
537
537
#pragma mark Algorithms
538
538
539
- // / Depth-first search for connected components
540
- static void connectedComponentsDFS (
539
+ // / Perform a depth-first search.
540
+ // /
541
+ // / \param cg The constraint graph.
542
+ // / \param node The current constraint graph node.
543
+ // / \param nodeIndex The index of the current constraint graph node.
544
+ // / \param visitFixedBindings Whether to visit the nodes by following
545
+ // / fixed bindings.
546
+ // / \param preVisitNode Called before traversing a node. Must return \c
547
+ // / false when the node has already been visited.
548
+ // / \param visitConstraint Called before considering a constraint. If it
549
+ // / returns \c false, that constraint will be skipped.
550
+ // / \param visitedConstraints Set of already-visited constraints, used
551
+ // / internally to avoid duplicated work.
552
+ static void depthFirstSearch (
541
553
ConstraintGraph &cg,
542
554
ConstraintGraphNode &node,
543
555
unsigned nodeIndex,
544
- unsigned component,
545
- std::vector<unsigned > &components,
556
+ bool visitFixedBindings,
557
+ llvm::function_ref<bool (unsigned )> preVisitNode,
558
+ llvm::function_ref<bool(Constraint *)> visitConstraint,
546
559
llvm::DenseSet<Constraint *> &visitedConstraints) {
547
- // If we have already seen this node, we're done.
548
- unsigned &nodeComponent = components[nodeIndex];
549
- if (nodeComponent == component)
560
+ // Visit this node. If we've already seen it, bail out.
561
+ if (!preVisitNode (nodeIndex))
550
562
return ;
551
563
552
- assert (nodeComponent == components.size () && " Already in a component?" );
553
- nodeComponent = component;
554
-
555
564
// Local function to visit adjacent type variables.
556
565
auto visitAdjacencies = [&](ArrayRef<TypeVariableType *> adjTypeVars) {
557
566
for (auto adj : adjTypeVars) {
@@ -560,9 +569,10 @@ static void connectedComponentsDFS(
560
569
561
570
auto adjNodeAndIndex = cg.lookupNode (adj);
562
571
563
- // Visit the next node.
564
- connectedComponentsDFS (cg, adjNodeAndIndex.first , adjNodeAndIndex.second ,
565
- component, components, visitedConstraints);
572
+ // Recurse into this node.
573
+ depthFirstSearch (cg, adjNodeAndIndex.first , adjNodeAndIndex.second ,
574
+ visitFixedBindings, preVisitNode, visitConstraint,
575
+ visitedConstraints);
566
576
}
567
577
};
568
578
@@ -573,26 +583,49 @@ static void connectedComponentsDFS(
573
583
if (!visitedConstraints.insert (constraint).second )
574
584
continue ;
575
585
576
- visitAdjacencies (constraint->getTypeVariables ());
586
+ if (visitConstraint (constraint))
587
+ visitAdjacencies (constraint->getTypeVariables ());
577
588
}
578
589
579
- // Walk any type variables related via fixed bindings.
580
- visitAdjacencies (node.getFixedAdjacencies ());
581
-
582
590
// Visit all of the other nodes in the equivalence class.
583
591
auto nodeTypeVar = node.getTypeVariable ();
584
592
auto repTypeVar = cg.getConstraintSystem ().getRepresentative (nodeTypeVar);
585
- if (nodeTypeVar != repTypeVar) {
586
- // We are not the representative; visit the representative to be sure.
587
- auto repNodeAndIndex = cg.lookupNode (repTypeVar);
588
- connectedComponentsDFS (cg, repNodeAndIndex.first , repNodeAndIndex.second ,
589
- component, components, visitedConstraints);
590
- return ;
593
+ if (nodeTypeVar == repTypeVar) {
594
+ // We are the representative, so visit all of the other type variables
595
+ // in this equivalence class.
596
+ visitAdjacencies (node.getEquivalenceClass ());
597
+ } else {
598
+ // We are not the representative; visit the representative.
599
+ visitAdjacencies (repTypeVar);
600
+ }
601
+
602
+ if (visitFixedBindings) {
603
+ // Walk any type variables related via fixed bindings.
604
+ visitAdjacencies (node.getFixedAdjacencies ());
591
605
}
606
+ }
592
607
593
- // We are the representative, so visit all of the other type variables
594
- // in this equivalence class.
595
- visitAdjacencies (node.getEquivalenceClass ());
608
+ // / Perform a depth-first search.
609
+ // /
610
+ // / \param cg The constraint graph.
611
+ // / \param node The current constraint graph node.
612
+ // / \param nodeIndex The index of the current constraint graph node.
613
+ // / \param visitFixedBindings Whether to visit the nodes by following
614
+ // / fixed bindings.
615
+ // / \param preVisitNode Called before traversing a node. Must return \c
616
+ // / false when the node has already been visited.
617
+ // / \param visitConstraint Called before considering a constraint. If it
618
+ // / returns \c false, that constraint will be skipped.
619
+ static void depthFirstSearch (
620
+ ConstraintGraph &cg,
621
+ ConstraintGraphNode &node,
622
+ unsigned nodeIndex,
623
+ bool visitFixedBindings,
624
+ llvm::function_ref<bool (unsigned )> preVisitNode,
625
+ llvm::function_ref<bool(Constraint *)> visitConstraint) {
626
+ llvm::DenseSet<Constraint *> visitedConstraints;
627
+ depthFirstSearch (cg, node, nodeIndex, visitFixedBindings, preVisitNode,
628
+ visitConstraint, visitedConstraints);
596
629
}
597
630
598
631
unsigned ConstraintGraph::computeConnectedComponents (
@@ -628,8 +661,23 @@ unsigned ConstraintGraph::computeConnectedComponents(
628
661
unsigned component = numComponents++;
629
662
630
663
// Note that this node is part of this component, then visit it.
631
- connectedComponentsDFS (*this , nodeAndIndex.first , nodeAndIndex.second ,
632
- component, components, visitedConstraints);
664
+ depthFirstSearch (
665
+ *this , nodeAndIndex.first , nodeAndIndex.second ,
666
+ /* visitFixedBindings=*/ true ,
667
+ [&](unsigned nodeIndex) {
668
+ // If we have already seen this node, we're done.
669
+ unsigned &nodeComponent = components[nodeIndex];
670
+ if (nodeComponent == component)
671
+ return false ;
672
+
673
+ assert (nodeComponent == components.size () &&
674
+ " Already in a component?" );
675
+ nodeComponent = component;
676
+ return true ;
677
+ },
678
+ [&](Constraint *constraint) {
679
+ return true ;
680
+ });
633
681
}
634
682
635
683
// Figure out which components have unbound type variables; these
0 commit comments