Skip to content

Commit 2bc198e

Browse files
authored
Merge pull request #19971 from rudkx/sort-designated-types
[ConstraintSystem] Sort the designated types based on actual argument…
2 parents 474ecd5 + 5b4a332 commit 2bc198e

File tree

3 files changed

+86
-3
lines changed

3 files changed

+86
-3
lines changed

lib/Sema/CSSolver.cpp

Lines changed: 79 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1683,14 +1683,91 @@ getOperatorDesignatedNominalTypes(Constraint *bindOverload) {
16831683
return operatorDecl->getDesignatedNominalTypes();
16841684
}
16851685

1686+
void ConstraintSystem::sortDesignatedTypes(
1687+
SmallVectorImpl<NominalTypeDecl *> &nominalTypes,
1688+
Constraint *bindOverload) {
1689+
auto *tyvar = bindOverload->getFirstType()->castTo<TypeVariableType>();
1690+
llvm::SetVector<Constraint *> applicableFns;
1691+
getConstraintGraph().gatherConstraints(
1692+
tyvar, applicableFns, ConstraintGraph::GatheringKind::EquivalenceClass,
1693+
[](Constraint *match) {
1694+
return match->getKind() == ConstraintKind::ApplicableFunction;
1695+
});
1696+
1697+
// FIXME: This is not true when we run the constraint optimizer.
1698+
// assert(applicableFns.size() <= 1);
1699+
1700+
// We have a disjunction for an operator but no application of it,
1701+
// so it's being passed as an argument.
1702+
if (applicableFns.size() == 0)
1703+
return;
1704+
1705+
// FIXME: We have more than one applicable per disjunction as a
1706+
// result of merging disjunction type variables. We may want
1707+
// to rip that out at some point.
1708+
Constraint *foundApplicable = nullptr;
1709+
SmallVector<Optional<Type>, 2> argumentTypes;
1710+
for (auto *applicableFn : applicableFns) {
1711+
argumentTypes.clear();
1712+
auto *fnTy = applicableFn->getFirstType()->castTo<FunctionType>();
1713+
ArgumentInfoCollector argInfo(*this, fnTy);
1714+
// Stop if we hit anything with concrete types or conformances to
1715+
// literals.
1716+
if (!argInfo.getTypes().empty() || !argInfo.getLiteralProtocols().empty()) {
1717+
foundApplicable = applicableFn;
1718+
break;
1719+
}
1720+
}
1721+
1722+
if (!foundApplicable)
1723+
return;
1724+
1725+
// FIXME: It would be good to avoid this redundancy.
1726+
auto *fnTy = foundApplicable->getFirstType()->castTo<FunctionType>();
1727+
ArgumentInfoCollector argInfo(*this, fnTy);
1728+
1729+
size_t nextType = 0;
1730+
for (auto argType : argInfo.getTypes()) {
1731+
auto *nominal = argType->getAnyNominal();
1732+
for (size_t i = nextType + 1; i < nominalTypes.size(); ++i) {
1733+
if (nominal == nominalTypes[i]) {
1734+
std::swap(nominalTypes[nextType], nominalTypes[i]);
1735+
++nextType;
1736+
break;
1737+
}
1738+
}
1739+
}
1740+
1741+
if (nextType + 1 >= nominalTypes.size())
1742+
return;
1743+
1744+
for (auto *protocol : argInfo.getLiteralProtocols()) {
1745+
auto defaultType = TC.getDefaultType(protocol, DC);
1746+
auto *nominal = defaultType->getAnyNominal();
1747+
for (size_t i = nextType + 1; i < nominalTypes.size(); ++i) {
1748+
if (nominal == nominalTypes[i]) {
1749+
std::swap(nominalTypes[nextType], nominalTypes[i]);
1750+
++nextType;
1751+
break;
1752+
}
1753+
}
1754+
}
1755+
}
1756+
16861757
void ConstraintSystem::partitionForDesignatedTypes(
16871758
ArrayRef<Constraint *> Choices, ConstraintMatchLoop forEachChoice,
16881759
PartitionAppendCallback appendPartition) {
16891760

1690-
auto designatedNominalTypes = getOperatorDesignatedNominalTypes(Choices[0]);
1691-
if (designatedNominalTypes.empty())
1761+
auto types = getOperatorDesignatedNominalTypes(Choices[0]);
1762+
if (types.empty())
16921763
return;
16931764

1765+
SmallVector<NominalTypeDecl *, 4> designatedNominalTypes(types.begin(),
1766+
types.end());
1767+
1768+
if (designatedNominalTypes.size() > 1)
1769+
sortDesignatedTypes(designatedNominalTypes, Choices[0]);
1770+
16941771
SmallVector<SmallVector<unsigned, 4>, 4> definedInDesignatedType;
16951772
SmallVector<SmallVector<unsigned, 4>, 4> definedInExtensionOfDesignatedType;
16961773

lib/Sema/ConstraintSystem.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3227,6 +3227,12 @@ class ConstraintSystem {
32273227
typedef std::function<void(SmallVectorImpl<unsigned> &options)>
32283228
PartitionAppendCallback;
32293229

3230+
// Attempt to sort nominalTypes based on what we can discover about
3231+
// calls into the overloads in the disjunction that bindOverload is
3232+
// a part of.
3233+
void sortDesignatedTypes(SmallVectorImpl<NominalTypeDecl *> &nominalTypes,
3234+
Constraint *bindOverload);
3235+
32303236
// Partition the choices in a disjunction based on those that match
32313237
// the designated types for the operator that the disjunction was
32323238
// formed for.

validation-test/Sema/type_checker_perf/fast/rdar17024694.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %target-typecheck-verify-swift -solver-expression-time-threshold=1
1+
// RUN: %target-typecheck-verify-swift -solver-expression-time-threshold=1 -swift-version 5 -solver-disable-shrink -disable-constraint-solver-performance-hacks -solver-enable-operator-designated-types
22
// REQUIRES: tools-release,no_asserts
33

44
_ = (2...100).reversed().filter({ $0 % 11 == 0 }).map {

0 commit comments

Comments
 (0)