@@ -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
15541659Type 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