Skip to content

Commit 79035e9

Browse files
authored
Merge pull request #84210 from slavapestov/remove-has-dynamic-self-result
AST: Remove AbstractFunctionDecl::hasDynamicSelfResult()
2 parents 3ee222f + 507f761 commit 79035e9

File tree

3 files changed

+97
-105
lines changed

3 files changed

+97
-105
lines changed

include/swift/AST/Decl.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8321,10 +8321,6 @@ class AbstractFunctionDecl : public GenericContext, public ValueDecl {
83218321
/// Asserts if not in type context.
83228322
Type getMethodInterfaceType() const;
83238323

8324-
/// Tests if this is a function returning a DynamicSelfType, or a
8325-
/// constructor.
8326-
bool hasDynamicSelfResult() const;
8327-
83288324
/// The async function marked as the alternative to this function, if any.
83298325
AbstractFunctionDecl *getAsyncAlternative() const;
83308326

lib/AST/Decl.cpp

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9925,12 +9925,6 @@ Type AbstractFunctionDecl::getMethodInterfaceType() const {
99259925
return Ty->castTo<AnyFunctionType>()->getResult();
99269926
}
99279927

9928-
bool AbstractFunctionDecl::hasDynamicSelfResult() const {
9929-
if (auto *funcDecl = dyn_cast<FuncDecl>(this))
9930-
return funcDecl->getResultInterfaceType()->hasDynamicSelfType();
9931-
return isa<ConstructorDecl>(this);
9932-
}
9933-
99349928
AbstractFunctionDecl *AbstractFunctionDecl::getAsyncAlternative() const {
99359929
// Async functions can't have async alternatives
99369930
if (hasAsync())

lib/Sema/CSApply.cpp

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

Comments
 (0)