@@ -783,6 +783,7 @@ namespace {
783
783
// We don't need to do any further adjustment once we've built the
784
784
// curry thunk.
785
785
return buildSingleCurryThunk (result, fnDecl,
786
+ adjustedFullType->castTo <FunctionType>(),
786
787
adjustedFullType->castTo <FunctionType>(),
787
788
locator);
788
789
}
@@ -1342,6 +1343,7 @@ namespace {
1342
1343
AutoClosureExpr *buildSingleCurryThunk (Expr *baseExpr, Expr *fnExpr,
1343
1344
DeclContext *declOrClosure,
1344
1345
FunctionType *thunkTy,
1346
+ FunctionType *refTy,
1345
1347
ConstraintLocatorBuilder locator) {
1346
1348
const OptionSet<ParameterList::CloneFlags> options =
1347
1349
(ParameterList::Implicit | ParameterList::NamedArguments);
@@ -1404,24 +1406,10 @@ namespace {
1404
1406
if (baseExpr) {
1405
1407
if (auto *fnDecl = dyn_cast<AbstractFunctionDecl>(declOrClosure)) {
1406
1408
if (fnDecl->getDeclContext ()->getSelfClassDecl ()) {
1407
- if (fnDecl->hasDynamicSelfResult ()) {
1408
- Type convTy;
1409
-
1410
- if (cs.getType (baseExpr)->hasOpenedExistential ()) {
1411
- // FIXME: Sometimes we need to convert to an opened existential
1412
- // first, because CovariantReturnConversionExpr does not support
1413
- // direct conversions from a class C to an existential C & P.
1414
- convTy = cs.getType (baseExpr)->getMetatypeInstanceType ();
1415
- if (thunkTy->getResult ()->getOptionalObjectType ())
1416
- convTy = OptionalType::get (thunkTy);
1417
- } else {
1418
- convTy = thunkTy->getResult ();
1419
- }
1420
-
1421
- if (!thunkBody->getType ()->isEqual (convTy)) {
1422
- thunkBody = cs.cacheType (
1423
- new (ctx) CovariantReturnConversionExpr (thunkBody, convTy));
1424
- }
1409
+ auto convTy = refTy->getResult ();
1410
+ if (!thunkBody->getType ()->isEqual (convTy)) {
1411
+ thunkBody = cs.cacheType (
1412
+ new (ctx) CovariantReturnConversionExpr (thunkBody, convTy));
1425
1413
}
1426
1414
}
1427
1415
}
@@ -1460,15 +1448,19 @@ namespace {
1460
1448
// / \param thunkTy The type of the resulting thunk. This should be the
1461
1449
// / type of the \c fnExpr, with any potential adjustments for things like
1462
1450
// / concurrency.
1451
+ // / \param refTy The type of the declaration reference inside the thunk.
1452
+ // / This might involve opened existentials or a covariant
1453
+ // / Self result.
1463
1454
// / \param locator The locator pinned on the function reference carried
1464
1455
// / by \p fnExpr. If the function has associated applied property wrappers,
1465
1456
// / the locator is used to pull them in.
1466
1457
AutoClosureExpr *buildSingleCurryThunk (Expr *fnExpr,
1467
1458
DeclContext *declOrClosure,
1468
1459
FunctionType *thunkTy,
1460
+ FunctionType *refTy,
1469
1461
ConstraintLocatorBuilder locator) {
1470
1462
return buildSingleCurryThunk (/* baseExpr=*/ nullptr , fnExpr, declOrClosure,
1471
- thunkTy, locator);
1463
+ thunkTy, refTy, locator);
1472
1464
}
1473
1465
1474
1466
// / Build a "{ self in { args in self.fn(args) } }" nested curry thunk.
@@ -1478,12 +1470,16 @@ namespace {
1478
1470
// / the parameters of the inner thunk.
1479
1471
// / \param member The underlying function declaration to be called.
1480
1472
// / \param outerThunkTy The type of the outer thunk.
1473
+ // / \param outerRefTy The type of the declaration reference inside the thunk.
1474
+ // / This might involve opened existentials or a covariant
1475
+ // / Self result.
1481
1476
// / \param memberLocator The locator pinned on the member reference. If the
1482
1477
// / function has associated applied property wrappers, the locator is used
1483
1478
// / to pull them in.
1484
1479
AutoClosureExpr *
1485
1480
buildDoubleCurryThunk (DeclRefExpr *memberRef, ValueDecl *member,
1486
1481
FunctionType *outerThunkTy,
1482
+ FunctionType *outerRefTy,
1487
1483
ConstraintLocatorBuilder memberLocator,
1488
1484
DeclNameLoc memberLoc, bool isDynamicLookup) {
1489
1485
const auto selfThunkParam = outerThunkTy->getParams ().front ();
@@ -1596,7 +1592,9 @@ namespace {
1596
1592
} else {
1597
1593
auto *innerThunk = buildSingleCurryThunk (
1598
1594
selfOpenedRef, memberRef, cast<DeclContext>(member),
1599
- outerThunkTy->getResult ()->castTo <FunctionType>(), memberLocator);
1595
+ outerThunkTy->getResult ()->castTo <FunctionType>(),
1596
+ outerRefTy->getResult ()->castTo <FunctionType>(),
1597
+ memberLocator);
1600
1598
assert ((!outerActorIsolation ||
1601
1599
innerThunk->getActorIsolation ().getKind () ==
1602
1600
outerActorIsolation->getKind ()) &&
@@ -1635,7 +1633,8 @@ namespace {
1635
1633
1636
1634
Expr *buildStaticCurryThunk (Expr *base, Expr *declRefExpr,
1637
1635
AbstractFunctionDecl *member,
1638
- FunctionType *adjustedOpenedType,
1636
+ FunctionType *curryThunkTy,
1637
+ FunctionType *curryRefTy,
1639
1638
ConstraintLocatorBuilder locator,
1640
1639
ConstraintLocatorBuilder memberLocator,
1641
1640
bool openedExistential) {
@@ -1650,7 +1649,7 @@ namespace {
1650
1649
// built is the curried reference.
1651
1650
return buildSingleCurryThunk (
1652
1651
base, declRefExpr, member,
1653
- adjustedOpenedType ,
1652
+ curryThunkTy, curryRefTy ,
1654
1653
memberLocator);
1655
1654
} else {
1656
1655
// Add a useless ".self" to avoid downstream diagnostics, in case
@@ -1682,7 +1681,7 @@ namespace {
1682
1681
1683
1682
auto *closure = buildSingleCurryThunk (
1684
1683
baseRef, declRefExpr, member,
1685
- adjustedOpenedType ,
1684
+ curryThunkTy, curryRefTy ,
1686
1685
memberLocator);
1687
1686
1688
1687
// Wrap the closure in a capture list.
@@ -1955,12 +1954,15 @@ namespace {
1955
1954
1956
1955
// If we opened up an existential when referencing this member, update
1957
1956
// the base accordingly.
1957
+ Type baseOpenedTy = baseTy;
1958
1958
bool openedExistential = false ;
1959
1959
1960
1960
auto knownOpened = solution.OpenedExistentialTypes .find (
1961
1961
getConstraintSystem ().getConstraintLocator (
1962
1962
memberLocator));
1963
1963
if (knownOpened != solution.OpenedExistentialTypes .end ()) {
1964
+ baseOpenedTy = knownOpened->second ;
1965
+
1964
1966
// Determine if we're going to have an OpenExistentialExpr around
1965
1967
// this member reference.
1966
1968
//
@@ -1982,7 +1984,7 @@ namespace {
1982
1984
baseIsInstance && member->isInstanceMember ())) {
1983
1985
// Open the existential before performing the member reference.
1984
1986
base = openExistentialReference (base, knownOpened->second , member);
1985
- baseTy = knownOpened-> second ;
1987
+ baseTy = baseOpenedTy ;
1986
1988
selfTy = baseTy;
1987
1989
openedExistential = true ;
1988
1990
} else {
@@ -2064,7 +2066,7 @@ namespace {
2064
2066
// Now replace DynamicSelfType with the actual base type
2065
2067
// of the call.
2066
2068
auto replacementTy = getDynamicSelfReplacementType (
2067
- baseTy , member, memberLocator.getBaseLocator ());
2069
+ baseOpenedTy , member, memberLocator.getBaseLocator ());
2068
2070
refTy = simplifyType (
2069
2071
overload.openedFullType
2070
2072
->replaceDynamicSelfType (replacementTy));
@@ -2122,12 +2124,57 @@ namespace {
2122
2124
// very specific shape, we only emit a single closure here and
2123
2125
// capture the original SuperRefExpr, since its evaluation does not
2124
2126
// have side effects, instead of abstracting out a 'self' parameter.
2125
- const auto isSuperPartialApplication = needsCurryThunk && isSuper;
2126
- if (isSuperPartialApplication) {
2127
+ if (isUnboundInstanceMember) {
2128
+ if (needsCurryThunk) {
2129
+ // For an unbound reference to a method, all conversions, including
2130
+ // dynamic 'Self' handling, are done within the thunk to support
2131
+ // the edge case of an unbound reference to a 'Self'-returning class
2132
+ // method on a protocol metatype. The result of calling the method
2133
+ // must be downcast to the opened archetype before being erased to the
2134
+ // subclass existential to cope with the expectations placed
2135
+ // on 'CovariantReturnConversionExpr'.
2136
+ auto *curryThunkTy = adjustedOpenedType->castTo <FunctionType>();
2137
+ auto *curryRefTy = adjustedRefTy->castTo <FunctionType>();
2138
+
2139
+ // Replace the DeclRefExpr with a closure expression which SILGen
2140
+ // knows how to emit.
2141
+ ref = buildDoubleCurryThunk (declRefExpr, member,
2142
+ curryThunkTy, curryRefTy,
2143
+ memberLocator, memberLoc,
2144
+ isDynamic);
2145
+ }
2146
+
2147
+ ref = adjustTypeForDeclReference (
2148
+ ref, cs.getType (ref), adjustedOpenedType,
2149
+ locator);
2150
+
2151
+ // Reference to an unbound instance method.
2152
+ Expr *result = new (ctx) DotSyntaxBaseIgnoredExpr (base, dotLoc,
2153
+ ref,
2154
+ cs.getType (ref));
2155
+ cs.cacheType (result);
2156
+ closeExistentials (result, locator, /* force=*/ openedExistential);
2157
+ return forceUnwrapIfExpected (result, memberLocator);
2158
+
2159
+ } else if (needsCurryThunk && isSuper) {
2127
2160
ref = buildSingleCurryThunk (
2128
2161
base, declRefExpr, cast<AbstractFunctionDecl>(member),
2129
2162
adjustedOpenedType->castTo <FunctionType>(),
2163
+ adjustedRefTy->castTo <FunctionType>()
2164
+ ->getResult ()->castTo <FunctionType>(),
2130
2165
memberLocator);
2166
+
2167
+ // Handle DynamicSelfType.
2168
+ if (!adjustedRefTy->isEqual (adjustedRefTySelf)) {
2169
+ auto conversionTy = adjustedRefTy->castTo <FunctionType>()->getResult ();
2170
+ ref = cs.cacheType (new (ctx) CovariantFunctionConversionExpr (
2171
+ ref, conversionTy));
2172
+ }
2173
+
2174
+ // The thunk that is built for a 'super' method reference does not
2175
+ // require application.
2176
+ return forceUnwrapIfExpected (ref, memberLocator);
2177
+
2131
2178
} else if (needsCurryThunk) {
2132
2179
// Another case where we want to build a single closure is when
2133
2180
// we have a partial application of a static member. It is better
@@ -2140,37 +2187,31 @@ namespace {
2140
2187
return buildStaticCurryThunk (
2141
2188
base, declRefExpr, cast<AbstractFunctionDecl>(member),
2142
2189
adjustedOpenedType->castTo <FunctionType>(),
2190
+ adjustedRefTy->castTo <FunctionType>()
2191
+ ->getResult ()->castTo <FunctionType>(),
2143
2192
locator, memberLocator, openedExistential);
2144
2193
}
2145
2194
2146
- FunctionType *curryThunkTy = nullptr ;
2147
- if (isUnboundInstanceMember) {
2148
- // For an unbound reference to a method, all conversions, including
2149
- // dynamic 'Self' handling, are done within the thunk to support
2150
- // the edge case of an unbound reference to a 'Self'-returning class
2151
- // method on a protocol metatype. The result of calling the method
2152
- // must be downcast to the opened archetype before being erased to the
2153
- // subclass existential to cope with the expectations placed
2154
- // on 'CovariantReturnConversionExpr'.
2155
- curryThunkTy = adjustedOpenedType->castTo <FunctionType>();
2156
- } else {
2157
- curryThunkTy = adjustedRefTySelf->castTo <FunctionType>();
2158
-
2159
- // Check if we need to open an existential stored inside 'self'.
2160
- auto knownOpened = solution.OpenedExistentialTypes .find (
2161
- getConstraintSystem ().getConstraintLocator (memberLocator));
2162
- if (knownOpened != solution.OpenedExistentialTypes .end ()) {
2163
- curryThunkTy =
2164
- typeEraseOpenedArchetypesFromEnvironment (
2165
- curryThunkTy, knownOpened->second ->getGenericEnvironment ())
2166
- ->castTo <FunctionType>();
2167
- }
2195
+ auto *curryThunkTy = adjustedRefTySelf->castTo <FunctionType>();
2196
+ auto *curryRefTy = curryThunkTy;
2197
+
2198
+ // Check if we need to open an existential stored inside 'self'.
2199
+ if (knownOpened != solution.OpenedExistentialTypes .end ()) {
2200
+ curryThunkTy =
2201
+ typeEraseOpenedArchetypesFromEnvironment (
2202
+ curryThunkTy, knownOpened->second ->getGenericEnvironment ())
2203
+ ->castTo <FunctionType>();
2168
2204
}
2169
2205
2170
2206
// Replace the DeclRefExpr with a closure expression which SILGen
2171
2207
// knows how to emit.
2172
- ref = buildDoubleCurryThunk (declRefExpr, member, curryThunkTy,
2173
- memberLocator, memberLoc, isDynamic);
2208
+ ref = buildDoubleCurryThunk (declRefExpr, member,
2209
+ curryThunkTy, curryRefTy,
2210
+ memberLocator, memberLoc,
2211
+ isDynamic);
2212
+
2213
+ // Fall through, but with 'ref' now an AutoClosureExpr instead of
2214
+ // a DeclRefExpr.
2174
2215
}
2175
2216
2176
2217
// If the member is a method with a dynamic 'Self' result type, wrap an
@@ -2179,57 +2220,18 @@ namespace {
2179
2220
// replacement type -- usually the base object type.
2180
2221
//
2181
2222
// Note: For unbound references this is handled inside the thunk.
2182
- if (!isUnboundInstanceMember &&
2183
- member->getDeclContext ()->getSelfClassDecl ()) {
2184
- if (overload.adjustedOpenedFullType ->hasDynamicSelfType ()) {
2185
-
2186
- // Now, replace DynamicSelfType with the actual base type of
2187
- // the call.
2188
- //
2189
- // We look at the original opened type with unsimplified type
2190
- // variables, because we only want to replace DynamicSelfType
2191
- // that appears in the original type of the member, and not
2192
- // one introduced by substitution.
2193
- auto replacementTy = getDynamicSelfReplacementType (
2194
- baseTy, member, memberLocator.getBaseLocator ());
2195
- auto conversionTy = simplifyType (
2196
- overload.adjustedOpenedFullType
2197
- ->replaceDynamicSelfType (replacementTy));
2198
- if (!conversionTy->isEqual (adjustedRefTySelf)) {
2199
- if (isSuperPartialApplication) {
2200
- conversionTy =
2201
- conversionTy->castTo <FunctionType>()->getResult ();
2202
- }
2203
-
2204
- ref = cs.cacheType (new (ctx) CovariantFunctionConversionExpr (
2205
- ref, conversionTy));
2206
- }
2223
+ if (member->getDeclContext ()->getSelfClassDecl ()) {
2224
+ if (!adjustedRefTy->isEqual (adjustedRefTySelf)) {
2225
+ ref = cs.cacheType (new (ctx) CovariantFunctionConversionExpr (
2226
+ ref, adjustedRefTy));
2207
2227
}
2208
2228
}
2209
2229
2210
- // The thunk that is built for a 'super' method reference does not
2211
- // require application.
2212
- if (isSuperPartialApplication) {
2213
- return forceUnwrapIfExpected (ref, memberLocator);
2214
- }
2215
-
2216
2230
ApplyExpr *apply;
2217
2231
if (isa<ConstructorDecl>(member)) {
2218
2232
// FIXME: Provide type annotation.
2219
2233
ref = forceUnwrapIfExpected (ref, memberLocator);
2220
2234
apply = ConstructorRefCallExpr::create (ctx, ref, base);
2221
- } else if (isUnboundInstanceMember) {
2222
- ref = adjustTypeForDeclReference (
2223
- ref, cs.getType (ref), adjustedOpenedType,
2224
- locator);
2225
-
2226
- // Reference to an unbound instance method.
2227
- Expr *result = new (ctx) DotSyntaxBaseIgnoredExpr (base, dotLoc,
2228
- ref,
2229
- cs.getType (ref));
2230
- cs.cacheType (result);
2231
- closeExistentials (result, locator, /* force=*/ openedExistential);
2232
- return forceUnwrapIfExpected (result, memberLocator);
2233
2235
} else {
2234
2236
assert ((!baseIsInstance || member->isInstanceMember ()) &&
2235
2237
" can't call a static method on an instance" );
@@ -9143,7 +9145,7 @@ namespace {
9143
9145
if (AnyFunctionRef (closure).hasExternalPropertyWrapperParameters ()) {
9144
9146
auto *thunkTy = Rewriter.cs .getType (closure)->castTo <FunctionType>();
9145
9147
return Action::SkipNode (Rewriter.buildSingleCurryThunk (
9146
- closure, closure, thunkTy,
9148
+ closure, closure, thunkTy, thunkTy,
9147
9149
Rewriter.cs .getConstraintLocator (closure)));
9148
9150
}
9149
9151
0 commit comments