Skip to content

Commit 0063c3c

Browse files
authored
Merge pull request #84131 from slavapestov/remove-covariant-result-type-post-cleanup
Sema: Clean up getTypeOfMemberReference() and buildMemberRef()
2 parents ecd2b8a + 60246a2 commit 0063c3c

File tree

12 files changed

+422
-305
lines changed

12 files changed

+422
-305
lines changed

include/swift/AST/Types.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1343,6 +1343,10 @@ class alignas(1 << TypeAlignInBits) TypeBase
13431343
/// argument labels removed.
13441344
Type removeArgumentLabels(unsigned numArgumentLabels);
13451345

1346+
/// Replace DynamicSelfType anywhere it appears in covariant position with
1347+
/// its underlying Self type.
1348+
Type eraseDynamicSelfType();
1349+
13461350
/// Replace DynamicSelfType anywhere it appears in covariant position with
13471351
/// the given type.
13481352
Type replaceDynamicSelfType(Type newSelfType);

include/swift/Sema/ConstraintSystem.h

Lines changed: 33 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4456,30 +4456,6 @@ class ConstraintSystem {
44564456
DeclContext *useDC,
44574457
PreparedOverloadBuilder *preparedOverload);
44584458

4459-
/// Return the type-of-reference of the given value.
4460-
///
4461-
/// \param baseType if non-null, return the type of a member reference to
4462-
/// this value when the base has the given type
4463-
///
4464-
/// \param UseDC The context of the access. Some variables have different
4465-
/// types depending on where they are used.
4466-
///
4467-
/// \param locator The locator anchored at this value reference, when
4468-
/// it is a member reference.
4469-
///
4470-
/// \param wantInterfaceType Whether we want the interface type, if available.
4471-
Type getUnopenedTypeOfReference(VarDecl *value, Type baseType,
4472-
DeclContext *UseDC,
4473-
ConstraintLocator *locator,
4474-
bool wantInterfaceType);
4475-
4476-
/// Given the opened type and a pile of information about a member reference,
4477-
/// determine the reference type of the member reference.
4478-
Type getMemberReferenceTypeFromOpenedType(
4479-
Type &openedType, Type baseObjTy, ValueDecl *value, DeclContext *outerDC,
4480-
ConstraintLocator *locator, bool hasAppliedSelf, bool isDynamicLookup,
4481-
ArrayRef<OpenedType> replacements);
4482-
44834459
/// Retrieve the type of a reference to the given value declaration,
44844460
/// as a member with a base of the given type.
44854461
///
@@ -4507,6 +4483,39 @@ class ConstraintSystem {
45074483
}
45084484

45094485
private:
4486+
DeclReferenceType getTypeOfMemberTypeReference(
4487+
Type baseObjTy, TypeDecl *typeDecl, ConstraintLocator *locator,
4488+
PreparedOverloadBuilder *preparedOverload);
4489+
4490+
/// Return the type-of-reference of the given value.
4491+
///
4492+
/// \param baseType if non-null, return the type of a member reference to
4493+
/// this value when the base has the given type
4494+
///
4495+
/// \param UseDC The context of the access. Some variables have different
4496+
/// types depending on where they are used.
4497+
///
4498+
/// \param locator The locator anchored at this value reference, when
4499+
/// it is a member reference.
4500+
///
4501+
/// \param wantInterfaceType Whether we want the interface type, if available.
4502+
Type getUnopenedTypeOfReference(VarDecl *value, Type baseType,
4503+
DeclContext *UseDC,
4504+
ConstraintLocator *locator,
4505+
bool wantInterfaceType);
4506+
4507+
std::pair<Type, Type> getOpenedStorageType(
4508+
Type baseTy, AbstractStorageDecl *value, DeclContext *useDC,
4509+
bool hasAppliedSelf, ArrayRef<OpenedType> replacements,
4510+
ConstraintLocator *locator, PreparedOverloadBuilder *preparedOverload);
4511+
4512+
/// Given the opened type and a pile of information about a member reference,
4513+
/// determine the reference type of the member reference.
4514+
Type getMemberReferenceTypeFromOpenedType(
4515+
Type type, Type baseObjTy, ValueDecl *value,
4516+
ConstraintLocator *locator, bool hasAppliedSelf, bool isDynamicLookup,
4517+
ArrayRef<OpenedType> replacements);
4518+
45104519
/// Add the constraints needed to bind an overload's type variable.
45114520
void bindOverloadType(const SelectedOverload &overload, Type boundType,
45124521
ConstraintLocator *locator, DeclContext *useDC);

lib/AST/Type.cpp

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1342,19 +1342,34 @@ Type TypeBase::removeArgumentLabels(unsigned numArgumentLabels) {
13421342
return FunctionType::get(unlabeledParams, result, fnType->getExtInfo());
13431343
}
13441344

1345+
Type TypeBase::eraseDynamicSelfType() {
1346+
if (!hasDynamicSelfType())
1347+
return Type(this);
1348+
1349+
return Type(this).transformWithPosition(
1350+
TypePosition::Covariant,
1351+
[&](TypeBase *t, TypePosition pos) -> std::optional<Type> {
1352+
if (isa<DynamicSelfType>(t) &&
1353+
pos == TypePosition::Covariant) {
1354+
return cast<DynamicSelfType>(t)->getSelfType();
1355+
}
1356+
return std::nullopt;
1357+
});
1358+
}
1359+
13451360
Type TypeBase::replaceDynamicSelfType(Type newSelfType) {
13461361
if (!hasDynamicSelfType())
13471362
return Type(this);
13481363

13491364
return Type(this).transformWithPosition(
13501365
TypePosition::Covariant,
13511366
[&](TypeBase *t, TypePosition pos) -> std::optional<Type> {
1352-
if (isa<DynamicSelfType>(t) &&
1353-
pos == TypePosition::Covariant) {
1354-
return newSelfType;
1355-
}
1356-
return std::nullopt;
1357-
});
1367+
if (isa<DynamicSelfType>(t) &&
1368+
pos == TypePosition::Covariant) {
1369+
return newSelfType;
1370+
}
1371+
return std::nullopt;
1372+
});
13581373
}
13591374

13601375
Type TypeBase::withCovariantResultType() {

lib/ConstExtract/ConstExtract.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -312,7 +312,7 @@ extractCompileTimeValue(Expr *expr, const DeclContext *declContext) {
312312
return std::make_shared<FunctionCallValue>(identifier, parameters);
313313
}
314314

315-
if (auto constructorRefCall = dyn_cast<ConstructorRefCallExpr>(callExpr->getFn())) {
315+
if (isa<ConstructorRefCallExpr>(callExpr->getFn())) {
316316
std::vector<FunctionParameter> parameters =
317317
extractFunctionArguments(callExpr->getArgs(), declContext);
318318
return std::make_shared<InitCallValue>(callExpr->getType(), parameters);

lib/Sema/CSApply.cpp

Lines changed: 86 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -1743,14 +1743,16 @@ namespace {
17431743
return forceUnwrapIfExpected(ref, memberLocator);
17441744
}
17451745

1746+
/// FIXME: Simplify this horrible parameter list.
17461747
Expr *buildVarMemberRef(Expr *base, SourceLoc dotLoc,
17471748
bool baseIsInstance,
17481749
ConcreteDeclRef memberRef,
17491750
DeclNameLoc memberLoc,
17501751
Type containerTy,
17511752
Type refTy,
1753+
Type refTySelf,
17521754
Type adjustedRefTy,
1753-
Type adjustedOpenedType,
1755+
Type adjustedRefTySelf,
17541756
AccessSemantics semantics,
17551757
ConstraintLocatorBuilder locator,
17561758
ConstraintLocatorBuilder memberLocator,
@@ -1789,37 +1791,28 @@ namespace {
17891791
base->setImplicit();
17901792
}
17911793

1792-
const auto hasDynamicSelf = refTy->hasDynamicSelfType();
1793-
17941794
auto memberRefExpr
17951795
= new (ctx) MemberRefExpr(base, dotLoc, memberRef,
17961796
memberLoc, Implicit, semantics);
17971797
memberRefExpr->setIsSuper(isSuper);
17981798

1799-
if (hasDynamicSelf) {
1800-
refTy = refTy->replaceDynamicSelfType(containerTy);
1801-
adjustedRefTy = adjustedRefTy->replaceDynamicSelfType(
1802-
containerTy);
1803-
}
1804-
1805-
cs.setType(memberRefExpr, resultType(refTy));
1799+
auto resultTySelf = resultType(refTySelf);
1800+
cs.setType(memberRefExpr, resultTySelf);
18061801

18071802
Expr *result = memberRefExpr;
1808-
result = adjustTypeForDeclReference(result, resultType(refTy),
1809-
resultType(adjustedRefTy),
1803+
result = adjustTypeForDeclReference(result, resultTySelf,
1804+
resultType(adjustedRefTySelf),
18101805
locator);
18111806
closeExistentials(result, locator);
18121807

18131808
// If the property is of dynamic 'Self' type, wrap an implicit
18141809
// conversion around the resulting expression, with the destination
18151810
// type having 'Self' swapped for the appropriate replacement
18161811
// type -- usually the base object type.
1817-
if (hasDynamicSelf) {
1818-
const auto conversionTy = adjustedOpenedType;
1819-
if (!containerTy->isEqual(conversionTy)) {
1820-
result = cs.cacheType(new (ctx) CovariantReturnConversionExpr(
1821-
result, conversionTy));
1822-
}
1812+
auto resultTy = resultType(refTy);
1813+
if (!resultTy->isEqual(resultTySelf)) {
1814+
result = cs.cacheType(new (ctx) CovariantReturnConversionExpr(
1815+
result, resultTy));
18231816
}
18241817

18251818
// If we need to load, do so now.
@@ -1943,7 +1936,8 @@ namespace {
19431936
Expr *ref = cs.cacheType(new (ctx) DotSyntaxBaseIgnoredExpr(
19441937
base, dotLoc, dre, refTy));
19451938

1946-
ref = adjustTypeForDeclReference(ref, refTy, adjustedRefTy, locator);
1939+
ref = adjustTypeForDeclReference(ref, refTy, adjustedRefTy,
1940+
locator);
19471941
return forceUnwrapIfExpected(ref, memberLocator);
19481942
}
19491943

@@ -2051,6 +2045,34 @@ namespace {
20512045
}
20522046
assert(base && "Unable to convert base?");
20532047

2048+
// This is the type of the DeclRefExpr, where DynamicSelfType has
2049+
// been replaced with the static Self type of the member, ie the
2050+
// base class it is declared in.
2051+
Type refTySelf = refTy, adjustedRefTySelf = adjustedRefTy;
2052+
2053+
// Now, deal with DynamicSelfType.
2054+
if (overload.openedFullType->hasDynamicSelfType()) {
2055+
// We look at the original opened type with unsimplified type
2056+
// variables, because we only want to erase DynamicSelfType
2057+
// that appears in the original type of the member, and not
2058+
// one introduced by substitution.
2059+
refTySelf = simplifyType(
2060+
overload.openedFullType->eraseDynamicSelfType());
2061+
adjustedRefTySelf = simplifyType(
2062+
overload.adjustedOpenedFullType->eraseDynamicSelfType());
2063+
2064+
// Now replace DynamicSelfType with the actual base type
2065+
// of the call.
2066+
auto replacementTy = getDynamicSelfReplacementType(
2067+
baseTy, member, memberLocator.getBaseLocator());
2068+
refTy = simplifyType(
2069+
overload.openedFullType
2070+
->replaceDynamicSelfType(replacementTy));
2071+
adjustedRefTy = simplifyType(
2072+
overload.adjustedOpenedFullType
2073+
->replaceDynamicSelfType(replacementTy));
2074+
}
2075+
20542076
// Handle dynamic references.
20552077
if (!needsCurryThunk &&
20562078
(isDynamic || member->getAttrs().hasAttribute<OptionalAttr>())) {
@@ -2064,24 +2086,14 @@ namespace {
20642086
if (isa<VarDecl>(member)) {
20652087
return buildVarMemberRef(base, dotLoc, baseIsInstance,
20662088
memberRef, memberLoc, containerTy,
2067-
refTy, adjustedRefTy, adjustedOpenedType,
2089+
refTy, refTySelf, adjustedRefTy, adjustedRefTySelf,
20682090
semantics, locator, memberLocator,
20692091
isSuper, isUnboundInstanceMember, Implicit);
20702092
}
20712093

20722094
ASSERT(isa<AbstractFunctionDecl>(member) ||
20732095
isa<EnumElementDecl>(member));
20742096

2075-
Type refTySelf = refTy, adjustedRefTySelf = adjustedRefTy;
2076-
2077-
auto *func = dyn_cast<FuncDecl>(member);
2078-
if (func && func->getResultInterfaceType()->hasDynamicSelfType()) {
2079-
ASSERT(refTy->hasDynamicSelfType());
2080-
refTySelf = refTy->replaceDynamicSelfType(containerTy);
2081-
adjustedRefTySelf = adjustedRefTy->replaceDynamicSelfType(
2082-
containerTy);
2083-
}
2084-
20852097
// Handle all other references.
20862098
auto declRefExpr = new (ctx) DeclRefExpr(memberRef, memberLoc,
20872099
Implicit, semantics);
@@ -2169,30 +2181,28 @@ namespace {
21692181
// Note: For unbound references this is handled inside the thunk.
21702182
if (!isUnboundInstanceMember &&
21712183
member->getDeclContext()->getSelfClassDecl()) {
2172-
if (auto func = dyn_cast<AbstractFunctionDecl>(member)) {
2173-
if (func->hasDynamicSelfResult()) {
2174-
// FIXME: Once CovariantReturnConversionExpr (unchecked_ref_cast)
2175-
// supports a class existential dest., consider using the opened
2176-
// type directly to avoid recomputing the 'Self' replacement and
2177-
// substituting.
2178-
const Type replacementTy = getDynamicSelfReplacementType(
2179-
baseTy, member, memberLocator.getBaseLocator());
2180-
if (!replacementTy->isEqual(containerTy)) {
2181-
if (isa<ConstructorDecl>(member)) {
2182-
adjustedRefTy = adjustedRefTy->withCovariantResultType();
2183-
} else {
2184-
ASSERT(adjustedRefTy->hasDynamicSelfType());
2185-
}
2186-
Type conversionTy =
2187-
adjustedRefTy->replaceDynamicSelfType(replacementTy);
2188-
if (isSuperPartialApplication) {
2189-
conversionTy =
2190-
conversionTy->castTo<FunctionType>()->getResult();
2191-
}
2184+
if (overload.adjustedOpenedFullType->hasDynamicSelfType()) {
21922185

2193-
ref = cs.cacheType(new (ctx) CovariantFunctionConversionExpr(
2194-
ref, conversionTy));
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();
21952202
}
2203+
2204+
ref = cs.cacheType(new (ctx) CovariantFunctionConversionExpr(
2205+
ref, conversionTy));
21962206
}
21972207
}
21982208
}
@@ -2548,7 +2558,6 @@ namespace {
25482558
// Form the subscript expression.
25492559
auto subscriptExpr = SubscriptExpr::create(
25502560
ctx, base, args, subscriptRef, isImplicit, semantics);
2551-
cs.setType(subscriptExpr, fullSubscriptTy->getResult());
25522561
subscriptExpr->setIsSuper(isSuper);
25532562

25542563
if (!hasDynamicSelf) {
@@ -2587,30 +2596,36 @@ namespace {
25872596
bool implicit) {
25882597
// The constructor was opened with the allocating type, not the
25892598
// initializer type. Map the former into the latter.
2590-
auto *resultTy =
2591-
solution.simplifyType(openedFullType)->castTo<FunctionType>();
2592-
2593-
const auto selfTy = getBaseType(resultTy);
2594-
2595-
ParameterTypeFlags flags;
2596-
if (!selfTy->hasReferenceSemantics())
2597-
flags = flags.withInOut(true);
2599+
auto getOpenedInitializerType = [&](Type ty) -> FunctionType * {
2600+
auto *resultTy = solution.simplifyType(ty)->castTo<FunctionType>();
2601+
auto selfTy = getBaseType(resultTy);
2602+
2603+
ParameterTypeFlags flags;
2604+
if (!selfTy->hasReferenceSemantics())
2605+
flags = flags.withInOut(true);
2606+
2607+
auto selfParam = AnyFunctionType::Param(selfTy, Identifier(), flags);
2608+
return FunctionType::get({selfParam},
2609+
resultTy->getResult(),
2610+
resultTy->getExtInfo());
2611+
};
25982612

2599-
auto selfParam = AnyFunctionType::Param(selfTy, Identifier(), flags);
2600-
resultTy = FunctionType::get({selfParam}, resultTy->getResult(),
2601-
resultTy->getExtInfo());
2613+
auto *resultTySelf = getOpenedInitializerType(
2614+
openedFullType->eraseDynamicSelfType());
26022615

26032616
// Build the constructor reference.
26042617
Expr *ctorRef = cs.cacheType(
2605-
new (ctx) OtherConstructorDeclRefExpr(ref, loc, implicit, resultTy));
2618+
new (ctx) OtherConstructorDeclRefExpr(ref, loc, implicit, resultTySelf));
2619+
2620+
auto *resultTy = getOpenedInitializerType(
2621+
openedFullType->replaceDynamicSelfType(
2622+
cs.getType(base)->getWithoutSpecifierType()));
26062623

26072624
// Wrap in covariant `Self` return if needed.
2608-
if (ref.getDecl()->getDeclContext()->getSelfClassDecl()) {
2609-
auto covariantTy = resultTy->withCovariantResultType()
2610-
->replaceDynamicSelfType(cs.getType(base)->getWithoutSpecifierType());
2611-
if (!covariantTy->isEqual(resultTy))
2612-
ctorRef = cs.cacheType(
2613-
new (ctx) CovariantFunctionConversionExpr(ctorRef, covariantTy));
2625+
if (!resultTy->isEqual(resultTySelf)) {
2626+
ASSERT(ref.getDecl()->getDeclContext()->getSelfClassDecl());
2627+
ctorRef = cs.cacheType(
2628+
new (ctx) CovariantFunctionConversionExpr(ctorRef, resultTy));
26142629
}
26152630

26162631
return ctorRef;

0 commit comments

Comments
 (0)