Skip to content

Commit b487b69

Browse files
committed
[ConstraintSystem] Delay inference until let's clear that type variable attempt is successful
Currently bindings where inferred on every `bindTypeVariable` call, but that's wasteful because not all binds are always correct. To avoid unnecessary inference traffic let's wait until re-activated constraints are simplified and notify binding inference about new fixed type only if all of them are successful.
1 parent f12efe9 commit b487b69

File tree

6 files changed

+42
-13
lines changed

6 files changed

+42
-13
lines changed

include/swift/Sema/ConstraintGraph.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ class Constraint;
4444
class ConstraintGraph;
4545
class ConstraintGraphScope;
4646
class ConstraintSystem;
47+
class TypeVariableBinding;
4748

4849
/// A single node in the constraint graph, which represents a type variable.
4950
class ConstraintGraphNode {
@@ -144,11 +145,9 @@ class ConstraintGraphNode {
144145
/// bindings (i.e. if `DependentMemberType` is involved, because it requires
145146
/// a conformance lookup), so inference has to be delayed until its clear that
146147
/// type variable has been bound to a valid type and solver can make progress.
147-
void
148-
introduceToInference(Type fixedType,
149-
SmallPtrSetImpl<TypeVariableType *> &referencedVars);
148+
void introduceToInference(Type fixedType);
150149

151-
/// Opposite of \c introduceToInference(Type, ...)
150+
/// Opposite of \c introduceToInference(Type)
152151
void
153152
retractFromInference(Type fixedType,
154153
SmallPtrSetImpl<TypeVariableType *> &referencedVars);
@@ -211,6 +210,8 @@ class ConstraintGraphNode {
211210
void verify(ConstraintGraph &cg);
212211

213212
friend class ConstraintGraph;
213+
friend class ConstraintSystem;
214+
friend class TypeVariableBinding;
214215
};
215216

216217
/// A graph that describes the relationships among the various type variables

include/swift/Sema/ConstraintSystem.h

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3631,6 +3631,10 @@ class ConstraintSystem {
36313631

36323632
/// Indicates that we are applying a fix.
36333633
TMF_ApplyingFix = 0x02,
3634+
3635+
/// Indicates that we are attempting a possible type for
3636+
/// a type variable.
3637+
TMF_BindingTypeVariable = 0x04,
36343638
};
36353639

36363640
/// Options that govern how type matching should proceed.
@@ -3702,10 +3706,14 @@ class ConstraintSystem {
37023706
/// \param type The fixed type to which the type variable will be bound.
37033707
///
37043708
/// \param updateState Whether to update the state based on this binding.
3705-
/// False when we're only assigning a type as part of reconstructing
3709+
/// False when we're only assigning a type as part of reconstructing
37063710
/// a complete solution from partial solutions.
3711+
///
3712+
/// \param notifyBindingInference Whether to notify binding inference about
3713+
/// the change to this type variable.
37073714
void assignFixedType(TypeVariableType *typeVar, Type type,
3708-
bool updateState = true);
3715+
bool updateState = true,
3716+
bool notifyBindingInference = true);
37093717

37103718
/// Determine if the type in question is an Array<T> and, if so, provide the
37113719
/// element type of the array.

lib/Sema/CSBindings.cpp

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1796,6 +1796,7 @@ bool TypeVariableBinding::attempt(ConstraintSystem &cs) const {
17961796
ConstraintSystem::TypeMatchOptions options;
17971797

17981798
options |= ConstraintSystem::TMF_GenerateConstraints;
1799+
options |= ConstraintSystem::TMF_BindingTypeVariable;
17991800

18001801
auto result =
18011802
cs.matchTypes(TypeVar, type, ConstraintKind::Bind, options, srcLocator);
@@ -1833,5 +1834,16 @@ bool TypeVariableBinding::attempt(ConstraintSystem &cs) const {
18331834
return true;
18341835
}
18351836

1836-
return !cs.simplify();
1837+
if (cs.simplify())
1838+
return false;
1839+
1840+
// If all of the re-activated constraints where simplified,
1841+
// let's notify binding inference about the fact that type
1842+
// variable has been bound successfully.
1843+
{
1844+
auto &CG = cs.getConstraintGraph();
1845+
CG[TypeVar].introduceToInference(type);
1846+
}
1847+
1848+
return true;
18371849
}

lib/Sema/CSSimplify.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3016,7 +3016,8 @@ ConstraintSystem::matchTypesBindTypeVar(
30163016
: getTypeMatchFailure(locator);
30173017
}
30183018

3019-
assignFixedType(typeVar, type);
3019+
assignFixedType(typeVar, type, /*updateState=*/true,
3020+
/*notifyInference=*/!flags.contains(TMF_BindingTypeVariable));
30203021

30213022
return getTypeMatchSuccess();
30223023
}

lib/Sema/ConstraintGraph.cpp

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

338-
void ConstraintGraphNode::introduceToInference(
339-
Type fixedType, SmallPtrSetImpl<TypeVariableType *> &referencedVars) {
338+
void ConstraintGraphNode::introduceToInference(Type fixedType) {
340339
// Notify all of the type variables that reference this one.
341340
//
342341
// Since this type variable has been replaced with a fixed type
@@ -345,6 +344,12 @@ void ConstraintGraphNode::introduceToInference(
345344
// change as well.
346345
notifyReferencingVars();
347346

347+
if (!fixedType->hasTypeVariable())
348+
return;
349+
350+
SmallPtrSet<TypeVariableType *, 4> referencedVars;
351+
fixedType->getTypeVariables(referencedVars);
352+
348353
for (auto *referencedVar : referencedVars) {
349354
auto &node = CG[referencedVar];
350355

@@ -593,8 +598,6 @@ void ConstraintGraph::bindTypeVariable(TypeVariableType *typeVar, Type fixed) {
593598
otherNode.addReferencedBy(typeVar);
594599
node.addReferencedVar(otherTypeVar);
595600
}
596-
597-
node.introduceToInference(fixed, referencedVars);
598601
}
599602

600603
void ConstraintGraph::unbindTypeVariable(TypeVariableType *typeVar, Type fixed) {

lib/Sema/ConstraintSystem.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,8 @@ bool ConstraintSystem::typeVarOccursInType(TypeVariableType *typeVar,
155155
}
156156

157157
void ConstraintSystem::assignFixedType(TypeVariableType *typeVar, Type type,
158-
bool updateState) {
158+
bool updateState,
159+
bool notifyBindingInference) {
159160
assert(!type->hasError() &&
160161
"Should not be assigning a type involving ErrorType!");
161162

@@ -199,6 +200,9 @@ void ConstraintSystem::assignFixedType(TypeVariableType *typeVar, Type type,
199200
// Notify the constraint graph.
200201
CG.bindTypeVariable(typeVar, type);
201202
addTypeVariableConstraintsToWorkList(typeVar);
203+
204+
if (notifyBindingInference)
205+
CG[typeVar].introduceToInference(type);
202206
}
203207

204208
void ConstraintSystem::addTypeVariableConstraintsToWorkList(

0 commit comments

Comments
 (0)