@@ -783,6 +783,7 @@ namespace {
783783 // We don't need to do any further adjustment once we've built the
784784 // curry thunk.
785785 return buildSingleCurryThunk (result, fnDecl,
786+ adjustedFullType->castTo <FunctionType>(),
786787 adjustedFullType->castTo <FunctionType>(),
787788 locator);
788789 }
@@ -1342,6 +1343,7 @@ namespace {
13421343 AutoClosureExpr *buildSingleCurryThunk (Expr *baseExpr, Expr *fnExpr,
13431344 DeclContext *declOrClosure,
13441345 FunctionType *thunkTy,
1346+ FunctionType *refTy,
13451347 ConstraintLocatorBuilder locator) {
13461348 const OptionSet<ParameterList::CloneFlags> options =
13471349 (ParameterList::Implicit | ParameterList::NamedArguments);
@@ -1404,24 +1406,10 @@ namespace {
14041406 if (baseExpr) {
14051407 if (auto *fnDecl = dyn_cast<AbstractFunctionDecl>(declOrClosure)) {
14061408 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));
14251413 }
14261414 }
14271415 }
@@ -1460,15 +1448,19 @@ namespace {
14601448 // / \param thunkTy The type of the resulting thunk. This should be the
14611449 // / type of the \c fnExpr, with any potential adjustments for things like
14621450 // / 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.
14631454 // / \param locator The locator pinned on the function reference carried
14641455 // / by \p fnExpr. If the function has associated applied property wrappers,
14651456 // / the locator is used to pull them in.
14661457 AutoClosureExpr *buildSingleCurryThunk (Expr *fnExpr,
14671458 DeclContext *declOrClosure,
14681459 FunctionType *thunkTy,
1460+ FunctionType *refTy,
14691461 ConstraintLocatorBuilder locator) {
14701462 return buildSingleCurryThunk (/* baseExpr=*/ nullptr , fnExpr, declOrClosure,
1471- thunkTy, locator);
1463+ thunkTy, refTy, locator);
14721464 }
14731465
14741466 // / Build a "{ self in { args in self.fn(args) } }" nested curry thunk.
@@ -1478,12 +1470,16 @@ namespace {
14781470 // / the parameters of the inner thunk.
14791471 // / \param member The underlying function declaration to be called.
14801472 // / \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.
14811476 // / \param memberLocator The locator pinned on the member reference. If the
14821477 // / function has associated applied property wrappers, the locator is used
14831478 // / to pull them in.
14841479 AutoClosureExpr *
14851480 buildDoubleCurryThunk (DeclRefExpr *memberRef, ValueDecl *member,
14861481 FunctionType *outerThunkTy,
1482+ FunctionType *outerRefTy,
14871483 ConstraintLocatorBuilder memberLocator,
14881484 DeclNameLoc memberLoc, bool isDynamicLookup) {
14891485 const auto selfThunkParam = outerThunkTy->getParams ().front ();
@@ -1596,7 +1592,9 @@ namespace {
15961592 } else {
15971593 auto *innerThunk = buildSingleCurryThunk (
15981594 selfOpenedRef, memberRef, cast<DeclContext>(member),
1599- outerThunkTy->getResult ()->castTo <FunctionType>(), memberLocator);
1595+ outerThunkTy->getResult ()->castTo <FunctionType>(),
1596+ outerRefTy->getResult ()->castTo <FunctionType>(),
1597+ memberLocator);
16001598 assert ((!outerActorIsolation ||
16011599 innerThunk->getActorIsolation ().getKind () ==
16021600 outerActorIsolation->getKind ()) &&
@@ -1635,7 +1633,8 @@ namespace {
16351633
16361634 Expr *buildStaticCurryThunk (Expr *base, Expr *declRefExpr,
16371635 AbstractFunctionDecl *member,
1638- FunctionType *adjustedOpenedType,
1636+ FunctionType *curryThunkTy,
1637+ FunctionType *curryRefTy,
16391638 ConstraintLocatorBuilder locator,
16401639 ConstraintLocatorBuilder memberLocator,
16411640 bool openedExistential) {
@@ -1650,7 +1649,7 @@ namespace {
16501649 // built is the curried reference.
16511650 return buildSingleCurryThunk (
16521651 base, declRefExpr, member,
1653- adjustedOpenedType ,
1652+ curryThunkTy, curryRefTy ,
16541653 memberLocator);
16551654 } else {
16561655 // Add a useless ".self" to avoid downstream diagnostics, in case
@@ -1682,7 +1681,7 @@ namespace {
16821681
16831682 auto *closure = buildSingleCurryThunk (
16841683 baseRef, declRefExpr, member,
1685- adjustedOpenedType ,
1684+ curryThunkTy, curryRefTy ,
16861685 memberLocator);
16871686
16881687 // Wrap the closure in a capture list.
@@ -1955,12 +1954,15 @@ namespace {
19551954
19561955 // If we opened up an existential when referencing this member, update
19571956 // the base accordingly.
1957+ Type baseOpenedTy = baseTy;
19581958 bool openedExistential = false ;
19591959
19601960 auto knownOpened = solution.OpenedExistentialTypes .find (
19611961 getConstraintSystem ().getConstraintLocator (
19621962 memberLocator));
19631963 if (knownOpened != solution.OpenedExistentialTypes .end ()) {
1964+ baseOpenedTy = knownOpened->second ;
1965+
19641966 // Determine if we're going to have an OpenExistentialExpr around
19651967 // this member reference.
19661968 //
@@ -1982,7 +1984,7 @@ namespace {
19821984 baseIsInstance && member->isInstanceMember ())) {
19831985 // Open the existential before performing the member reference.
19841986 base = openExistentialReference (base, knownOpened->second , member);
1985- baseTy = knownOpened-> second ;
1987+ baseTy = baseOpenedTy ;
19861988 selfTy = baseTy;
19871989 openedExistential = true ;
19881990 } else {
@@ -2064,7 +2066,7 @@ namespace {
20642066 // Now replace DynamicSelfType with the actual base type
20652067 // of the call.
20662068 auto replacementTy = getDynamicSelfReplacementType (
2067- baseTy , member, memberLocator.getBaseLocator ());
2069+ baseOpenedTy , member, memberLocator.getBaseLocator ());
20682070 refTy = simplifyType (
20692071 overload.openedFullType
20702072 ->replaceDynamicSelfType (replacementTy));
@@ -2122,12 +2124,57 @@ namespace {
21222124 // very specific shape, we only emit a single closure here and
21232125 // capture the original SuperRefExpr, since its evaluation does not
21242126 // 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) {
21272160 ref = buildSingleCurryThunk (
21282161 base, declRefExpr, cast<AbstractFunctionDecl>(member),
21292162 adjustedOpenedType->castTo <FunctionType>(),
2163+ adjustedRefTy->castTo <FunctionType>()
2164+ ->getResult ()->castTo <FunctionType>(),
21302165 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+
21312178 } else if (needsCurryThunk) {
21322179 // Another case where we want to build a single closure is when
21332180 // we have a partial application of a static member. It is better
@@ -2140,37 +2187,31 @@ namespace {
21402187 return buildStaticCurryThunk (
21412188 base, declRefExpr, cast<AbstractFunctionDecl>(member),
21422189 adjustedOpenedType->castTo <FunctionType>(),
2190+ adjustedRefTy->castTo <FunctionType>()
2191+ ->getResult ()->castTo <FunctionType>(),
21432192 locator, memberLocator, openedExistential);
21442193 }
21452194
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>();
21682204 }
21692205
21702206 // Replace the DeclRefExpr with a closure expression which SILGen
21712207 // 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.
21742215 }
21752216
21762217 // If the member is a method with a dynamic 'Self' result type, wrap an
@@ -2179,57 +2220,18 @@ namespace {
21792220 // replacement type -- usually the base object type.
21802221 //
21812222 // 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));
22072227 }
22082228 }
22092229
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-
22162230 ApplyExpr *apply;
22172231 if (isa<ConstructorDecl>(member)) {
22182232 // FIXME: Provide type annotation.
22192233 ref = forceUnwrapIfExpected (ref, memberLocator);
22202234 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);
22332235 } else {
22342236 assert ((!baseIsInstance || member->isInstanceMember ()) &&
22352237 " can't call a static method on an instance" );
@@ -9143,7 +9145,7 @@ namespace {
91439145 if (AnyFunctionRef (closure).hasExternalPropertyWrapperParameters ()) {
91449146 auto *thunkTy = Rewriter.cs .getType (closure)->castTo <FunctionType>();
91459147 return Action::SkipNode (Rewriter.buildSingleCurryThunk (
9146- closure, closure, thunkTy,
9148+ closure, closure, thunkTy, thunkTy,
91479149 Rewriter.cs .getConstraintLocator (closure)));
91489150 }
91499151
0 commit comments