@@ -2124,14 +2124,57 @@ namespace {
21242124 // very specific shape, we only emit a single closure here and
21252125 // capture the original SuperRefExpr, since its evaluation does not
21262126 // 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) {
21292160 ref = buildSingleCurryThunk (
21302161 base, declRefExpr, cast<AbstractFunctionDecl>(member),
21312162 adjustedOpenedType->castTo <FunctionType>(),
21322163 adjustedRefTy->castTo <FunctionType>()
21332164 ->getResult ()->castTo <FunctionType>(),
21342165 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+
21352178 } else if (needsCurryThunk) {
21362179 // Another case where we want to build a single closure is when
21372180 // we have a partial application of a static member. It is better
@@ -2149,30 +2192,15 @@ namespace {
21492192 locator, memberLocator, openedExistential);
21502193 }
21512194
2152- FunctionType *curryThunkTy = nullptr ;
2153- FunctionType *curryRefTy = nullptr ;
2195+ auto *curryThunkTy = adjustedRefTySelf-> castTo <FunctionType>() ;
2196+ auto *curryRefTy = curryThunkTy ;
21542197
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>();
21762204 }
21772205
21782206 // Replace the DeclRefExpr with a closure expression which SILGen
@@ -2181,6 +2209,9 @@ namespace {
21812209 curryThunkTy, curryRefTy,
21822210 memberLocator, memberLoc,
21832211 isDynamic);
2212+
2213+ // Fall through, but with 'ref' now an AutoClosureExpr instead of
2214+ // a DeclRefExpr.
21842215 }
21852216
21862217 // If the member is a method with a dynamic 'Self' result type, wrap an
@@ -2189,45 +2220,18 @@ namespace {
21892220 // replacement type -- usually the base object type.
21902221 //
21912222 // 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));
22052227 }
22062228 }
22072229
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-
22142230 ApplyExpr *apply;
22152231 if (isa<ConstructorDecl>(member)) {
22162232 // FIXME: Provide type annotation.
22172233 ref = forceUnwrapIfExpected (ref, memberLocator);
22182234 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);
22312235 } else {
22322236 assert ((!baseIsInstance || member->isInstanceMember ()) &&
22332237 " can't call a static method on an instance" );
0 commit comments