@@ -89,8 +89,10 @@ ConstraintGraph::lookupNode(TypeVariableType *typeVar) {
89
89
// If this type variable is not the representative of its equivalence class,
90
90
// add it to its representative's set of equivalences.
91
91
auto typeVarRep = CS.getRepresentative (typeVar);
92
- if (typeVar != typeVarRep)
93
- mergeNodes (typeVar, typeVarRep);
92
+ if (typeVar != typeVarRep) {
93
+ mergeNodesPre (typeVar);
94
+ mergeNodes (typeVarRep, typeVar);
95
+ }
94
96
else if (auto fixed = CS.getFixedType (typeVarRep)) {
95
97
// Bind the type variable.
96
98
bindTypeVariable (typeVar, fixed);
@@ -251,32 +253,6 @@ void ConstraintGraphNode::addToEquivalenceClass(
251
253
if (EquivalenceClass.empty ())
252
254
EquivalenceClass.push_back (getTypeVariable ());
253
255
EquivalenceClass.append (typeVars.begin (), typeVars.end ());
254
-
255
- {
256
- for (auto *newMember : typeVars) {
257
- auto &node = CG[newMember];
258
-
259
- for (auto *constraint : node.getConstraints ()) {
260
- introduceToInference (constraint);
261
-
262
- if (!isUsefulForReferencedVars (constraint))
263
- continue ;
264
-
265
- notifyReferencedVars ([&](ConstraintGraphNode &referencedVar) {
266
- referencedVar.introduceToInference (constraint);
267
- });
268
- }
269
-
270
- // FIXME: Perhaps this also needs to be split up into two stages,
271
- // where the first stage runs before we merge the equivalence
272
- // classes
273
- node.notifyReferencingVars (
274
- [&](ConstraintGraphNode &node, Constraint *constraint) {
275
- node.retractFromInference (constraint);
276
- node.introduceToInference (constraint);
277
- });
278
- }
279
- }
280
256
}
281
257
282
258
void ConstraintGraphNode::truncateEquivalenceClass (unsigned prevSize) {
@@ -525,31 +501,60 @@ void ConstraintGraph::removeConstraint(TypeVariableType *typeVar,
525
501
OrphanedConstraints.pop_back ();
526
502
}
527
503
504
+ void ConstraintGraph::mergeNodesPre (TypeVariableType *typeVar2) {
505
+ // Merge equivalence class from the non-representative type variable.
506
+ auto &nonRepNode = (*this )[typeVar2];
507
+
508
+ for (auto *newMember : nonRepNode.getEquivalenceClassUnsafe ()) {
509
+ auto &node = (*this )[newMember];
510
+
511
+ node.notifyReferencingVars (
512
+ [&](ConstraintGraphNode &node, Constraint *constraint) {
513
+ node.retractFromInference (constraint);
514
+ });
515
+ }
516
+ }
517
+
528
518
void ConstraintGraph::mergeNodes (TypeVariableType *typeVar1,
529
519
TypeVariableType *typeVar2) {
530
- assert (CS.getRepresentative (typeVar1) == CS.getRepresentative (typeVar2) &&
531
- " type representatives don't match" );
532
-
533
520
// Retrieve the node for the representative that we're merging into.
534
- auto typeVarRep = CS.getRepresentative (typeVar1);
535
- auto &repNode = (*this )[typeVarRep];
521
+ ASSERT (CS.getRepresentative (typeVar1) == typeVar1);
536
522
537
- // Retrieve the node for the non-representative.
538
- assert ((typeVar1 == typeVarRep || typeVar2 == typeVarRep) &&
539
- " neither type variable is the new representative?" );
540
- auto typeVarNonRep = typeVar1 == typeVarRep? typeVar2 : typeVar1;
523
+ auto &repNode = (*this )[typeVar1];
541
524
542
525
// Record the change, if there are active scopes.
543
526
if (CS.isRecordingChanges ()) {
544
527
CS.recordChange (
545
528
SolverTrail::Change::ExtendedEquivalenceClass (
546
- typeVarRep ,
529
+ typeVar1 ,
547
530
repNode.getEquivalenceClass ().size ()));
548
531
}
549
532
550
533
// Merge equivalence class from the non-representative type variable.
551
- auto &nonRepNode = (*this )[typeVarNonRep];
552
- repNode.addToEquivalenceClass (nonRepNode.getEquivalenceClassUnsafe ());
534
+ auto &nonRepNode = (*this )[typeVar2];
535
+
536
+ auto typeVars = nonRepNode.getEquivalenceClassUnsafe ();
537
+ repNode.addToEquivalenceClass (typeVars);
538
+
539
+ for (auto *newMember : typeVars) {
540
+ auto &node = (*this )[newMember];
541
+
542
+ for (auto *constraint : node.getConstraints ()) {
543
+ repNode.introduceToInference (constraint);
544
+
545
+ if (!isUsefulForReferencedVars (constraint))
546
+ continue ;
547
+
548
+ repNode.notifyReferencedVars ([&](ConstraintGraphNode &referencedVar) {
549
+ referencedVar.introduceToInference (constraint);
550
+ });
551
+ }
552
+
553
+ node.notifyReferencingVars (
554
+ [&](ConstraintGraphNode &node, Constraint *constraint) {
555
+ node.introduceToInference (constraint);
556
+ });
557
+ }
553
558
}
554
559
555
560
void ConstraintGraph::bindTypeVariable (TypeVariableType *typeVar, Type fixed) {
0 commit comments