Skip to content

Commit 166c41d

Browse files
committed
[ConstraintGraph] Extract logic related to fixed types into dedicated methods on graph node
1 parent 654ec0d commit 166c41d

File tree

2 files changed

+69
-39
lines changed

2 files changed

+69
-39
lines changed

include/swift/Sema/ConstraintGraph.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,24 @@ class ConstraintGraphNode {
135135
/// equivalence class changes.
136136
void reintroduceToInference(Constraint *constraint, bool notifyReferencedVars);
137137

138+
/// Similar to \c introduceToInference(Constraint *, ...) this method is going
139+
/// to notify inference that this type variable has been bound to a concrete
140+
/// type.
141+
///
142+
/// The reason why this can't simplify be a part of \c bindTypeVariable
143+
/// is related to the fact that it's sometimes expensive to re-compute
144+
/// bindings (i.e. if `DependentMemberType` is involved, because it requires
145+
/// a conformance lookup), so inference has to be delayed until its clear that
146+
/// type variable has been bound to a valid type and solver can make progress.
147+
void
148+
introduceToInference(Type fixedType,
149+
SmallPtrSetImpl<TypeVariableType *> &referencedVars);
150+
151+
/// Opposite of \c introduceToInference(Type, ...)
152+
void
153+
retractFromInference(Type fixedType,
154+
SmallPtrSetImpl<TypeVariableType *> &referencedVars);
155+
138156
/// Drop all previously collected bindings and re-infer based on the
139157
/// current set constraints associated with this equivalence class.
140158
void resetBindingSet();
@@ -148,6 +166,7 @@ class ConstraintGraphNode {
148166
/// This is useful in situations when type variable gets bound and unbound,
149167
/// or equivalence class changes.
150168
void notifyReferencingVars() const;
169+
151170
/// }
152171

153172
/// The constraint graph this node belongs to.

lib/Sema/ConstraintGraph.cpp

Lines changed: 50 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,46 @@ void ConstraintGraphNode::reintroduceToInference(Constraint *constraint,
335335
introduceToInference(constraint, notifyReferencedVars);
336336
}
337337

338+
void ConstraintGraphNode::introduceToInference(
339+
Type fixedType, SmallPtrSetImpl<TypeVariableType *> &referencedVars) {
340+
// Notify all of the type variables that reference this one.
341+
//
342+
// Since this type variable has been replaced with a fixed type
343+
// all of the concrete types that reference it are going to change,
344+
// which means that all of the not-yet-attempted bindings should
345+
// change as well.
346+
notifyReferencingVars();
347+
348+
for (auto *referencedVar : referencedVars) {
349+
auto &node = CG[referencedVar];
350+
351+
// Newly referred vars need to re-introduce all constraints associated
352+
// with this type variable since they are now going to be used in
353+
// all of the constraints that reference bound type variable.
354+
for (auto *constraint : getConstraints()) {
355+
if (isUsefulForReferencedVars(constraint))
356+
node.reintroduceToInference(constraint,
357+
/*notifyReferencedVars=*/false);
358+
}
359+
}
360+
}
361+
362+
void ConstraintGraphNode::retractFromInference(
363+
Type fixedType, SmallPtrSetImpl<TypeVariableType *> &referencedVars) {
364+
// Notify referencing variables (just like in bound case) that this
365+
// type variable has been modified.
366+
notifyReferencingVars();
367+
368+
// TODO: This might be an overkill but it's (currently)
369+
// the simpliest way to reliably ensure that all of the
370+
// no longer related constraints have been retracted.
371+
for (auto *referencedVar : referencedVars) {
372+
auto &node = CG[referencedVar];
373+
if (node.forRepresentativeVar())
374+
node.resetBindingSet();
375+
}
376+
}
377+
338378
void ConstraintGraphNode::resetBindingSet() {
339379
assert(forRepresentativeVar());
340380

@@ -541,65 +581,36 @@ void ConstraintGraph::bindTypeVariable(TypeVariableType *typeVar, Type fixed) {
541581

542582
auto &node = (*this)[typeVar];
543583

544-
// Notify all of the type variables that reference this one.
545-
//
546-
// Since this type variable has been replaced with a fixed type
547-
// all of the concrete types that reference it are going to change,
548-
// which means that all of the not-yet-attempted bindings should
549-
// change as well.
550-
node.notifyReferencingVars();
551-
552-
if (!fixed->hasTypeVariable())
553-
return;
554-
555-
llvm::SmallPtrSet<TypeVariableType *, 4> typeVars;
556-
fixed->getTypeVariables(typeVars);
584+
llvm::SmallPtrSet<TypeVariableType *, 4> referencedVars;
585+
fixed->getTypeVariables(referencedVars);
557586

558-
for (auto otherTypeVar : typeVars) {
587+
for (auto otherTypeVar : referencedVars) {
559588
if (typeVar == otherTypeVar)
560589
continue;
561590

562591
auto &otherNode = (*this)[otherTypeVar];
563592

564593
otherNode.addReferencedBy(typeVar);
565594
node.addReferencedVar(otherTypeVar);
566-
567-
// Newly referred vars need to re-introduce all constraints associated
568-
// with this type variable since they are now going to be used in
569-
// all of the constraints that reference bound type variable.
570-
for (auto *constraint : (*this)[typeVar].getConstraints()) {
571-
if (isUsefulForReferencedVars(constraint))
572-
otherNode.reintroduceToInference(constraint,
573-
/*notifyReferencedVars=*/false);
574-
}
575595
}
596+
597+
node.introduceToInference(fixed, referencedVars);
576598
}
577599

578600
void ConstraintGraph::unbindTypeVariable(TypeVariableType *typeVar, Type fixed) {
579601
auto &node = (*this)[typeVar];
580602

581-
// Notify referencing variables (just like in bound case) that this
582-
// type variable has been modified.
583-
node.notifyReferencingVars();
603+
llvm::SmallPtrSet<TypeVariableType *, 4> referencedVars;
604+
fixed->getTypeVariables(referencedVars);
584605

585-
if (!fixed->hasTypeVariable())
586-
return;
587-
588-
llvm::SmallPtrSet<TypeVariableType *, 4> typeVars;
589-
fixed->getTypeVariables(typeVars);
590-
591-
for (auto otherTypeVar : typeVars) {
606+
for (auto otherTypeVar : referencedVars) {
592607
auto &otherNode = (*this)[otherTypeVar];
593608

594609
otherNode.removeReferencedBy(typeVar);
595610
node.removeReference(otherTypeVar);
596-
597-
// TODO: This might be an overkill but it's (currently)
598-
// the simpliest way to reliably ensure that all of the
599-
// no longer related constraints have been retracted.
600-
if (otherNode.forRepresentativeVar())
601-
otherNode.resetBindingSet();
602611
}
612+
613+
node.retractFromInference(fixed, referencedVars);
603614
}
604615

605616
#pragma mark Algorithms

0 commit comments

Comments
 (0)