Skip to content

Commit d6fb460

Browse files
committed
Sema: Clean up curry thunk logic in buildMemberRef()
1 parent 59b7599 commit d6fb460

File tree

1 file changed

+60
-56
lines changed

1 file changed

+60
-56
lines changed

lib/Sema/CSApply.cpp

Lines changed: 60 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)