Skip to content

Commit 60246a2

Browse files
committed
Sema: Further split up getTypeOfMemberTypeReference()
1 parent 68be47f commit 60246a2

File tree

2 files changed

+156
-124
lines changed

2 files changed

+156
-124
lines changed

include/swift/Sema/ConstraintSystem.h

Lines changed: 33 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4456,30 +4456,6 @@ class ConstraintSystem {
44564456
DeclContext *useDC,
44574457
PreparedOverloadBuilder *preparedOverload);
44584458

4459-
/// Return the type-of-reference of the given value.
4460-
///
4461-
/// \param baseType if non-null, return the type of a member reference to
4462-
/// this value when the base has the given type
4463-
///
4464-
/// \param UseDC The context of the access. Some variables have different
4465-
/// types depending on where they are used.
4466-
///
4467-
/// \param locator The locator anchored at this value reference, when
4468-
/// it is a member reference.
4469-
///
4470-
/// \param wantInterfaceType Whether we want the interface type, if available.
4471-
Type getUnopenedTypeOfReference(VarDecl *value, Type baseType,
4472-
DeclContext *UseDC,
4473-
ConstraintLocator *locator,
4474-
bool wantInterfaceType);
4475-
4476-
/// Given the opened type and a pile of information about a member reference,
4477-
/// determine the reference type of the member reference.
4478-
Type getMemberReferenceTypeFromOpenedType(
4479-
Type type, Type baseObjTy, ValueDecl *value, DeclContext *outerDC,
4480-
ConstraintLocator *locator, bool hasAppliedSelf, bool isDynamicLookup,
4481-
ArrayRef<OpenedType> replacements);
4482-
44834459
/// Retrieve the type of a reference to the given value declaration,
44844460
/// as a member with a base of the given type.
44854461
///
@@ -4507,6 +4483,39 @@ class ConstraintSystem {
45074483
}
45084484

45094485
private:
4486+
DeclReferenceType getTypeOfMemberTypeReference(
4487+
Type baseObjTy, TypeDecl *typeDecl, ConstraintLocator *locator,
4488+
PreparedOverloadBuilder *preparedOverload);
4489+
4490+
/// Return the type-of-reference of the given value.
4491+
///
4492+
/// \param baseType if non-null, return the type of a member reference to
4493+
/// this value when the base has the given type
4494+
///
4495+
/// \param UseDC The context of the access. Some variables have different
4496+
/// types depending on where they are used.
4497+
///
4498+
/// \param locator The locator anchored at this value reference, when
4499+
/// it is a member reference.
4500+
///
4501+
/// \param wantInterfaceType Whether we want the interface type, if available.
4502+
Type getUnopenedTypeOfReference(VarDecl *value, Type baseType,
4503+
DeclContext *UseDC,
4504+
ConstraintLocator *locator,
4505+
bool wantInterfaceType);
4506+
4507+
std::pair<Type, Type> getOpenedStorageType(
4508+
Type baseTy, AbstractStorageDecl *value, DeclContext *useDC,
4509+
bool hasAppliedSelf, ArrayRef<OpenedType> replacements,
4510+
ConstraintLocator *locator, PreparedOverloadBuilder *preparedOverload);
4511+
4512+
/// Given the opened type and a pile of information about a member reference,
4513+
/// determine the reference type of the member reference.
4514+
Type getMemberReferenceTypeFromOpenedType(
4515+
Type type, Type baseObjTy, ValueDecl *value,
4516+
ConstraintLocator *locator, bool hasAppliedSelf, bool isDynamicLookup,
4517+
ArrayRef<OpenedType> replacements);
4518+
45104519
/// Add the constraints needed to bind an overload's type variable.
45114520
void bindOverloadType(const SelectedOverload &overload, Type boundType,
45124521
ConstraintLocator *locator, DeclContext *useDC);

lib/Sema/TypeOfReference.cpp

Lines changed: 123 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -1427,6 +1427,111 @@ void ConstraintSystem::openGenericRequirement(
14271427
preparedOverload);
14281428
}
14291429

1430+
DeclReferenceType ConstraintSystem::getTypeOfMemberTypeReference(
1431+
Type baseObjTy, TypeDecl *typeDecl, ConstraintLocator *locator,
1432+
PreparedOverloadBuilder *preparedOverload) {
1433+
assert(!isa<ModuleDecl>(typeDecl) && "Nested module?");
1434+
1435+
auto memberTy = TypeChecker::substMemberTypeWithBase(typeDecl, baseObjTy);
1436+
1437+
// If the member type is a constraint, e.g. because the
1438+
// reference is to a typealias with an underlying protocol
1439+
// or composition type, the member reference has existential
1440+
// type.
1441+
if (memberTy->isConstraintType())
1442+
memberTy = ExistentialType::get(memberTy);
1443+
1444+
checkNestedTypeConstraints(*this, memberTy, locator, preparedOverload);
1445+
1446+
// Convert any placeholders and open any generics.
1447+
memberTy = replaceInferableTypesWithTypeVars(
1448+
memberTy, locator, preparedOverload);
1449+
1450+
// Wrap it in a metatype, unless this is a value generic.
1451+
// 'substMemberTypeWithBase' returns the underlying value type
1452+
// of the value generic (e.g. 'Int').
1453+
if (!isa<GenericTypeParamDecl>(typeDecl) ||
1454+
!cast<GenericTypeParamDecl>(typeDecl)->isValue()) {
1455+
memberTy = MetatypeType::get(memberTy);
1456+
}
1457+
1458+
FunctionType::Param baseObjParam(baseObjTy);
1459+
auto openedType = FunctionType::get({baseObjParam}, memberTy);
1460+
return { openedType, openedType, memberTy, memberTy, Type() };
1461+
}
1462+
1463+
std::pair<Type, Type> ConstraintSystem::getOpenedStorageType(
1464+
Type baseTy, AbstractStorageDecl *value, DeclContext *useDC,
1465+
bool hasAppliedSelf, ArrayRef<OpenedType> replacements,
1466+
ConstraintLocator *locator, PreparedOverloadBuilder *preparedOverload) {
1467+
Type thrownErrorType;
1468+
1469+
if (auto accessor = value->getEffectfulGetAccessor()) {
1470+
thrownErrorType = accessor->getEffectiveThrownErrorType().value_or(Type());
1471+
}
1472+
1473+
// For a property, build a type (Self) -> PropType.
1474+
// For a subscript, build a type (Self) -> (Indices...) throws(?) -> ElementType.
1475+
//
1476+
// If the access is mutating, wrap the storage type in an lvalue type.
1477+
Type refType;
1478+
if (auto *subscript = dyn_cast<SubscriptDecl>(value)) {
1479+
auto elementTy = subscript->getElementInterfaceType();
1480+
1481+
if (doesStorageProduceLValue(subscript, baseTy, useDC, *this, locator))
1482+
elementTy = LValueType::get(elementTy);
1483+
1484+
auto indices = subscript->getInterfaceType()
1485+
->castTo<AnyFunctionType>()->getParams();
1486+
1487+
// Transfer the thrown error type into the subscript reference type,
1488+
// which will be used in the application.
1489+
FunctionType::ExtInfo info;
1490+
if (thrownErrorType) {
1491+
info = info.withThrows(true, thrownErrorType);
1492+
thrownErrorType = Type();
1493+
}
1494+
1495+
refType = FunctionType::get(indices, elementTy, info);
1496+
} else {
1497+
// Delay the adjustment for preconcurrency until after we've formed
1498+
// the function type for this kind of reference. Otherwise we will lose
1499+
// track of the adjustment in the formed function's return type.
1500+
1501+
refType = getUnopenedTypeOfReference(cast<VarDecl>(value), baseTy, useDC,
1502+
locator,
1503+
/*wantInterfaceType=*/true);
1504+
}
1505+
1506+
auto *outerDC = value->getDeclContext();
1507+
auto selfTy = outerDC->getSelfInterfaceType();
1508+
1509+
// If this is a reference to an instance member that applies self,
1510+
// where self is a value type and the base type is an lvalue, wrap it in an
1511+
// inout type.
1512+
auto selfFlags = ParameterTypeFlags();
1513+
if (value->isInstanceMember() && hasAppliedSelf &&
1514+
!outerDC->getDeclaredInterfaceType()->hasReferenceSemantics() &&
1515+
baseTy->is<LValueType>() &&
1516+
!selfTy->hasError())
1517+
selfFlags = selfFlags.withInOut(true);
1518+
1519+
// If the storage is generic, open the self and ref types.
1520+
selfTy = openType(selfTy, replacements, locator, preparedOverload);
1521+
refType = openType(refType, replacements, locator, preparedOverload);
1522+
1523+
if (thrownErrorType) {
1524+
thrownErrorType = openType(thrownErrorType, replacements, locator,
1525+
preparedOverload);
1526+
}
1527+
1528+
FunctionType::Param selfParam(selfTy, Identifier(), selfFlags);
1529+
1530+
FunctionType::ExtInfo info;
1531+
return std::make_pair(thrownErrorType,
1532+
FunctionType::get({selfParam}, refType, info));
1533+
}
1534+
14301535
/// Add the constraint on the type used for the 'Self' type for a member
14311536
/// reference.
14321537
///
@@ -1552,9 +1657,11 @@ static bool isExistentialMemberAccessWithExplicitBaseExpression(
15521657
}
15531658

15541659
Type ConstraintSystem::getMemberReferenceTypeFromOpenedType(
1555-
Type type, Type baseObjTy, ValueDecl *value, DeclContext *outerDC,
1660+
Type type, Type baseObjTy, ValueDecl *value,
15561661
ConstraintLocator *locator, bool hasAppliedSelf, bool isDynamicLookup,
15571662
ArrayRef<OpenedType> replacements) {
1663+
auto *outerDC = value->getDeclContext();
1664+
15581665
// Cope with dynamic 'Self'.
15591666
if (outerDC->getSelfClassDecl()) {
15601667
if (type->hasDynamicSelfType()) {
@@ -1667,34 +1774,8 @@ DeclReferenceType ConstraintSystem::getTypeOfMemberReference(
16671774
}
16681775

16691776
if (auto *typeDecl = dyn_cast<TypeDecl>(value)) {
1670-
assert(!isa<ModuleDecl>(typeDecl) && "Nested module?");
1671-
1672-
auto memberTy = TypeChecker::substMemberTypeWithBase(typeDecl, baseObjTy);
1673-
1674-
// If the member type is a constraint, e.g. because the
1675-
// reference is to a typealias with an underlying protocol
1676-
// or composition type, the member reference has existential
1677-
// type.
1678-
if (memberTy->isConstraintType())
1679-
memberTy = ExistentialType::get(memberTy);
1680-
1681-
checkNestedTypeConstraints(*this, memberTy, locator, preparedOverload);
1682-
1683-
// Convert any placeholders and open any generics.
1684-
memberTy = replaceInferableTypesWithTypeVars(
1685-
memberTy, locator, preparedOverload);
1686-
1687-
// Wrap it in a metatype, unless this is a value generic.
1688-
// 'substMemberTypeWithBase' returns the underlying value type
1689-
// of the value generic (e.g. 'Int').
1690-
if (!isa<GenericTypeParamDecl>(value) ||
1691-
!cast<GenericTypeParamDecl>(value)->isValue()) {
1692-
memberTy = MetatypeType::get(memberTy);
1693-
}
1694-
1695-
FunctionType::Param baseObjParam(baseObjTy);
1696-
auto openedType = FunctionType::get({baseObjParam}, memberTy);
1697-
return { openedType, openedType, memberTy, memberTy, Type() };
1777+
return getTypeOfMemberTypeReference(baseObjTy, typeDecl,
1778+
locator, preparedOverload);
16981779
}
16991780

17001781
// Figure out the declaration context to use when opening this type.
@@ -1704,7 +1785,6 @@ DeclReferenceType ConstraintSystem::getTypeOfMemberReference(
17041785
auto genericSig = innerDC->getGenericSignatureOfContext();
17051786

17061787
// Open the type of the generic function or member of a generic type.
1707-
Type openedType;
17081788
ArrayRef<OpenedType> replacements;
17091789
SmallVector<OpenedType, 4> localReplacements;
17101790
{
@@ -1731,6 +1811,7 @@ DeclReferenceType ConstraintSystem::getTypeOfMemberReference(
17311811
// strip it off later.
17321812
auto hasAppliedSelf = doesMemberRefApplyCurriedSelf(baseRValueTy, value);
17331813

1814+
Type openedType;
17341815
Type thrownErrorType;
17351816
if (isa<AbstractFunctionDecl>(value) ||
17361817
isa<EnumElementDecl>(value) ||
@@ -1755,77 +1836,18 @@ DeclReferenceType ConstraintSystem::getTypeOfMemberReference(
17551836
});
17561837
}
17571838
} else {
1758-
// If the storage has a throwing getter, save the thrown error type..
1759-
auto storage = cast<AbstractStorageDecl>(value);
1760-
if (auto accessor = storage->getEffectfulGetAccessor()) {
1761-
thrownErrorType = accessor->getEffectiveThrownErrorType().value_or(Type());
1762-
}
1839+
auto *storage = cast<AbstractStorageDecl>(value);
17631840

1764-
// For a property, build a type (Self) -> PropType.
1765-
// For a subscript, build a type (Self) -> (Indices...) throws(?) -> ElementType.
1766-
//
1767-
// If the access is mutating, wrap the storage type in an lvalue type.
1768-
Type refType;
1769-
if (auto *subscript = dyn_cast<SubscriptDecl>(value)) {
1770-
auto elementTy = subscript->getElementInterfaceType();
1771-
1772-
if (doesStorageProduceLValue(subscript, baseTy, useDC, *this, locator))
1773-
elementTy = LValueType::get(elementTy);
1774-
1775-
auto indices = subscript->getInterfaceType()
1776-
->castTo<AnyFunctionType>()->getParams();
1777-
1778-
// Transfer the thrown error type into the subscript reference type,
1779-
// which will be used in the application.
1780-
FunctionType::ExtInfo info;
1781-
if (thrownErrorType) {
1782-
info = info.withThrows(true, thrownErrorType);
1783-
thrownErrorType = Type();
1784-
}
1785-
1786-
refType = FunctionType::get(indices, elementTy, info);
1787-
} else {
1788-
// Delay the adjustment for preconcurrency until after we've formed
1789-
// the function type for this kind of reference. Otherwise we will lose
1790-
// track of the adjustment in the formed function's return type.
1791-
1792-
refType = getUnopenedTypeOfReference(cast<VarDecl>(value), baseTy, useDC,
1793-
locator,
1794-
/*wantInterfaceType=*/true);
1795-
}
1796-
1797-
auto selfTy = outerDC->getSelfInterfaceType();
1798-
1799-
// If this is a reference to an instance member that applies self,
1800-
// where self is a value type and the base type is an lvalue, wrap it in an
1801-
// inout type.
1802-
auto selfFlags = ParameterTypeFlags();
1803-
if (value->isInstanceMember() && hasAppliedSelf &&
1804-
!outerDC->getDeclaredInterfaceType()->hasReferenceSemantics() &&
1805-
baseTy->is<LValueType>() &&
1806-
!selfTy->hasError())
1807-
selfFlags = selfFlags.withInOut(true);
1808-
1809-
// If the storage is generic, open the self and ref types.
1810-
if (genericSig) {
1811-
selfTy = openType(selfTy, replacements, locator, preparedOverload);
1812-
refType = openType(refType, replacements, locator, preparedOverload);
1813-
1814-
if (thrownErrorType) {
1815-
thrownErrorType = openType(thrownErrorType, replacements, locator,
1816-
preparedOverload);
1817-
}
1818-
}
1819-
FunctionType::Param selfParam(selfTy, Identifier(), selfFlags);
1820-
1821-
FunctionType::ExtInfo info;
1822-
openedType = FunctionType::get({selfParam}, refType, info);
1841+
std::tie(thrownErrorType, openedType) = getOpenedStorageType(
1842+
baseTy, storage, useDC, hasAppliedSelf, replacements, locator,
1843+
preparedOverload);
18231844
}
1824-
assert(!openedType->hasTypeParameter());
18251845

1846+
ASSERT(!openedType->hasTypeParameter());
1847+
1848+
// Remove argument labels if this is an unapplied reference.
18261849
unsigned numRemovedArgumentLabels = getNumRemovedArgumentLabels(
18271850
value, /*isCurriedInstanceReference*/ !hasAppliedSelf, functionRefInfo);
1828-
18291851
openedType = openedType->removeArgumentLabels(numRemovedArgumentLabels);
18301852

18311853
Type baseOpenedTy = baseObjTy;
@@ -1897,6 +1919,7 @@ DeclReferenceType ConstraintSystem::getTypeOfMemberReference(
18971919
}, preparedOverload);
18981920
}
18991921

1922+
// Unwrap property wrappers if this is an unapplied reference.
19001923
if (auto *funcDecl = dyn_cast<AbstractFunctionDecl>(value)) {
19011924
if (functionRefInfo.isUnapplied()) {
19021925
auto *fullFunctionType = openedType->getAs<AnyFunctionType>();
@@ -1938,24 +1961,24 @@ DeclReferenceType ConstraintSystem::getTypeOfMemberReference(
19381961
origFnType->getParams(), resultTy, origFnType->getExtInfo());
19391962
}
19401963

1941-
// Check if we need to apply a layer of optionality to the uncurried type.
1964+
// Check if we need to apply a layer of optionality to the type.
19421965
if (!isRequirementOrWitness(locator)) {
19431966
if (isDynamicLookup || value->getAttrs().hasAttribute<OptionalAttr>()) {
19441967
openedType = applyOptionality(value, openedType->castTo<FunctionType>());
19451968
origOpenedType = applyOptionality(value, origOpenedType->castTo<FunctionType>());
19461969
}
19471970
}
19481971

1949-
// Compute the type of the reference.
1972+
// Handle DynamicSelfType and a couple of other things.
19501973
Type type = getMemberReferenceTypeFromOpenedType(
1951-
openedType, baseObjTy, value, outerDC, locator, hasAppliedSelf,
1974+
openedType, baseObjTy, value, locator, hasAppliedSelf,
19521975
isDynamicLookup, replacements);
19531976

19541977
// Do the same thing for the original type, if there can be any difference.
19551978
Type origType = type;
19561979
if (openedType.getPointer() != origOpenedType.getPointer()) {
19571980
origType = getMemberReferenceTypeFromOpenedType(
1958-
origOpenedType, baseObjTy, value, outerDC, locator, hasAppliedSelf,
1981+
origOpenedType, baseObjTy, value, locator, hasAppliedSelf,
19591982
isDynamicLookup, replacements);
19601983
}
19611984

0 commit comments

Comments
 (0)