mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Take first steps towards simplifying the constraint graph by performing edge contraction.
This commit is contained in:
@@ -1323,9 +1323,20 @@ ConstraintSystem::matchTypes(Type type1, Type type2, TypeMatchKind kind,
|
||||
}
|
||||
SWIFT_FALLTHROUGH;
|
||||
|
||||
case TypeMatchKind::Conversion:
|
||||
if (typeVar1 && typeVar2) {
|
||||
auto rep1 = getRepresentative(typeVar1);
|
||||
auto rep2 = getRepresentative(typeVar2);
|
||||
if (rep1 == rep2) {
|
||||
// We already merged these two types, so this constraint is
|
||||
// trivially solved.
|
||||
return SolutionKind::Solved;
|
||||
}
|
||||
}
|
||||
SWIFT_FALLTHROUGH;
|
||||
|
||||
case TypeMatchKind::ConformsTo:
|
||||
case TypeMatchKind::Subtype:
|
||||
case TypeMatchKind::Conversion:
|
||||
case TypeMatchKind::ExplicitConversion:
|
||||
case TypeMatchKind::ArgumentConversion:
|
||||
case TypeMatchKind::OperatorArgumentTupleConversion:
|
||||
|
||||
@@ -821,6 +821,15 @@ static PotentialBindings getPotentialBindings(ConstraintSystem &cs,
|
||||
auto first = cs.simplifyType(constraint->getFirstType());
|
||||
auto second = cs.simplifyType(constraint->getSecondType());
|
||||
|
||||
if (auto firstTyvar = first->getAs<TypeVariableType>()) {
|
||||
if (auto secondTyvar = second->getAs<TypeVariableType>()) {
|
||||
if (cs.getRepresentative(firstTyvar) ==
|
||||
cs.getRepresentative(secondTyvar)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Type type;
|
||||
AllowedBindingKind kind;
|
||||
if (first->getAs<TypeVariableType>() == typeVar) {
|
||||
@@ -1242,6 +1251,9 @@ bool ConstraintSystem::solveRec(SmallVectorImpl<Solution> &solutions,
|
||||
return false;
|
||||
}
|
||||
|
||||
// Contract the edges of the constraint graph.
|
||||
CG.optimize();
|
||||
|
||||
// Compute the connected components of the constraint graph.
|
||||
// FIXME: We're seeding typeVars with TypeVariables so that the
|
||||
// connected-components algorithm only considers those type variables within
|
||||
|
||||
@@ -687,6 +687,74 @@ unsigned ConstraintGraph::computeConnectedComponents(
|
||||
return numComponents;
|
||||
}
|
||||
|
||||
bool ConstraintGraph::contractEdges() {
|
||||
llvm::SetVector<std::pair<TypeVariableType *,
|
||||
TypeVariableType *>> contractions;
|
||||
|
||||
auto tyvars = getTypeVariables();
|
||||
auto didContractEdges = false;
|
||||
|
||||
for (auto tyvar : tyvars) {
|
||||
SmallVector<Constraint *, 4> constraints;
|
||||
gatherConstraints(tyvar, constraints);
|
||||
|
||||
for (auto constraint : constraints) {
|
||||
// Contract binding edges between type variables.
|
||||
if (constraint->getKind() == ConstraintKind::Conversion ||
|
||||
constraint->getKind() == ConstraintKind::Bind ||
|
||||
constraint->getKind() == ConstraintKind::Equal) {
|
||||
if (auto tyvar1 = constraint->getFirstType()->
|
||||
getAs<TypeVariableType>()) {
|
||||
if (auto tyvar2 = constraint->getSecondType()->
|
||||
getAs<TypeVariableType>()) {
|
||||
|
||||
auto rep1 = CS.getRepresentative(tyvar1);
|
||||
auto rep2 = CS.getRepresentative(tyvar2);
|
||||
|
||||
if (rep1 != rep2) {
|
||||
|
||||
if (rep1->getImpl().canBindToLValue() ==
|
||||
rep2->getImpl().canBindToLValue()) {
|
||||
|
||||
// Merge the edges and remove the constraint.
|
||||
CS.mergeEquivalenceClasses(rep1, rep2);
|
||||
didContractEdges = true;
|
||||
removeEdge(constraint);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return didContractEdges;
|
||||
}
|
||||
|
||||
void ConstraintGraph::removeEdge(Constraint *constraint) {
|
||||
|
||||
for (auto &active : CS.ActiveConstraints) {
|
||||
if (&active == constraint) {
|
||||
CS.ActiveConstraints.erase(constraint);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto &inactive : CS.InactiveConstraints) {
|
||||
if (&inactive == constraint) {
|
||||
CS.InactiveConstraints.erase(constraint);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
removeConstraint(constraint);
|
||||
}
|
||||
|
||||
void ConstraintGraph::optimize() {
|
||||
// Merge equivalence classes until a fixed point is reached.
|
||||
while(contractEdges()) {}
|
||||
}
|
||||
|
||||
#pragma mark Debugging output
|
||||
|
||||
void ConstraintGraphNode::print(llvm::raw_ostream &out, unsigned indent) {
|
||||
|
||||
@@ -287,6 +287,10 @@ public:
|
||||
/// Verify the invariants of the graph.
|
||||
void verify();
|
||||
|
||||
/// Optimize the constraint graph by eliminating simple transitive
|
||||
/// connections between nodes.
|
||||
void optimize();
|
||||
|
||||
private:
|
||||
/// Remove the node corresponding to the given type variable.
|
||||
///
|
||||
@@ -304,6 +308,15 @@ private:
|
||||
/// caution.
|
||||
void unbindTypeVariable(TypeVariableType *typeVar, Type fixedType);
|
||||
|
||||
|
||||
/// Perform edge contraction on the constraint graph, merging equivalence
|
||||
/// classes until a fixed point is reached.
|
||||
bool contractEdges();
|
||||
|
||||
/// To support edge contraction, remove a constraint from both the constraint
|
||||
/// graph and its enclosing constraint system.
|
||||
void removeEdge(Constraint *constraint);
|
||||
|
||||
/// The constraint system.
|
||||
ConstraintSystem &CS;
|
||||
|
||||
|
||||
@@ -878,6 +878,7 @@ public:
|
||||
|
||||
friend class Fix;
|
||||
friend class OverloadChoice;
|
||||
friend class ConstraintGraph;
|
||||
|
||||
class SolverScope;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user