@@ -1285,8 +1285,8 @@ namespace {
1285
1285
ConstraintLocatorBuilder locator,
1286
1286
ConstraintLocatorBuilder memberLocator, bool Implicit,
1287
1287
AccessSemantics semantics) {
1288
- auto choice = overload.choice ;
1289
- auto openedType = overload.openedType ;
1288
+ const auto & choice = overload.choice ;
1289
+ const auto openedType = overload.openedType ;
1290
1290
1291
1291
ValueDecl *member = choice.getDecl ();
1292
1292
@@ -1369,9 +1369,10 @@ namespace {
1369
1369
return forceUnwrapIfExpected (DSBI, choice, memberLocator);
1370
1370
}
1371
1371
1372
- bool isUnboundInstanceMember =
1373
- (!baseIsInstance && member->isInstanceMember ());
1374
- bool isPartialApplication = shouldBuildCurryThunk (choice, baseIsInstance);
1372
+ const bool isUnboundInstanceMember =
1373
+ (!baseIsInstance && member->isInstanceMember ());
1374
+ const bool isPartialApplication =
1375
+ shouldBuildCurryThunk (choice, baseIsInstance);
1375
1376
1376
1377
// The formal type of the 'self' value for the member's declaration.
1377
1378
Type containerTy = getBaseType (refTy->castTo <FunctionType>());
@@ -1531,8 +1532,8 @@ namespace {
1531
1532
base->setImplicit ();
1532
1533
}
1533
1534
1534
- auto hasDynamicSelf =
1535
- varDecl->getValueInterfaceType ()->hasDynamicSelfType ();
1535
+ const auto hasDynamicSelf =
1536
+ varDecl->getValueInterfaceType ()->hasDynamicSelfType ();
1536
1537
1537
1538
auto memberRefExpr
1538
1539
= new (context) MemberRefExpr (base, dotLoc, memberRef,
@@ -1546,11 +1547,15 @@ namespace {
1546
1547
Expr *result = memberRefExpr;
1547
1548
closeExistential (result, locator);
1548
1549
1550
+ // If the property is of dynamic 'Self' type, wrap an implicit
1551
+ // conversion around the resulting expression, with the destination
1552
+ // type having 'Self' swapped for the appropriate replacement
1553
+ // type -- usually the base object type.
1549
1554
if (hasDynamicSelf) {
1550
- if (!baseTy-> isEqual (containerTy)) {
1551
- result = new (context) CovariantReturnConversionExpr (
1552
- result, simplifyType (openedType));
1553
- cs. cacheType ( result);
1555
+ const auto conversionTy = simplifyType (openedType);
1556
+ if (!containerTy-> isEqual (conversionTy)) {
1557
+ result = cs. cacheType ( new (context) CovariantReturnConversionExpr (
1558
+ result, conversionTy) );
1554
1559
}
1555
1560
}
1556
1561
return forceUnwrapIfExpected (result, choice, memberLocator);
@@ -1567,9 +1572,8 @@ namespace {
1567
1572
cs.setType (declRefExpr, refTy);
1568
1573
Expr *ref = declRefExpr;
1569
1574
1570
- if (isPartialApplication) {
1571
- auto curryThunkTy = refTy->castTo <FunctionType>();
1572
-
1575
+ const auto isSuperPartialApplication = isPartialApplication && isSuper;
1576
+ if (isSuperPartialApplication) {
1573
1577
// A partial application thunk consists of two nested closures:
1574
1578
//
1575
1579
// { self in { args... in self.method(args...) } }
@@ -1588,17 +1592,12 @@ namespace {
1588
1592
// very specific shape, we only emit a single closure here and
1589
1593
// capture the original SuperRefExpr, since its evaluation does not
1590
1594
// have side effects, instead of abstracting out a 'self' parameter.
1591
- if (isSuper) {
1592
- auto selfFnTy = curryThunkTy->getResult ()->castTo <FunctionType>();
1593
-
1594
- auto closure = buildCurryThunk (member, selfFnTy, base, ref,
1595
- memberLocator);
1595
+ const auto selfFnTy =
1596
+ refTy->castTo <FunctionType>()->getResult ()->castTo <FunctionType>();
1596
1597
1597
- // Skip the code below -- we're not building an extra level of
1598
- // call by applying the 'super', instead the closure we just
1599
- // built is the curried reference.
1600
- return closure;
1601
- }
1598
+ ref = buildCurryThunk (member, selfFnTy, base, ref, memberLocator);
1599
+ } else if (isPartialApplication) {
1600
+ auto curryThunkTy = refTy->castTo <FunctionType>();
1602
1601
1603
1602
// Another case where we want to build a single closure is when
1604
1603
// we have a partial application of a constructor on a statically-
@@ -1618,7 +1617,7 @@ namespace {
1618
1617
memberLocator);
1619
1618
1620
1619
// Skip the code below -- we're not building an extra level of
1621
- // call by applying the metatype instead the closure we just
1620
+ // call by applying the metatype; instead, the closure we just
1622
1621
// built is the curried reference.
1623
1622
return closure;
1624
1623
}
@@ -1695,22 +1694,41 @@ namespace {
1695
1694
ref = outerClosure;
1696
1695
}
1697
1696
1698
- // If this is a method whose result type is dynamic Self, or a
1699
- // construction, replace the result type with the actual object type.
1697
+ // If the member is a method with a dynamic 'Self' result type, wrap an
1698
+ // implicit function type conversion around the resulting expression,
1699
+ // with the destination type having 'Self' swapped for the appropriate
1700
+ // replacement type -- usually the base object type.
1700
1701
if (!member->getDeclContext ()->getSelfProtocolDecl ()) {
1701
1702
if (auto func = dyn_cast<AbstractFunctionDecl>(member)) {
1702
1703
if (func->hasDynamicSelfResult () &&
1703
1704
!baseTy->getOptionalObjectType ()) {
1704
- if (!baseTy->isEqual (containerTy)) {
1705
- auto dynamicSelfFnType = refTy->replaceCovariantResultType (baseTy, 2 );
1706
- ref = new (context) CovariantFunctionConversionExpr (ref,
1707
- dynamicSelfFnType);
1708
- cs.cacheType (ref);
1705
+ // FIXME: Once CovariantReturnConversionExpr (unchecked_ref_cast)
1706
+ // supports a class existential dest., consider using the opened
1707
+ // type directly to avoid recomputing the 'Self' replacement and
1708
+ // substituting.
1709
+ const Type replacementTy = getDynamicSelfReplacementType (
1710
+ baseTy, member, memberLocator.getBaseLocator ());
1711
+ if (!replacementTy->isEqual (containerTy)) {
1712
+ Type conversionTy =
1713
+ refTy->replaceCovariantResultType (replacementTy, 2 );
1714
+ if (isSuperPartialApplication) {
1715
+ conversionTy =
1716
+ conversionTy->castTo <FunctionType>()->getResult ();
1717
+ }
1718
+
1719
+ ref = cs.cacheType (new (context) CovariantFunctionConversionExpr (
1720
+ ref, conversionTy));
1709
1721
}
1710
1722
}
1711
1723
}
1712
1724
}
1713
1725
1726
+ // The thunk that is built for a 'super' method reference does not
1727
+ // require application.
1728
+ if (isSuperPartialApplication) {
1729
+ return forceUnwrapIfExpected (ref, choice, memberLocator);
1730
+ }
1731
+
1714
1732
ApplyExpr *apply;
1715
1733
if (isa<ConstructorDecl>(member)) {
1716
1734
// FIXME: Provide type annotation.
@@ -2113,22 +2131,35 @@ namespace {
2113
2131
if (!base)
2114
2132
return nullptr ;
2115
2133
2134
+ const auto hasDynamicSelf =
2135
+ subscript->getElementInterfaceType ()->hasDynamicSelfType ();
2136
+
2116
2137
// Form the subscript expression.
2117
2138
auto subscriptExpr = SubscriptExpr::create (
2118
2139
ctx, base, index, subscriptRef, isImplicit, semantics, getType);
2119
2140
cs.setType (subscriptExpr, fullSubscriptTy->getResult ());
2120
2141
subscriptExpr->setIsSuper (isSuper);
2142
+ cs.setType (subscriptExpr,
2143
+ hasDynamicSelf
2144
+ ? fullSubscriptTy->getResult ()->replaceCovariantResultType (
2145
+ containerTy, 0 )
2146
+ : fullSubscriptTy->getResult ());
2121
2147
2122
2148
Expr *result = subscriptExpr;
2123
2149
closeExistential (result, locator);
2124
2150
2125
- if (subscript->getElementInterfaceType ()->hasDynamicSelfType ()) {
2126
- auto dynamicSelfFnType =
2127
- openedFullFnType->replaceCovariantResultType (baseTy, 2 );
2128
- result =
2129
- new (ctx) CovariantReturnConversionExpr (result, dynamicSelfFnType);
2130
- cs.cacheType (result);
2131
- cs.setType (result, simplifyType (baseTy));
2151
+ // If the element is of dynamic 'Self' type, wrap an implicit conversion
2152
+ // around the resulting expression, with the destination type having
2153
+ // 'Self' swapped for the appropriate replacement type -- usually the
2154
+ // base object type.
2155
+ if (hasDynamicSelf) {
2156
+ const auto conversionTy = simplifyType (
2157
+ selected.openedType ->castTo <FunctionType>()->getResult ());
2158
+
2159
+ if (!containerTy->isEqual (conversionTy)) {
2160
+ result = cs.cacheType (
2161
+ new (ctx) CovariantReturnConversionExpr (result, conversionTy));
2162
+ }
2132
2163
}
2133
2164
2134
2165
return result;
0 commit comments