Skip to content

Commit e81ce93

Browse files
committed
[CSSolver] Refactor selectBestBindingDisjunction
Add an assert which verifies that all of the disjunction choices has the same type variable on the left-hand side. Based on that fact, refactor `selectBestBindingDisjunction` to only check first choice to find suitable "bind" disjunctions to favor.
1 parent 1ea3ebc commit e81ce93

File tree

2 files changed

+45
-50
lines changed

2 files changed

+45
-50
lines changed

lib/Sema/CSSolver.cpp

Lines changed: 26 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1856,73 +1856,49 @@ static Constraint *selectBestBindingDisjunction(
18561856
if (disjunctions.empty())
18571857
return nullptr;
18581858

1859-
// Collect any disjunctions that simply attempt bindings for a
1860-
// type variable.
1861-
SmallVector<Constraint *, 8> bindingDisjunctions;
1859+
auto getAsTypeVar = [&cs](Type type) {
1860+
return cs.simplifyType(type)->getRValueType()->getAs<TypeVariableType>();
1861+
};
1862+
1863+
Constraint *firstBindDisjunction = nullptr;
18621864
for (auto *disjunction : disjunctions) {
1863-
TypeVariableType *commonTypeVariable = nullptr;
1864-
if (llvm::all_of(
1865-
disjunction->getNestedConstraints(),
1866-
[&](Constraint *bindingConstraint) {
1867-
if (bindingConstraint->getKind() != ConstraintKind::Bind)
1868-
return false;
1869-
1870-
auto *tv = cs.simplifyType(bindingConstraint->getFirstType())
1871-
->getRValueType()
1872-
->getAs<TypeVariableType>();
1873-
// Only do this for simple type variable bindings, not for
1874-
// bindings like: ($T1) -> $T2 bind String -> Int
1875-
if (!tv)
1876-
return false;
1877-
1878-
// If we've seen a variable before, make sure that this is
1879-
// the same one.
1880-
if (commonTypeVariable == tv)
1881-
return true;
1882-
if (commonTypeVariable)
1883-
return false;
1884-
1885-
commonTypeVariable = tv;
1886-
return true;
1887-
})) {
1888-
bindingDisjunctions.push_back(disjunction);
1889-
}
1890-
}
1865+
auto choices = disjunction->getNestedConstraints();
1866+
assert(!choices.empty());
18911867

1892-
for (auto *disjunction : bindingDisjunctions) {
1893-
auto nested = disjunction->getNestedConstraints();
1894-
assert(!nested.empty());
1895-
auto *tv = cs.simplifyType(nested[0]->getFirstType())
1896-
->getRValueType()
1897-
->getAs<TypeVariableType>();
1898-
assert(tv);
1868+
auto *choice = choices.front();
1869+
if (choice->getKind() != ConstraintKind::Bind)
1870+
continue;
1871+
1872+
// We can judge disjunction based on the single choice
1873+
// because all of choices (of bind overload set) should
1874+
// have the same left-hand side.
1875+
// Only do this for simple type variable bindings, not for
1876+
// bindings like: ($T1) -> $T2 bind String -> Int
1877+
auto *typeVar = getAsTypeVar(choice->getFirstType());
1878+
if (!typeVar)
1879+
continue;
1880+
1881+
if (!firstBindDisjunction)
1882+
firstBindDisjunction = disjunction;
18991883

19001884
llvm::SetVector<Constraint *> constraints;
19011885
cs.getConstraintGraph().gatherConstraints(
1902-
tv, constraints, ConstraintGraph::GatheringKind::EquivalenceClass,
1886+
typeVar, constraints, ConstraintGraph::GatheringKind::EquivalenceClass,
19031887
[](Constraint *constraint) {
19041888
return constraint->getKind() == ConstraintKind::Conversion;
19051889
});
19061890

19071891
for (auto *constraint : constraints) {
1908-
auto toType =
1909-
cs.simplifyType(constraint->getSecondType())->getRValueType();
1910-
auto *toTV = toType->getAs<TypeVariableType>();
1911-
if (tv != toTV)
1912-
continue;
1913-
1914-
return disjunction;
1892+
if (typeVar == getAsTypeVar(constraint->getSecondType()))
1893+
return disjunction;
19151894
}
19161895
}
19171896

19181897
// If we had any binding disjunctions, return the first of
19191898
// those. These ensure that we attempt to bind types earlier than
19201899
// trying the elements of other disjunctions, which can often mean
19211900
// we fail faster.
1922-
if (!bindingDisjunctions.empty())
1923-
return bindingDisjunctions[0];
1924-
1925-
return nullptr;
1901+
return firstBindDisjunction;
19261902
}
19271903

19281904
Constraint *ConstraintSystem::selectDisjunction() {

lib/Sema/Constraint.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -722,6 +722,25 @@ Constraint *Constraint::createDisjunction(ConstraintSystem &cs,
722722
return constraints.front();
723723
}
724724

725+
#ifndef NDEBUG
726+
assert(!constraints.empty());
727+
// Verify that all disjunction choices have the same left-hand side.
728+
Type commonType;
729+
assert(llvm::all_of(constraints, [&](const Constraint *choice) -> bool {
730+
// if this disjunction is formed from "fixed"
731+
// constraints let's not try to validate.
732+
if (choice->HasRestriction || choice->getFix())
733+
return true;
734+
735+
auto currentType = choice->getFirstType();
736+
if (!commonType) {
737+
commonType = currentType;
738+
return true;
739+
}
740+
return commonType->isEqual(currentType);
741+
}));
742+
#endif
743+
725744
// Create the disjunction constraint.
726745
uniqueTypeVariables(typeVars);
727746
unsigned size = totalSizeToAlloc<TypeVariableType*>(typeVars.size());

0 commit comments

Comments
 (0)