Skip to content

Commit 8137c7b

Browse files
committed
[ConstraintGraph] Split fixed binding storage into referenced by/from
Binding inference requires constraint propagation through to referenced type variables, in current "fixed bindings" storage mode it is impossible to figure out whether tracked type variables are referenced by or from a type variable. Splitting storage for referenced by/from also helps to provide more meaningful debug output and make sure there are no attempts to insert duplicate references.
1 parent cd724d4 commit 8137c7b

File tree

2 files changed

+76
-34
lines changed

2 files changed

+76
-34
lines changed

include/swift/Sema/ConstraintGraph.h

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,12 @@ class ConstraintGraphNode {
6363

6464
/// Retrieve the set of type variables that are adjacent due to fixed
6565
/// bindings.
66-
ArrayRef<TypeVariableType *> getFixedBindings() const {
67-
return FixedBindings;
66+
ArrayRef<TypeVariableType *> getReferencedVars() const {
67+
return References.getArrayRef();
68+
}
69+
70+
ArrayRef<TypeVariableType *> getReferencedBy() const {
71+
return ReferencedBy.getArrayRef();
6872
}
6973

7074
/// Retrieve all of the type variables in the same equivalence class
@@ -95,11 +99,18 @@ class ConstraintGraphNode {
9599
void addToEquivalenceClass(ArrayRef<TypeVariableType *> typeVars);
96100

97101
/// Add a type variable related to this type variable through fixed
98-
/// bindings.
99-
void addFixedBinding(TypeVariableType *typeVar);
100-
101-
/// Remove a type variable from the fixed-binding relationship.
102-
void removeFixedBinding(TypeVariableType *typeVar);
102+
/// binding.
103+
void addReferencedVar(TypeVariableType *typeVar);
104+
105+
/// Add a type variable referencing this type variable - this type
106+
/// variable occurs in fixed type of the given type variable.
107+
void addReferencedBy(TypeVariableType *typeVar);
108+
109+
/// Remove a type variable referenced by this node through a fixed binding.
110+
void removeReference(TypeVariableType *typeVar);
111+
112+
/// Remove a type variable which used to reference this type variable.
113+
void removeReferencedBy(TypeVariableType *typeVar);
103114

104115
/// The type variable this node represents.
105116
TypeVariableType *TypeVar;
@@ -112,9 +123,13 @@ class ConstraintGraphNode {
112123
/// to the index within the vector of constraints.
113124
llvm::SmallDenseMap<Constraint *, unsigned, 2> ConstraintIndex;
114125

126+
/// The set of type variables that reference type variable associated
127+
/// with this constraint graph node.
128+
llvm::SmallSetVector<TypeVariableType *, 2> ReferencedBy;
129+
115130
/// The set of type variables that occur within the fixed binding of
116131
/// this type variable.
117-
SmallVector<TypeVariableType *, 2> FixedBindings;
132+
llvm::SmallSetVector<TypeVariableType *, 2> References;
118133

119134
/// All of the type variables in the same equivalence class as this
120135
/// representative type variable.

lib/Sema/ConstraintGraph.cpp

Lines changed: 53 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -143,12 +143,28 @@ void ConstraintGraphNode::addToEquivalenceClass(
143143
EquivalenceClass.append(typeVars.begin(), typeVars.end());
144144
}
145145

146-
void ConstraintGraphNode::addFixedBinding(TypeVariableType *typeVar) {
147-
FixedBindings.push_back(typeVar);
146+
void ConstraintGraphNode::addReferencedVar(TypeVariableType *typeVar) {
147+
bool inserted = References.insert(typeVar);
148+
assert(inserted && "Attempt to reference a duplicate type variable");
149+
(void)inserted;
148150
}
149151

150-
void ConstraintGraphNode::removeFixedBinding(TypeVariableType *typeVar) {
151-
FixedBindings.pop_back();
152+
void ConstraintGraphNode::addReferencedBy(TypeVariableType *typeVar) {
153+
bool inserted = ReferencedBy.insert(typeVar);
154+
assert(inserted && "Already referenced by the given type variable");
155+
(void)inserted;
156+
}
157+
158+
void ConstraintGraphNode::removeReference(TypeVariableType *typeVar) {
159+
auto removed = References.remove(typeVar);
160+
assert(removed && "Variables are not connected");
161+
(void)removed;
162+
}
163+
164+
void ConstraintGraphNode::removeReferencedBy(TypeVariableType *typeVar) {
165+
auto removed = ReferencedBy.remove(typeVar);
166+
assert(removed && "Variables are not connected");
167+
(void)removed;
152168
}
153169

154170
#pragma mark Graph scope management
@@ -349,11 +365,10 @@ void ConstraintGraph::bindTypeVariable(TypeVariableType *typeVar, Type fixed) {
349365
fixed->getTypeVariables(typeVars);
350366
auto &node = (*this)[typeVar];
351367
for (auto otherTypeVar : typeVars) {
352-
if (typeVar == otherTypeVar)
353-
continue;
368+
if (typeVar == otherTypeVar) continue;
354369

355-
(*this)[otherTypeVar].addFixedBinding(typeVar);
356-
node.addFixedBinding(otherTypeVar);
370+
(*this)[otherTypeVar].addReferencedBy(typeVar);
371+
node.addReferencedVar(otherTypeVar);
357372
}
358373

359374
// Record the change, if there are active scopes.
@@ -372,8 +387,8 @@ void ConstraintGraph::unbindTypeVariable(TypeVariableType *typeVar, Type fixed){
372387
fixed->getTypeVariables(typeVars);
373388
auto &node = (*this)[typeVar];
374389
for (auto otherTypeVar : typeVars) {
375-
(*this)[otherTypeVar].removeFixedBinding(typeVar);
376-
node.removeFixedBinding(otherTypeVar);
390+
(*this)[otherTypeVar].removeReferencedBy(typeVar);
391+
node.removeReference(otherTypeVar);
377392
}
378393
}
379394

@@ -435,7 +450,8 @@ static void depthFirstSearch(
435450
}
436451

437452
// Walk any type variables related via fixed bindings.
438-
visitAdjacencies(node.getFixedBindings());
453+
visitAdjacencies(node.getReferencedBy());
454+
visitAdjacencies(node.getReferencedVars());
439455
}
440456

441457
llvm::TinyPtrVector<Constraint *> ConstraintGraph::gatherConstraints(
@@ -513,7 +529,11 @@ llvm::TinyPtrVector<Constraint *> ConstraintGraph::gatherConstraints(
513529
constraints.push_back(constraint);
514530
}
515531

516-
for (auto adjTypeVar : node.getFixedBindings()) {
532+
for (auto adjTypeVar : node.getReferencedBy()) {
533+
addTypeVarConstraints(adjTypeVar);
534+
}
535+
536+
for (auto adjTypeVar : node.getReferencedVars()) {
517537
addTypeVarConstraints(adjTypeVar);
518538
}
519539
}
@@ -1202,24 +1222,31 @@ void ConstraintGraphNode::print(llvm::raw_ostream &out, unsigned indent,
12021222
}
12031223
}
12041224

1205-
// Print fixed bindings.
1206-
if (!FixedBindings.empty()) {
1207-
out.indent(indent + 2);
1208-
out << "Fixed bindings: ";
1209-
SmallVector<TypeVariableType *, 4> sortedFixedBindings(
1210-
FixedBindings.begin(), FixedBindings.end());
1211-
std::sort(sortedFixedBindings.begin(), sortedFixedBindings.end(),
1225+
auto printVarList = [&](ArrayRef<TypeVariableType *> typeVars) {
1226+
SmallVector<TypeVariableType *, 4> sorted(typeVars.begin(), typeVars.end());
1227+
std::sort(sorted.begin(), sorted.end(),
12121228
[&](TypeVariableType *typeVar1, TypeVariableType *typeVar2) {
12131229
return typeVar1->getID() < typeVar2->getID();
12141230
});
12151231

1216-
interleave(sortedFixedBindings,
1217-
[&](TypeVariableType *typeVar) {
1218-
out << "$T" << typeVar->getID();
1219-
},
1220-
[&]() {
1221-
out << ", ";
1222-
});
1232+
interleave(
1233+
sorted,
1234+
[&](TypeVariableType *typeVar) { out << typeVar->getString(PO); },
1235+
[&out] { out << ", "; });
1236+
};
1237+
1238+
// Print fixed bindings.
1239+
if (!ReferencedBy.empty()) {
1240+
out.indent(indent + 2);
1241+
out << "Referenced By: ";
1242+
printVarList(getReferencedBy());
1243+
out << "\n";
1244+
}
1245+
1246+
if (!References.empty()) {
1247+
out.indent(indent + 2);
1248+
out << "References: ";
1249+
printVarList(getReferencedVars());
12231250
out << "\n";
12241251
}
12251252

0 commit comments

Comments
 (0)