@@ -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);
@@ -177,7 +179,9 @@ void ConstraintGraphNode::removeConstraint(Constraint *constraint) {
177
179
Constraints.pop_back ();
178
180
}
179
181
180
- void ConstraintGraphNode::notifyReferencingVars () const {
182
+ void ConstraintGraphNode::notifyReferencingVars (
183
+ llvm::function_ref<void (ConstraintGraphNode &,
184
+ Constraint *)> notification) const {
181
185
SmallVector<TypeVariableType *, 4 > stack;
182
186
183
187
stack.push_back (TypeVar);
@@ -199,7 +203,7 @@ void ConstraintGraphNode::notifyReferencingVars() const {
199
203
affectedVar->getImpl ().getRepresentative (/* record=*/ nullptr );
200
204
201
205
if (!repr->getImpl ().getFixedType (/* record=*/ nullptr ))
202
- CG[repr]. reintroduceToInference ( constraint);
206
+ notification ( CG[repr], constraint);
203
207
}
204
208
}
205
209
};
@@ -236,7 +240,7 @@ void ConstraintGraphNode::notifyReferencingVars() const {
236
240
}
237
241
238
242
void ConstraintGraphNode::notifyReferencedVars (
239
- llvm::function_ref<void (ConstraintGraphNode &)> notification) {
243
+ llvm::function_ref<void (ConstraintGraphNode &)> notification) const {
240
244
for (auto *fixedBinding : getReferencedVars ()) {
241
245
notification (CG[fixedBinding]);
242
246
}
@@ -249,25 +253,6 @@ void ConstraintGraphNode::addToEquivalenceClass(
249
253
if (EquivalenceClass.empty ())
250
254
EquivalenceClass.push_back (getTypeVariable ());
251
255
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
- }
271
256
}
272
257
273
258
void ConstraintGraphNode::truncateEquivalenceClass (unsigned prevSize) {
@@ -343,19 +328,17 @@ void ConstraintGraphNode::retractFromInference(Constraint *constraint) {
343
328
}
344
329
}
345
330
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 {
352
335
// Notify all of the type variables that reference this one.
353
336
//
354
337
// Since this type variable has been replaced with a fixed type
355
338
// all of the concrete types that reference it are going to change,
356
339
// which means that all of the not-yet-attempted bindings should
357
340
// change as well.
358
- notifyReferencingVars ();
341
+ notifyReferencingVars (notification );
359
342
360
343
if (!fixedType->hasTypeVariable ())
361
344
return ;
@@ -371,11 +354,27 @@ void ConstraintGraphNode::introduceToInference(Type fixedType) {
371
354
// all of the constraints that reference bound type variable.
372
355
for (auto *constraint : getConstraints ()) {
373
356
if (isUsefulForReferencedVars (constraint))
374
- node. reintroduceToInference ( constraint);
357
+ notification (node, constraint);
375
358
}
376
359
}
377
360
}
378
361
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
+
379
378
#pragma mark Graph mutation
380
379
381
380
void ConstraintGraph::removeNode (TypeVariableType *typeVar) {
@@ -486,31 +485,60 @@ void ConstraintGraph::removeConstraint(TypeVariableType *typeVar,
486
485
OrphanedConstraints.pop_back ();
487
486
}
488
487
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
+
489
502
void ConstraintGraph::mergeNodes (TypeVariableType *typeVar1,
490
503
TypeVariableType *typeVar2) {
491
- assert (CS.getRepresentative (typeVar1) == CS.getRepresentative (typeVar2) &&
492
- " type representatives don't match" );
493
-
494
504
// 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);
497
506
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];
502
508
503
509
// Record the change, if there are active scopes.
504
510
if (CS.isRecordingChanges ()) {
505
511
CS.recordChange (
506
512
SolverTrail::Change::ExtendedEquivalenceClass (
507
- typeVarRep ,
513
+ typeVar1 ,
508
514
repNode.getEquivalenceClass ().size ()));
509
515
}
510
516
511
517
// 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
+ }
514
542
}
515
543
516
544
void ConstraintGraph::bindTypeVariable (TypeVariableType *typeVar, Type fixed) {
@@ -537,6 +565,10 @@ void ConstraintGraph::bindTypeVariable(TypeVariableType *typeVar, Type fixed) {
537
565
}
538
566
}
539
567
568
+ void ConstraintGraph::retractFromInference (TypeVariableType *typeVar, Type fixed) {
569
+ (*this )[typeVar].retractFromInference (fixed);
570
+ }
571
+
540
572
void ConstraintGraph::introduceToInference (TypeVariableType *typeVar, Type fixed) {
541
573
(*this )[typeVar].introduceToInference (fixed);
542
574
}
0 commit comments