@@ -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);
@@ -177,7 +179,9 @@ void ConstraintGraphNode::removeConstraint(Constraint *constraint) {
177179 Constraints.pop_back ();
178180}
179181
180- void ConstraintGraphNode::notifyReferencingVars () const {
182+ void ConstraintGraphNode::notifyReferencingVars (
183+ llvm::function_ref<void (ConstraintGraphNode &,
184+ Constraint *)> notification) const {
181185 SmallVector<TypeVariableType *, 4 > stack;
182186
183187 stack.push_back (TypeVar);
@@ -199,7 +203,7 @@ void ConstraintGraphNode::notifyReferencingVars() const {
199203 affectedVar->getImpl ().getRepresentative (/* record=*/ nullptr );
200204
201205 if (!repr->getImpl ().getFixedType (/* record=*/ nullptr ))
202- CG[repr]. reintroduceToInference ( constraint);
206+ notification ( CG[repr], constraint);
203207 }
204208 }
205209 };
@@ -236,7 +240,7 @@ void ConstraintGraphNode::notifyReferencingVars() const {
236240}
237241
238242void ConstraintGraphNode::notifyReferencedVars (
239- llvm::function_ref<void (ConstraintGraphNode &)> notification) {
243+ llvm::function_ref<void (ConstraintGraphNode &)> notification) const {
240244 for (auto *fixedBinding : getReferencedVars ()) {
241245 notification (CG[fixedBinding]);
242246 }
@@ -249,25 +253,6 @@ void ConstraintGraphNode::addToEquivalenceClass(
249253 if (EquivalenceClass.empty ())
250254 EquivalenceClass.push_back (getTypeVariable ());
251255 EquivalenceClass.append (typeVars.begin (), typeVars.end ());
252-
253- {
254- for (auto *newMember : typeVars) {
255- auto &node = CG[newMember];
256-
257- for (auto *constraint : node.getConstraints ()) {
258- introduceToInference (constraint);
259-
260- if (!isUsefulForReferencedVars (constraint))
261- continue ;
262-
263- notifyReferencedVars ([&](ConstraintGraphNode &referencedVar) {
264- referencedVar.introduceToInference (constraint);
265- });
266- }
267-
268- node.notifyReferencingVars ();
269- }
270- }
271256}
272257
273258void ConstraintGraphNode::truncateEquivalenceClass (unsigned prevSize) {
@@ -343,19 +328,17 @@ void ConstraintGraphNode::retractFromInference(Constraint *constraint) {
343328 }
344329}
345330
346- void ConstraintGraphNode::reintroduceToInference (Constraint *constraint) {
347- retractFromInference (constraint);
348- introduceToInference (constraint);
349- }
350-
351- void ConstraintGraphNode::introduceToInference (Type fixedType) {
331+ void ConstraintGraphNode::updateFixedType (
332+ Type fixedType,
333+ llvm::function_ref<void (ConstraintGraphNode &,
334+ Constraint *)> notification) const {
352335 // Notify all of the type variables that reference this one.
353336 //
354337 // Since this type variable has been replaced with a fixed type
355338 // all of the concrete types that reference it are going to change,
356339 // which means that all of the not-yet-attempted bindings should
357340 // change as well.
358- notifyReferencingVars ();
341+ notifyReferencingVars (notification );
359342
360343 if (!fixedType->hasTypeVariable ())
361344 return ;
@@ -371,11 +354,27 @@ void ConstraintGraphNode::introduceToInference(Type fixedType) {
371354 // all of the constraints that reference bound type variable.
372355 for (auto *constraint : getConstraints ()) {
373356 if (isUsefulForReferencedVars (constraint))
374- node. reintroduceToInference ( constraint);
357+ notification (node, constraint);
375358 }
376359 }
377360}
378361
362+ void ConstraintGraphNode::retractFromInference (Type fixedType) {
363+ return updateFixedType (
364+ fixedType,
365+ [](ConstraintGraphNode &node, Constraint *constraint) {
366+ node.retractFromInference (constraint);
367+ });
368+ }
369+
370+ void ConstraintGraphNode::introduceToInference (Type fixedType) {
371+ return updateFixedType (
372+ fixedType,
373+ [](ConstraintGraphNode &node, Constraint *constraint) {
374+ node.introduceToInference (constraint);
375+ });
376+ }
377+
379378#pragma mark Graph mutation
380379
381380void ConstraintGraph::removeNode (TypeVariableType *typeVar) {
@@ -486,31 +485,60 @@ void ConstraintGraph::removeConstraint(TypeVariableType *typeVar,
486485 OrphanedConstraints.pop_back ();
487486}
488487
488+ void ConstraintGraph::mergeNodesPre (TypeVariableType *typeVar2) {
489+ // Merge equivalence class from the non-representative type variable.
490+ auto &nonRepNode = (*this )[typeVar2];
491+
492+ for (auto *newMember : nonRepNode.getEquivalenceClassUnsafe ()) {
493+ auto &node = (*this )[newMember];
494+
495+ node.notifyReferencingVars (
496+ [&](ConstraintGraphNode &node, Constraint *constraint) {
497+ node.retractFromInference (constraint);
498+ });
499+ }
500+ }
501+
489502void ConstraintGraph::mergeNodes (TypeVariableType *typeVar1,
490503 TypeVariableType *typeVar2) {
491- assert (CS.getRepresentative (typeVar1) == CS.getRepresentative (typeVar2) &&
492- " type representatives don't match" );
493-
494504 // Retrieve the node for the representative that we're merging into.
495- auto typeVarRep = CS.getRepresentative (typeVar1);
496- auto &repNode = (*this )[typeVarRep];
505+ ASSERT (CS.getRepresentative (typeVar1) == typeVar1);
497506
498- // Retrieve the node for the non-representative.
499- assert ((typeVar1 == typeVarRep || typeVar2 == typeVarRep) &&
500- " neither type variable is the new representative?" );
501- auto typeVarNonRep = typeVar1 == typeVarRep? typeVar2 : typeVar1;
507+ auto &repNode = (*this )[typeVar1];
502508
503509 // Record the change, if there are active scopes.
504510 if (CS.isRecordingChanges ()) {
505511 CS.recordChange (
506512 SolverTrail::Change::ExtendedEquivalenceClass (
507- typeVarRep ,
513+ typeVar1 ,
508514 repNode.getEquivalenceClass ().size ()));
509515 }
510516
511517 // Merge equivalence class from the non-representative type variable.
512- auto &nonRepNode = (*this )[typeVarNonRep];
513- repNode.addToEquivalenceClass (nonRepNode.getEquivalenceClassUnsafe ());
518+ auto &nonRepNode = (*this )[typeVar2];
519+
520+ auto typeVars = nonRepNode.getEquivalenceClassUnsafe ();
521+ repNode.addToEquivalenceClass (typeVars);
522+
523+ for (auto *newMember : typeVars) {
524+ auto &node = (*this )[newMember];
525+
526+ for (auto *constraint : node.getConstraints ()) {
527+ repNode.introduceToInference (constraint);
528+
529+ if (!isUsefulForReferencedVars (constraint))
530+ continue ;
531+
532+ repNode.notifyReferencedVars ([&](ConstraintGraphNode &referencedVar) {
533+ referencedVar.introduceToInference (constraint);
534+ });
535+ }
536+
537+ node.notifyReferencingVars (
538+ [&](ConstraintGraphNode &node, Constraint *constraint) {
539+ node.introduceToInference (constraint);
540+ });
541+ }
514542}
515543
516544void ConstraintGraph::bindTypeVariable (TypeVariableType *typeVar, Type fixed) {
@@ -537,6 +565,10 @@ void ConstraintGraph::bindTypeVariable(TypeVariableType *typeVar, Type fixed) {
537565 }
538566}
539567
568+ void ConstraintGraph::retractFromInference (TypeVariableType *typeVar, Type fixed) {
569+ (*this )[typeVar].retractFromInference (fixed);
570+ }
571+
540572void ConstraintGraph::introduceToInference (TypeVariableType *typeVar, Type fixed) {
541573 (*this )[typeVar].introduceToInference (fixed);
542574}
0 commit comments