Skip to content

Commit a5a8cf4

Browse files
authored
Merge pull request #83858 from slavapestov/covariant-result-type-part-2
AST: Continue process of removing replaceCovariantResultType()
2 parents b11ccb6 + a7d12e7 commit a5a8cf4

17 files changed

+187
-122
lines changed

include/swift/AST/Types.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1344,6 +1344,9 @@ class alignas(1 << TypeAlignInBits) TypeBase
13441344
/// the given type.
13451345
Type replaceDynamicSelfType(Type newSelfType);
13461346

1347+
/// Hack to deal with ConstructorDecl interface types.
1348+
Type withCovariantResultType();
1349+
13471350
/// Deprecated in favor of the above.
13481351
Type replaceCovariantResultType(Type newResultType,
13491352
unsigned uncurryLevel);

lib/AST/ASTContext.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4076,7 +4076,7 @@ AnyFunctionType::Param swift::computeSelfParam(AbstractFunctionDecl *AFD,
40764076
// Methods returning 'Self' have a dynamic 'self'.
40774077
//
40784078
// FIXME: All methods of non-final classes should have this.
4079-
else if (wantDynamicSelf && FD->hasDynamicSelfResult())
4079+
else if (wantDynamicSelf && FD->getResultInterfaceType()->hasDynamicSelfType())
40804080
isDynamicSelf = true;
40814081

40824082
} else if (auto *CD = dyn_cast<ConstructorDecl>(AFD)) {

lib/AST/Type.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1357,6 +1357,42 @@ Type TypeBase::replaceDynamicSelfType(Type newSelfType) {
13571357
});
13581358
}
13591359

1360+
Type TypeBase::withCovariantResultType() {
1361+
// Unwrap the outer function type.
1362+
auto fnType = this->castTo<AnyFunctionType>();
1363+
ASSERT(fnType->getParams().size() == 1);
1364+
1365+
// Unwrap the inner function type.
1366+
auto resultFnType = fnType->getResult()->castTo<FunctionType>();
1367+
auto resultType = resultFnType->getResult();
1368+
1369+
bool wasOptional = false;
1370+
if (auto objectType = resultType->getOptionalObjectType()) {
1371+
wasOptional = true;
1372+
resultType = objectType;
1373+
}
1374+
1375+
ASSERT(resultType->getClassOrBoundGenericClass());
1376+
resultType = DynamicSelfType::get(resultType, getASTContext());
1377+
1378+
// Rebuild the inner function type.
1379+
if (wasOptional)
1380+
resultType = OptionalType::get(resultType);
1381+
1382+
resultFnType = FunctionType::get(resultFnType->getParams(), resultType,
1383+
resultFnType->getExtInfo());
1384+
1385+
// Rebuild the outer function type.
1386+
if (auto genericFn = dyn_cast<GenericFunctionType>(fnType)) {
1387+
return GenericFunctionType::get(genericFn->getGenericSignature(),
1388+
fnType->getParams(), resultFnType,
1389+
fnType->getExtInfo());
1390+
}
1391+
1392+
return FunctionType::get(fnType->getParams(), resultFnType,
1393+
fnType->getExtInfo());
1394+
}
1395+
13601396
Type TypeBase::replaceCovariantResultType(Type newResultType,
13611397
unsigned uncurryLevel) {
13621398
if (uncurryLevel == 0) {

lib/AST/TypeSubstitution.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -885,8 +885,9 @@ Type TypeBase::adjustSuperclassMemberDeclType(const ValueDecl *baseDecl,
885885

886886
if (auto *afd = dyn_cast<AbstractFunctionDecl>(baseDecl)) {
887887
type = type->replaceSelfParameterType(this);
888-
if (isa<ConstructorDecl>(afd))
889-
return type->replaceCovariantResultType(this, /*uncurryLevel=*/2);
888+
if (isa<ConstructorDecl>(afd) &&
889+
afd->getDeclContext()->getSelfClassDecl())
890+
type = type->withCovariantResultType();
890891
}
891892

892893
return type->replaceDynamicSelfType(this);

lib/PrintAsClang/DeclAndTypePrinter.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1250,7 +1250,8 @@ class DeclAndTypePrinter::Implementation
12501250
// Constructors and methods returning DynamicSelf return
12511251
// instancetype.
12521252
if (isa<ConstructorDecl>(AFD) ||
1253-
(isa<FuncDecl>(AFD) && cast<FuncDecl>(AFD)->hasDynamicSelfResult() &&
1253+
(isa<FuncDecl>(AFD) &&
1254+
cast<FuncDecl>(AFD)->getResultInterfaceType()->hasDynamicSelfType() &&
12541255
!AFD->hasAsync())) {
12551256
if (errorConvention && errorConvention->stripsResultOptionality()) {
12561257
printNullability(OTK_Optional, NullabilityPrintKind::ContextSensitive);

lib/SIL/Verifier/SILVerifier.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4283,7 +4283,7 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
42834283
// If the method returns dynamic Self, substitute AnyObject for the
42844284
// result type.
42854285
if (auto fnDecl = dyn_cast<FuncDecl>(method.getDecl())) {
4286-
if (fnDecl->hasDynamicSelfResult()) {
4286+
if (fnDecl->getResultInterfaceType()->hasDynamicSelfType()) {
42874287
auto anyObjectTy = C.getAnyObjectType();
42884288
for (auto &result : results) {
42894289
auto resultTy =

lib/Sema/CSApply.cpp

Lines changed: 27 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1403,23 +1403,25 @@ namespace {
14031403
// special handling.
14041404
if (baseExpr) {
14051405
if (auto *fnDecl = dyn_cast<AbstractFunctionDecl>(declOrClosure)) {
1406-
if (fnDecl->hasDynamicSelfResult()) {
1407-
Type convTy;
1408-
1409-
if (cs.getType(baseExpr)->hasOpenedExistential()) {
1410-
// FIXME: Sometimes we need to convert to an opened existential
1411-
// first, because CovariantReturnConversionExpr does not support
1412-
// direct conversions from a class C to an existential C & P.
1413-
convTy = cs.getType(baseExpr)->getMetatypeInstanceType();
1414-
convTy =
1415-
thunkTy->getResult()->replaceCovariantResultType(convTy, 0);
1416-
} else {
1417-
convTy = thunkTy->getResult();
1418-
}
1406+
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+
}
14191420

1420-
if (!thunkBody->getType()->isEqual(convTy)) {
1421-
thunkBody = cs.cacheType(
1422-
new (ctx) CovariantReturnConversionExpr(thunkBody, convTy));
1421+
if (!thunkBody->getType()->isEqual(convTy)) {
1422+
thunkBody = cs.cacheType(
1423+
new (ctx) CovariantReturnConversionExpr(thunkBody, convTy));
1424+
}
14231425
}
14241426
}
14251427
}
@@ -1964,9 +1966,10 @@ namespace {
19641966

19651967
auto *func = dyn_cast<FuncDecl>(member);
19661968
if (func && func->getResultInterfaceType()->hasDynamicSelfType()) {
1967-
refTy = refTy->replaceCovariantResultType(containerTy, 2);
1968-
adjustedRefTy = adjustedRefTy->replaceCovariantResultType(
1969-
containerTy, 2);
1969+
ASSERT(refTy->hasDynamicSelfType());
1970+
refTy = refTy->replaceDynamicSelfType(containerTy);
1971+
adjustedRefTy = adjustedRefTy->replaceDynamicSelfType(
1972+
containerTy);
19701973
}
19711974

19721975
// Handle all other references.
@@ -2110,10 +2113,9 @@ namespace {
21102113
//
21112114
// Note: For unbound references this is handled inside the thunk.
21122115
if (!isUnboundInstanceMember &&
2113-
!member->getDeclContext()->getSelfProtocolDecl()) {
2116+
member->getDeclContext()->getSelfClassDecl()) {
21142117
if (auto func = dyn_cast<AbstractFunctionDecl>(member)) {
2115-
if (func->hasDynamicSelfResult() &&
2116-
!baseTy->getOptionalObjectType()) {
2118+
if (func->hasDynamicSelfResult()) {
21172119
// FIXME: Once CovariantReturnConversionExpr (unchecked_ref_cast)
21182120
// supports a class existential dest., consider using the opened
21192121
// type directly to avoid recomputing the 'Self' replacement and
@@ -2543,9 +2545,9 @@ namespace {
25432545
new (ctx) OtherConstructorDeclRefExpr(ref, loc, implicit, resultTy));
25442546

25452547
// Wrap in covariant `Self` return if needed.
2546-
if (selfTy->hasReferenceSemantics()) {
2547-
auto covariantTy = resultTy->replaceCovariantResultType(
2548-
cs.getType(base)->getWithoutSpecifierType(), 2);
2548+
if (ref.getDecl()->getDeclContext()->getSelfClassDecl()) {
2549+
auto covariantTy = resultTy->withCovariantResultType()
2550+
->replaceDynamicSelfType(cs.getType(base)->getWithoutSpecifierType());
25492551
if (!covariantTy->isEqual(resultTy))
25502552
ctorRef = cs.cacheType(
25512553
new (ctx) CovariantFunctionConversionExpr(ctorRef, covariantTy));

lib/Sema/CSSimplify.cpp

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13210,18 +13210,14 @@ bool ConstraintSystem::simplifyAppliedOverloadsImpl(
1321013210

1321113211
/// The common result type amongst all function overloads.
1321213212
Type commonResultType;
13213-
auto updateCommonResultType = [&](Type choiceType) {
13214-
auto markFailure = [&] {
13215-
commonResultType = ErrorType::get(getASTContext());
13216-
};
1321713213

13218-
auto choiceFnType = choiceType->getAs<FunctionType>();
13219-
if (!choiceFnType)
13220-
return markFailure();
13214+
auto markFailure = [&] {
13215+
commonResultType = ErrorType::get(getASTContext());
13216+
};
1322113217

13218+
auto updateCommonResultType = [&](Type choiceResultType) {
1322213219
// For now, don't attempt to establish a common result type when there
1322313220
// are type parameters.
13224-
Type choiceResultType = choiceFnType->getResult();
1322513221
if (choiceResultType->hasTypeParameter())
1322613222
return markFailure();
1322713223

@@ -13359,8 +13355,28 @@ bool ConstraintSystem::simplifyAppliedOverloadsImpl(
1335913355
choiceType = objectType;
1336013356
}
1336113357

13362-
// If we have a function type, we can compute a common result type.
13363-
updateCommonResultType(choiceType);
13358+
if (auto *choiceFnType = choiceType->getAs<FunctionType>()) {
13359+
if (isa<ConstructorDecl>(choice.getDecl())) {
13360+
auto choiceResultType = choice.getBaseType()
13361+
->getRValueType()
13362+
->getMetatypeInstanceType();
13363+
13364+
if (choiceResultType->getOptionalObjectType()) {
13365+
hasUnhandledConstraints = true;
13366+
return true;
13367+
}
13368+
13369+
if (choiceFnType->getResult()->getOptionalObjectType())
13370+
choiceResultType = OptionalType::get(choiceResultType);
13371+
13372+
updateCommonResultType(choiceResultType);
13373+
} else {
13374+
updateCommonResultType(choiceFnType->getResult());
13375+
}
13376+
} else {
13377+
markFailure();
13378+
}
13379+
1336413380
return true;
1336513381
});
1336613382

lib/Sema/MiscDiagnostics.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6808,13 +6808,15 @@ TypeChecker::omitNeedlessWords(AbstractFunctionDecl *afd) {
68086808
// Handle contextual type, result type, and returnsSelf.
68096809
Type contextType = afd->getDeclContext()->getDeclaredInterfaceType();
68106810
Type resultType;
6811-
bool returnsSelf = afd->hasDynamicSelfResult();
6811+
bool returnsSelf;
68126812

68136813
if (auto func = dyn_cast<FuncDecl>(afd)) {
68146814
resultType = func->getResultInterfaceType();
68156815
resultType = func->mapTypeIntoContext(resultType);
6816+
returnsSelf = func->getResultInterfaceType()->hasDynamicSelfType();
68166817
} else if (isa<ConstructorDecl>(afd)) {
68176818
resultType = contextType;
6819+
returnsSelf = true;
68186820
}
68196821

68206822
// Figure out the first parameter name.

lib/Sema/TypeCheckAttr.cpp

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -6641,21 +6641,21 @@ typecheckDifferentiableAttrforDecl(AbstractFunctionDecl *original,
66416641
// Dynamic `Self` is supported only as a single top-level result for class
66426642
// members. JVP/VJP functions returning `(Self, ...)` tuples would not
66436643
// type-check.
6644-
bool diagnoseDynamicSelfResult = original->hasDynamicSelfResult();
6645-
if (diagnoseDynamicSelfResult) {
6646-
// Diagnose class initializers in non-final classes.
6647-
if (isa<ConstructorDecl>(original)) {
6648-
if (!classDecl->isSemanticallyFinal()) {
6649-
diags.diagnose(
6650-
attr->getLocation(),
6651-
diag::differentiable_attr_nonfinal_class_init_unsupported,
6652-
classDecl->getDeclaredInterfaceType());
6653-
attr->setInvalid();
6654-
return nullptr;
6655-
}
6644+
// Diagnose class initializers in non-final classes.
6645+
if (isa<ConstructorDecl>(original)) {
6646+
if (!classDecl->isSemanticallyFinal()) {
6647+
diags.diagnose(
6648+
attr->getLocation(),
6649+
diag::differentiable_attr_nonfinal_class_init_unsupported,
6650+
classDecl->getDeclaredInterfaceType());
6651+
attr->setInvalid();
6652+
return nullptr;
66566653
}
6654+
}
6655+
6656+
if (auto *funcDecl = dyn_cast<FuncDecl>(original)) {
66576657
// Diagnose all other declarations returning dynamic `Self`.
6658-
else {
6658+
if (funcDecl->getResultInterfaceType()->hasDynamicSelfType()) {
66596659
diags.diagnose(
66606660
attr->getLocation(),
66616661
diag::
@@ -7035,19 +7035,19 @@ static bool typeCheckDerivativeAttr(DerivativeAttr *attr) {
70357035
// Dynamic `Self` is supported only as a single top-level result for class
70367036
// members. JVP/VJP functions returning `(Self, ...)` tuples would not
70377037
// type-check.
7038-
bool diagnoseDynamicSelfResult = originalAFD->hasDynamicSelfResult();
7039-
if (diagnoseDynamicSelfResult) {
7038+
if (isa<ConstructorDecl>(originalAFD)) {
70407039
// Diagnose class initializers in non-final classes.
7041-
if (isa<ConstructorDecl>(originalAFD)) {
7042-
if (!classDecl->isSemanticallyFinal()) {
7043-
diags.diagnose(attr->getLocation(),
7044-
diag::derivative_attr_nonfinal_class_init_unsupported,
7045-
classDecl->getDeclaredInterfaceType());
7046-
return true;
7047-
}
7040+
if (!classDecl->isSemanticallyFinal()) {
7041+
diags.diagnose(attr->getLocation(),
7042+
diag::derivative_attr_nonfinal_class_init_unsupported,
7043+
classDecl->getDeclaredInterfaceType());
7044+
return true;
70487045
}
7046+
}
7047+
7048+
if (auto *FD = dyn_cast<FuncDecl>(originalAFD)) {
70497049
// Diagnose all other declarations returning dynamic `Self`.
7050-
else {
7050+
if (FD->getResultInterfaceType()->hasDynamicSelfType()) {
70517051
diags.diagnose(
70527052
attr->getLocation(),
70537053
diag::derivative_attr_class_member_dynamic_self_result_unsupported,

0 commit comments

Comments
 (0)