@@ -89,8 +89,10 @@ ConstraintGraph::lookupNode(TypeVariableType *typeVar) {
8989 // If this type variable is not the representative of its equivalence class,
9090 // add it to its representative's set of equivalences.
9191 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+ }
9496 else if (auto fixed = CS.getFixedType (typeVarRep)) {
9597 // Bind the type variable.
9698 bindTypeVariable (typeVar, fixed);
@@ -251,32 +253,6 @@ void ConstraintGraphNode::addToEquivalenceClass(
251253 if (EquivalenceClass.empty ())
252254 EquivalenceClass.push_back (getTypeVariable ());
253255 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- }
280256}
281257
282258void ConstraintGraphNode::truncateEquivalenceClass (unsigned prevSize) {
@@ -525,31 +501,60 @@ void ConstraintGraph::removeConstraint(TypeVariableType *typeVar,
525501 OrphanedConstraints.pop_back ();
526502}
527503
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+
528518void ConstraintGraph::mergeNodes (TypeVariableType *typeVar1,
529519 TypeVariableType *typeVar2) {
530- assert (CS.getRepresentative (typeVar1) == CS.getRepresentative (typeVar2) &&
531- " type representatives don't match" );
532-
533520 // 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);
536522
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];
541524
542525 // Record the change, if there are active scopes.
543526 if (CS.isRecordingChanges ()) {
544527 CS.recordChange (
545528 SolverTrail::Change::ExtendedEquivalenceClass (
546- typeVarRep ,
529+ typeVar1 ,
547530 repNode.getEquivalenceClass ().size ()));
548531 }
549532
550533 // 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+ }
553558}
554559
555560void ConstraintGraph::bindTypeVariable (TypeVariableType *typeVar, Type fixed) {
0 commit comments