Skip to content

Commit c0917c9

Browse files
committed
[Constraint solver] Revert the "common type" optimization.
The "common type" optimization isn't really buying us anything at this point, because we're not able to make much use of the common structure often enough. Revert the "common type" optimization for now... I'll bring it back when there's enough optimization infrastructure around it to make it compelling.
1 parent 2e2ba8f commit c0917c9

File tree

2 files changed

+0
-332
lines changed

2 files changed

+0
-332
lines changed

lib/Sema/ConstraintSystem.cpp

Lines changed: 0 additions & 322 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
#include "TypeCheckType.h"
2222
#include "swift/AST/GenericEnvironment.h"
2323
#include "swift/AST/ParameterList.h"
24-
#include "swift/AST/TypeVisitor.h"
2524
#include "swift/Basic/Statistic.h"
2625
#include "llvm/ADT/SetVector.h"
2726
#include "llvm/ADT/SmallString.h"
@@ -1569,320 +1568,6 @@ Type ConstraintSystem::getEffectiveOverloadType(const OverloadChoice &overload,
15691568
return type;
15701569
}
15711570

1572-
namespace {
1573-
/// Type visitor that extracts the common type between two types, when
1574-
/// possible.
1575-
class CommonTypeVisitor : public TypeVisitor<CommonTypeVisitor, Type, Type> {
1576-
/// Perform a "leaf" match for types, which does not consider the children.
1577-
Type handleLeafMatch(Type type1, Type type2) {
1578-
if (type1->isEqual(type2))
1579-
return type1;
1580-
1581-
return handleMismatch(type1, type2);
1582-
}
1583-
1584-
/// Handle a mismatch between two types.
1585-
Type handleMismatch(Type type1, Type type2) {
1586-
return Type();
1587-
}
1588-
1589-
public:
1590-
Type visitTupleType(TupleType *tuple1, Type type2) {
1591-
if (tuple1->isEqual(type2))
1592-
return Type(tuple1);
1593-
1594-
auto tuple2 = type2->getAs<TupleType>();
1595-
if (!tuple2) {
1596-
return handleMismatch(Type(tuple1), type2);
1597-
}
1598-
1599-
// Check for structural similarity between the two tuple types.
1600-
auto elements1 = tuple1->getElements();
1601-
auto elements2 = tuple2->getElements();
1602-
if (elements1.size() != elements2.size()) {
1603-
return handleMismatch(Type(tuple1), type2);
1604-
}
1605-
1606-
for (unsigned i : indices(elements1)) {
1607-
const auto &elt1 = elements1[i];
1608-
const auto &elt2 = elements2[i];
1609-
if (elt1.getName() != elt2.getName() ||
1610-
elt1.getParameterFlags() != elt2.getParameterFlags()) {
1611-
return handleMismatch(Type(tuple1), type2);
1612-
}
1613-
}
1614-
1615-
// Recurse on the element types.
1616-
SmallVector<TupleTypeElt, 4> newElements;
1617-
newElements.reserve(elements1.size());
1618-
for (unsigned i : indices(elements1)) {
1619-
const auto &elt1 = elements1[i];
1620-
const auto &elt2 = elements2[i];
1621-
Type elementType = visit(elt1.getRawType(), elt2.getRawType());
1622-
if (!elementType) {
1623-
return handleMismatch(Type(tuple1), type2);
1624-
}
1625-
1626-
newElements.push_back(elt1.getWithType(elementType));
1627-
}
1628-
return TupleType::get(newElements, tuple1->getASTContext());
1629-
}
1630-
1631-
Type visitReferenceStorageType(ReferenceStorageType *refStorage1,
1632-
Type type2) {
1633-
if (refStorage1->isEqual(type2))
1634-
return Type(refStorage1);
1635-
1636-
auto refStorage2 = type2->getAs<ReferenceStorageType>();
1637-
if (!refStorage2 ||
1638-
refStorage1->getOwnership() != refStorage2->getOwnership()) {
1639-
return handleMismatch(Type(refStorage1), type2);
1640-
}
1641-
1642-
Type newReferentType = visit(refStorage1->getReferentType(),
1643-
refStorage2->getReferentType());
1644-
if (!newReferentType) {
1645-
return handleMismatch(Type(refStorage1), type2);
1646-
}
1647-
1648-
return ReferenceStorageType::get(newReferentType,
1649-
refStorage1->getOwnership(),
1650-
refStorage1->getASTContext());
1651-
}
1652-
1653-
Type visitAnyMetatypeType(AnyMetatypeType *metatype1, Type type2) {
1654-
if (metatype1->isEqual(type2))
1655-
return Type(metatype1);
1656-
1657-
1658-
auto metatype2 = type2->getAs<AnyMetatypeType>();
1659-
if (!metatype2) {
1660-
return handleMismatch(Type(metatype1), type2);
1661-
}
1662-
1663-
if (metatype1->getKind() != metatype2->getKind() ||
1664-
metatype1->hasRepresentation() != metatype2->hasRepresentation() ||
1665-
(metatype1->hasRepresentation() &&
1666-
metatype2->getRepresentation() != metatype2->getRepresentation())) {
1667-
return handleMismatch(Type(metatype1), type2);
1668-
}
1669-
1670-
Type newInstanceType = visit(metatype1->getInstanceType(),
1671-
metatype2->getInstanceType());
1672-
if (!newInstanceType) {
1673-
return handleMismatch(Type(metatype1), type2);
1674-
}
1675-
1676-
Optional<MetatypeRepresentation> representation;
1677-
if (metatype1->hasRepresentation())
1678-
representation = metatype1->getRepresentation();
1679-
1680-
if (metatype1->getKind() == TypeKind::Metatype)
1681-
return MetatypeType::get(newInstanceType, representation);
1682-
1683-
assert(metatype1->getKind() == TypeKind::ExistentialMetatype);
1684-
return ExistentialMetatypeType::get(newInstanceType, representation);
1685-
}
1686-
1687-
Type visitFunctionType(FunctionType *function1, Type type2) {
1688-
if (function1->isEqual(type2))
1689-
return Type(function1);
1690-
1691-
auto function2 = type2->getAs<FunctionType>();
1692-
if (!function2 ||
1693-
function1->getExtInfo() != function2->getExtInfo() ||
1694-
function1->getNumParams() != function2->getNumParams()) {
1695-
return handleMismatch(Type(function1), type2);
1696-
}
1697-
1698-
// Check for a structural match between the parameters.
1699-
auto params1 = function1->getParams();
1700-
auto params2 = function2->getParams();
1701-
for (unsigned i : indices(params1)) {
1702-
const auto &param1 = params1[i];
1703-
const auto &param2 = params2[i];
1704-
if (param1.getLabel() != param2.getLabel() ||
1705-
param1.getParameterFlags() != param2.getParameterFlags()) {
1706-
return handleMismatch(Type(function1), type2);
1707-
}
1708-
}
1709-
1710-
Type newResultType = visit(function1->getResult(), function2->getResult());
1711-
if (!newResultType) {
1712-
return handleMismatch(Type(function1), type2);
1713-
}
1714-
1715-
SmallVector<AnyFunctionType::Param, 4> newParams;
1716-
newParams.reserve(params1.size());
1717-
for (unsigned i : indices(params1)) {
1718-
const auto &param1 = params1[i];
1719-
const auto &param2 = params2[i];
1720-
Type newParamType = visit(param1.getPlainType(), param2.getPlainType());
1721-
if (!newParamType) {
1722-
return handleMismatch(Type(function1), type2);
1723-
}
1724-
1725-
newParams.push_back(AnyFunctionType::Param(newParamType,
1726-
param1.getLabel(),
1727-
param1.getParameterFlags()));
1728-
}
1729-
1730-
return FunctionType::get(newParams, newResultType, function1->getExtInfo());
1731-
}
1732-
1733-
Type visitGenericFunctionType(GenericFunctionType *function1, Type type2) {
1734-
llvm_unreachable("Caller should have eliminated these");
1735-
}
1736-
1737-
Type visitLValueType(LValueType *lvalue1, Type type2) {
1738-
if (lvalue1->isEqual(type2))
1739-
return Type(lvalue1);
1740-
1741-
auto lvalue2 = type2->getAs<LValueType>();
1742-
if (!lvalue2) {
1743-
return handleMismatch(Type(lvalue1), type2);
1744-
}
1745-
1746-
Type newObjectType =
1747-
visit(lvalue1->getObjectType(), lvalue2->getObjectType());
1748-
if (!newObjectType) {
1749-
return handleMismatch(Type(lvalue1), type2);
1750-
}
1751-
1752-
return LValueType::get(newObjectType);
1753-
}
1754-
1755-
Type visitInOutType(InOutType *inout1, Type type2) {
1756-
if (inout1->isEqual(type2))
1757-
return Type(inout1);
1758-
1759-
auto inout2 = type2->getAs<InOutType>();
1760-
if (!inout2) {
1761-
return handleMismatch(Type(inout1), type2);
1762-
}
1763-
1764-
Type newObjectType =
1765-
visit(inout1->getObjectType(), inout2->getObjectType());
1766-
if (!newObjectType) {
1767-
return handleMismatch(Type(inout1), type2);
1768-
}
1769-
1770-
return LValueType::get(newObjectType);
1771-
}
1772-
1773-
Type visitSugarType(SugarType *sugar1, Type type2) {
1774-
if (sugar1->isEqual(type2))
1775-
return Type(sugar1);
1776-
1777-
// FIXME: Reconstitute sugar.
1778-
return visit(Type(sugar1->getSinglyDesugaredType()), type2);
1779-
}
1780-
1781-
#define FAILURE_CASE(Class) \
1782-
Type visit##Class##Type(Class##Type *type1, Type type2) { \
1783-
return Type(); \
1784-
}
1785-
1786-
#define LEAF_CASE(Class) \
1787-
Type visit##Class##Type(Class##Type *type1, Type type2) { \
1788-
return handleLeafMatch(Type(type1), type2); \
1789-
}
1790-
1791-
FAILURE_CASE(Error)
1792-
FAILURE_CASE(Unresolved)
1793-
LEAF_CASE(Builtin)
1794-
LEAF_CASE(Nominal) // FIXME: We can do a more specific match here.
1795-
LEAF_CASE(BoundGeneric) // FIXME: We can do a more specific match here.
1796-
FAILURE_CASE(UnboundGeneric)
1797-
LEAF_CASE(Module)
1798-
LEAF_CASE(DynamicSelf) // FIXME: Can we do better here?
1799-
LEAF_CASE(Substitutable)
1800-
LEAF_CASE(DependentMember)
1801-
LEAF_CASE(SILFunction)
1802-
LEAF_CASE(SILBlockStorage)
1803-
LEAF_CASE(SILBox)
1804-
LEAF_CASE(SILToken)
1805-
LEAF_CASE(ProtocolComposition)
1806-
LEAF_CASE(TypeVariable) // FIXME: Could do better here when we create vars
1807-
1808-
#undef LEAF_CASE
1809-
#undef FAILURE_CASE
1810-
};
1811-
1812-
}
1813-
1814-
Type ConstraintSystem::findCommonOverloadType(
1815-
ArrayRef<OverloadChoice> choices,
1816-
ArrayRef<OverloadChoice> outerAlternatives,
1817-
ConstraintLocator *locator) {
1818-
// Local function to consider this new overload choice, updating the
1819-
// "common type". Returns true if this overload cannot be integrated into
1820-
// the common type, at which point there is no "common type".
1821-
Type commonType;
1822-
auto considerOverload = [&](const OverloadChoice &overload) -> bool {
1823-
// If we can't even get a type for the overload, there's nothing more to
1824-
// do.
1825-
Type overloadType =
1826-
getEffectiveOverloadType(overload, /*allowMembers=*/false, /*FIXME:*/DC);
1827-
if (!overloadType) {
1828-
return true;
1829-
}
1830-
1831-
// If this is the first overload, record it's type as the common type.
1832-
if (!commonType) {
1833-
commonType = overloadType;
1834-
return false;
1835-
}
1836-
1837-
// Find the common type between the current common type and the new
1838-
// overload's type.
1839-
commonType = CommonTypeVisitor().visit(commonType, overloadType);
1840-
if (!commonType) {
1841-
return true;
1842-
}
1843-
1844-
return false;
1845-
};
1846-
1847-
// Consider all of the choices and outer alternatives.
1848-
for (const auto &choice : choices) {
1849-
if (considerOverload(choice))
1850-
return Type();
1851-
}
1852-
for (const auto &choice : outerAlternatives) {
1853-
if (considerOverload(choice))
1854-
return Type();
1855-
}
1856-
1857-
assert(commonType && "We can't get here without having a common type");
1858-
1859-
// If our common type contains any generic parameters, open them up into
1860-
// type variables.
1861-
if (commonType->hasTypeParameter()) {
1862-
llvm::SmallDenseMap<const GenericTypeParamType *, TypeVariableType *>
1863-
openedGenericParams;
1864-
commonType = commonType.transformRec([&](TypeBase *type) -> Optional<Type> {
1865-
if (auto genericParam = dyn_cast<GenericTypeParamType>(type)) {
1866-
auto canGenericParam = GenericTypeParamType::get(
1867-
genericParam->getDepth(),
1868-
genericParam->getIndex(),
1869-
type->getASTContext());
1870-
auto knownTypeVar = openedGenericParams.find(canGenericParam);
1871-
if (knownTypeVar != openedGenericParams.end())
1872-
return Type(knownTypeVar->second);
1873-
1874-
auto typeVar = createTypeVariable(locator);
1875-
openedGenericParams[canGenericParam] = typeVar;
1876-
return Type(typeVar);
1877-
}
1878-
1879-
return None;
1880-
});
1881-
}
1882-
1883-
return commonType;
1884-
}
1885-
18861571
void ConstraintSystem::addOverloadSet(Type boundType,
18871572
ArrayRef<OverloadChoice> choices,
18881573
DeclContext *useDC,
@@ -1897,13 +1582,6 @@ void ConstraintSystem::addOverloadSet(Type boundType,
18971582
return;
18981583
}
18991584

1900-
// If we can compute a common type for the overload set, bind that type.
1901-
if (Type commonType = findCommonOverloadType(choices, outerAlternatives,
1902-
locator)) {
1903-
addConstraint(ConstraintKind::Bind, boundType, commonType, locator);
1904-
boundType = commonType;
1905-
}
1906-
19071585
tryOptimizeGenericDisjunction(*this, choices, favoredChoice);
19081586

19091587
SmallVector<OverloadChoice, 4> scratchChoices;

lib/Sema/ConstraintSystem.h

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2376,16 +2376,6 @@ class ConstraintSystem {
23762376
bool allowMembers,
23772377
DeclContext *useDC);
23782378

2379-
/// Given a set of overload choices, try to find a common structure amongst
2380-
/// all of them.
2381-
///
2382-
/// \returns the common type amongst the various overloads, which may contain
2383-
/// fresh type variables that abstract over differences between the different
2384-
/// overloads in the set.
2385-
Type findCommonOverloadType(ArrayRef<OverloadChoice> choices,
2386-
ArrayRef<OverloadChoice> outerAlternatives,
2387-
ConstraintLocator *locator);
2388-
23892379
/// Add a new overload set to the list of unresolved overload
23902380
/// sets.
23912381
void addOverloadSet(Type boundType, ArrayRef<OverloadChoice> choices,

0 commit comments

Comments
 (0)