@@ -2124,14 +2124,57 @@ namespace {
2124
2124
// very specific shape, we only emit a single closure here and
2125
2125
// capture the original SuperRefExpr, since its evaluation does not
2126
2126
// have side effects, instead of abstracting out a 'self' parameter.
2127
- const auto isSuperPartialApplication = needsCurryThunk && isSuper;
2128
- 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) {
2129
2160
ref = buildSingleCurryThunk (
2130
2161
base, declRefExpr, cast<AbstractFunctionDecl>(member),
2131
2162
adjustedOpenedType->castTo <FunctionType>(),
2132
2163
adjustedRefTy->castTo <FunctionType>()
2133
2164
->getResult ()->castTo <FunctionType>(),
2134
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
+
2135
2178
} else if (needsCurryThunk) {
2136
2179
// Another case where we want to build a single closure is when
2137
2180
// we have a partial application of a static member. It is better
@@ -2149,30 +2192,15 @@ namespace {
2149
2192
locator, memberLocator, openedExistential);
2150
2193
}
2151
2194
2152
- FunctionType *curryThunkTy = nullptr ;
2153
- FunctionType *curryRefTy = nullptr ;
2195
+ auto *curryThunkTy = adjustedRefTySelf-> castTo <FunctionType>() ;
2196
+ auto *curryRefTy = curryThunkTy ;
2154
2197
2155
- if (isUnboundInstanceMember) {
2156
- // For an unbound reference to a method, all conversions, including
2157
- // dynamic 'Self' handling, are done within the thunk to support
2158
- // the edge case of an unbound reference to a 'Self'-returning class
2159
- // method on a protocol metatype. The result of calling the method
2160
- // must be downcast to the opened archetype before being erased to the
2161
- // subclass existential to cope with the expectations placed
2162
- // on 'CovariantReturnConversionExpr'.
2163
- curryThunkTy = adjustedOpenedType->castTo <FunctionType>();
2164
- curryRefTy = adjustedRefTy->castTo <FunctionType>();
2165
- } else {
2166
- curryThunkTy = adjustedRefTySelf->castTo <FunctionType>();
2167
- curryRefTy = curryThunkTy;
2168
-
2169
- // Check if we need to open an existential stored inside 'self'.
2170
- if (knownOpened != solution.OpenedExistentialTypes .end ()) {
2171
- curryThunkTy =
2172
- typeEraseOpenedArchetypesFromEnvironment (
2173
- curryThunkTy, knownOpened->second ->getGenericEnvironment ())
2174
- ->castTo <FunctionType>();
2175
- }
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>();
2176
2204
}
2177
2205
2178
2206
// Replace the DeclRefExpr with a closure expression which SILGen
@@ -2181,6 +2209,9 @@ namespace {
2181
2209
curryThunkTy, curryRefTy,
2182
2210
memberLocator, memberLoc,
2183
2211
isDynamic);
2212
+
2213
+ // Fall through, but with 'ref' now an AutoClosureExpr instead of
2214
+ // a DeclRefExpr.
2184
2215
}
2185
2216
2186
2217
// If the member is a method with a dynamic 'Self' result type, wrap an
@@ -2189,45 +2220,18 @@ namespace {
2189
2220
// replacement type -- usually the base object type.
2190
2221
//
2191
2222
// Note: For unbound references this is handled inside the thunk.
2192
- if (!isUnboundInstanceMember &&
2193
- member->getDeclContext ()->getSelfClassDecl ()) {
2194
- if (overload.adjustedOpenedFullType ->hasDynamicSelfType ()) {
2195
- if (!adjustedRefTy->isEqual (adjustedRefTySelf)) {
2196
- Type conversionTy = adjustedRefTy;
2197
- if (isSuperPartialApplication) {
2198
- conversionTy =
2199
- conversionTy->castTo <FunctionType>()->getResult ();
2200
- }
2201
-
2202
- ref = cs.cacheType (new (ctx) CovariantFunctionConversionExpr (
2203
- ref, conversionTy));
2204
- }
2223
+ if (member->getDeclContext ()->getSelfClassDecl ()) {
2224
+ if (!adjustedRefTy->isEqual (adjustedRefTySelf)) {
2225
+ ref = cs.cacheType (new (ctx) CovariantFunctionConversionExpr (
2226
+ ref, adjustedRefTy));
2205
2227
}
2206
2228
}
2207
2229
2208
- // The thunk that is built for a 'super' method reference does not
2209
- // require application.
2210
- if (isSuperPartialApplication) {
2211
- return forceUnwrapIfExpected (ref, memberLocator);
2212
- }
2213
-
2214
2230
ApplyExpr *apply;
2215
2231
if (isa<ConstructorDecl>(member)) {
2216
2232
// FIXME: Provide type annotation.
2217
2233
ref = forceUnwrapIfExpected (ref, memberLocator);
2218
2234
apply = ConstructorRefCallExpr::create (ctx, ref, base);
2219
- } else if (isUnboundInstanceMember) {
2220
- ref = adjustTypeForDeclReference (
2221
- ref, cs.getType (ref), adjustedOpenedType,
2222
- locator);
2223
-
2224
- // Reference to an unbound instance method.
2225
- Expr *result = new (ctx) DotSyntaxBaseIgnoredExpr (base, dotLoc,
2226
- ref,
2227
- cs.getType (ref));
2228
- cs.cacheType (result);
2229
- closeExistentials (result, locator, /* force=*/ openedExistential);
2230
- return forceUnwrapIfExpected (result, memberLocator);
2231
2235
} else {
2232
2236
assert ((!baseIsInstance || member->isInstanceMember ()) &&
2233
2237
" can't call a static method on an instance" );
0 commit comments