@@ -83,6 +83,18 @@ ConstraintGraph::lookupNode(TypeVariableType *typeVar) {
83
83
return { *nodePtr, index };
84
84
}
85
85
86
+ llvm::TinyPtrVector<TypeVariableType *>
87
+ ConstraintGraphNode::getFixedAdjacencies () const {
88
+ llvm::TinyPtrVector<TypeVariableType *> results;
89
+ for (auto adj : getAdjacencies ()) {
90
+ auto adjInfo = AdjacencyInfo.find (adj);
91
+ assert (adjInfo != AdjacencyInfo.end ());
92
+ if (adjInfo->second .FixedBinding )
93
+ results.push_back (adj);
94
+ }
95
+ return results;
96
+ }
97
+
86
98
ArrayRef<TypeVariableType *> ConstraintGraphNode::getEquivalenceClass () const {
87
99
assert (TypeVar == TypeVar->getImpl ().getRepresentative (nullptr ) &&
88
100
" Can't request equivalence class from non-representative type var" );
@@ -525,40 +537,62 @@ void ConstraintGraph::gatherConstraints(
525
537
#pragma mark Algorithms
526
538
527
539
// / Depth-first search for connected components
528
- static void connectedComponentsDFS (ConstraintGraph &cg,
529
- ConstraintGraphNode &node,
530
- unsigned component,
531
- std::vector<unsigned > &components) {
532
- // Local function that recurses on the given set of type variables.
533
- auto visitAdjacencies = [&](ArrayRef<TypeVariableType *> typeVars) {
534
- for (auto adj : typeVars) {
535
- auto nodeAndIndex = cg.lookupNode (adj);
536
- // If we've already seen this node in this component, we're done.
537
- unsigned &curComponent = components[nodeAndIndex.second ];
538
- if (curComponent == component)
540
+ static void connectedComponentsDFS (
541
+ ConstraintGraph &cg,
542
+ ConstraintGraphNode &node,
543
+ unsigned nodeIndex,
544
+ unsigned component,
545
+ std::vector<unsigned > &components,
546
+ llvm::DenseSet<Constraint *> &visitedConstraints) {
547
+ // If we have already seen this node, we're done.
548
+ unsigned &nodeComponent = components[nodeIndex];
549
+ if (nodeComponent == component)
550
+ return ;
551
+
552
+ assert (nodeComponent == components.size () && " Already in a component?" );
553
+ nodeComponent = component;
554
+
555
+ // Local function to visit adjacent type variables.
556
+ auto visitAdjacencies = [&](ArrayRef<TypeVariableType *> adjTypeVars) {
557
+ for (auto adj : adjTypeVars) {
558
+ if (adj == node.getTypeVariable ())
539
559
continue ;
540
560
541
- // Mark this node as part of this connected component, then recurse.
542
- assert (curComponent == components.size () && " Already in a component?" );
543
- curComponent = component;
544
- connectedComponentsDFS (cg, nodeAndIndex.first , component, components);
561
+ auto adjNodeAndIndex = cg.lookupNode (adj);
562
+
563
+ // Visit the next node.
564
+ connectedComponentsDFS (cg, adjNodeAndIndex.first , adjNodeAndIndex.second ,
565
+ component, components, visitedConstraints);
545
566
}
546
567
};
547
568
548
- // Recurse to mark adjacent nodes as part of this connected component.
549
- visitAdjacencies (node.getAdjacencies ());
550
-
551
- // Figure out the representative for this type variable.
552
- auto &cs = cg.getConstraintSystem ();
553
- auto typeVarRep = cs.getRepresentative (node.getTypeVariable ());
554
- if (typeVarRep == node.getTypeVariable ()) {
555
- // This type variable is the representative of its set; visit all of the
556
- // other type variables in the same equivalence class.
557
- visitAdjacencies (node.getEquivalenceClass ().slice (1 ));
558
- } else {
559
- // Otherwise, visit the representative of the set.
560
- visitAdjacencies (typeVarRep);
569
+ // Walk all of the constraints associated with this node to find related
570
+ // nodes.
571
+ for (auto constraint : node.getConstraints ()) {
572
+ // If we've already seen this constraint, skip it.
573
+ if (!visitedConstraints.insert (constraint).second )
574
+ continue ;
575
+
576
+ visitAdjacencies (constraint->getTypeVariables ());
577
+ }
578
+
579
+ // Walk any type variables related via fixed bindings.
580
+ visitAdjacencies (node.getFixedAdjacencies ());
581
+
582
+ // Visit all of the other nodes in the equivalence class.
583
+ auto nodeTypeVar = node.getTypeVariable ();
584
+ 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 ;
561
591
}
592
+
593
+ // We are the representative, so visit all of the other type variables
594
+ // in this equivalence class.
595
+ visitAdjacencies (node.getEquivalenceClass ());
562
596
}
563
597
564
598
unsigned ConstraintGraph::computeConnectedComponents (
@@ -570,12 +604,14 @@ unsigned ConstraintGraph::computeConnectedComponents(
570
604
typeVars.clear ();
571
605
572
606
// Initialize the components with component == # of type variables,
573
- // a sentinel value indicating
607
+ // a sentinel value indicating that we have yet to assign a component to
608
+ // that particular type variable.
574
609
unsigned numTypeVariables = TypeVariables.size ();
575
610
components.assign (numTypeVariables, numTypeVariables);
576
611
577
612
// Perform a depth-first search from each type variable to identify
578
613
// what component it is in.
614
+ llvm::DenseSet<Constraint *> visitedConstraints;
579
615
unsigned numComponents = 0 ;
580
616
for (unsigned i = 0 ; i != numTypeVariables; ++i) {
581
617
auto typeVar = TypeVariables[i];
@@ -592,8 +628,8 @@ unsigned ConstraintGraph::computeConnectedComponents(
592
628
unsigned component = numComponents++;
593
629
594
630
// Note that this node is part of this component, then visit it.
595
- curComponent = component;
596
- connectedComponentsDFS (* this , nodeAndIndex. first , component, components);
631
+ connectedComponentsDFS (* this , nodeAndIndex. first , nodeAndIndex. second ,
632
+ component, components, visitedConstraints );
597
633
}
598
634
599
635
// Figure out which components have unbound type variables; these
0 commit comments