Skip to content

Commit e738b8a

Browse files
authored
Merge pull request #71353 from meg-gupta/initlifetimedep
Support for lifetime dependence specifiers on initializers
2 parents 4e971a4 + 0835d00 commit e738b8a

24 files changed

+260
-50
lines changed

include/swift/AST/AnyFunctionRef.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,11 @@ class AnyFunctionRef {
116116
if (auto *AFD = TheFunction.dyn_cast<AbstractFunctionDecl *>()) {
117117
if (auto *FD = dyn_cast<FuncDecl>(AFD))
118118
return FD->mapTypeIntoContext(FD->getResultInterfaceType());
119+
if (auto *CD = dyn_cast<ConstructorDecl>(AFD)) {
120+
if (CD->hasLifetimeDependentReturn()) {
121+
return CD->getResultInterfaceType();
122+
}
123+
}
119124
return TupleType::getEmpty(AFD->getASTContext());
120125
}
121126
return TheFunction.get<AbstractClosureExpr *>()->getResultType();

include/swift/AST/Decl.h

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8303,15 +8303,18 @@ class ConstructorDecl : public AbstractFunctionDecl {
83038303
/// inserted at the end of the initializer by SILGen.
83048304
Expr *CallToSuperInit = nullptr;
83058305

8306+
/// Valid when lifetime dependence specifiers are present.
8307+
TypeLoc InitRetType;
8308+
83068309
public:
8307-
ConstructorDecl(DeclName Name, SourceLoc ConstructorLoc,
8310+
ConstructorDecl(DeclName Name, SourceLoc ConstructorLoc,
83088311
bool Failable, SourceLoc FailabilityLoc,
83098312
bool Async, SourceLoc AsyncLoc,
83108313
bool Throws, SourceLoc ThrowsLoc,
83118314
TypeLoc thrownTy,
83128315
ParameterList *BodyParams,
8313-
GenericParamList *GenericParams,
8314-
DeclContext *Parent);
8316+
GenericParamList *GenericParams,
8317+
DeclContext *Parent, TypeRepr *InitRetTy);
83158318

83168319
static ConstructorDecl *
83178320
createImported(ASTContext &ctx, ClangNode clangNode, DeclName name,
@@ -8333,6 +8336,10 @@ class ConstructorDecl : public AbstractFunctionDecl {
83338336
/// Get the interface type of the initializing constructor.
83348337
Type getInitializerInterfaceType();
83358338

8339+
TypeRepr *getResultTypeRepr() const { return InitRetType.getTypeRepr(); }
8340+
8341+
void setDeserializedResultTypeLoc(TypeLoc ResultTyR);
8342+
83368343
/// Get the typechecked call to super.init expression, which needs to be
83378344
/// inserted at the end of the initializer by SILGen.
83388345
Expr *getSuperInitCall() { return CallToSuperInit; }
@@ -8412,6 +8419,8 @@ class ConstructorDecl : public AbstractFunctionDecl {
84128419
Bits.ConstructorDecl.HasStubImplementation = stub;
84138420
}
84148421

8422+
bool hasLifetimeDependentReturn() const;
8423+
84158424
ConstructorDecl *getOverriddenDecl() const {
84168425
return cast_or_null<ConstructorDecl>(
84178426
AbstractFunctionDecl::getOverriddenDecl());

include/swift/AST/DiagnosticsParse.def

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2179,6 +2179,10 @@ ERROR(requires_experimental_feature, none,
21792179
"%2 is enabled",
21802180
(StringRef, bool, StringRef))
21812181

2182+
//------------------------------------------------------------------------------
2183+
// MARK: Lifetime dependence
2184+
//------------------------------------------------------------------------------
2185+
21822186
ERROR(expected_lparen_after_lifetime_dependence, PointsToFirstBadToken,
21832187
"expected '(' after lifetime dependence specifier", ())
21842188

@@ -2193,5 +2197,9 @@ ERROR(expected_rparen_after_lifetime_dependence, PointsToFirstBadToken,
21932197
ERROR(expected_param_index_lifetime_dependence, PointsToFirstBadToken,
21942198
"expected unsigned parameter index in lifetime dependence specifier", ())
21952199

2200+
ERROR(lifetime_dependence_invalid_init_return, PointsToFirstBadToken,
2201+
"expected Self return type for initializers with lifetime dependence "
2202+
"specifiers",
2203+
())
21962204
#define UNDEFINE_DIAGNOSTIC_MACROS
21972205
#include "DefineDiagnosticMacros.h"

include/swift/AST/DiagnosticsSema.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7811,5 +7811,9 @@ ERROR(pack_iteration_where_clause_not_supported, none,
78117811
"cannot infer lifetime dependence, no ~Escapable or ~Copyable "
78127812
"parameters with ownership modifiers present",
78137813
())
7814+
ERROR(lifetime_dependence_ctor_non_self_or_nil_return, none,
7815+
"expected nil or self as return values in an initializer with "
7816+
"lifetime dependent specifiers",
7817+
())
78147818
#define UNDEFINE_DIAGNOSTIC_MACROS
78157819
#include "DefineDiagnosticMacros.h"

lib/AST/ASTBridging.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -945,12 +945,13 @@ BridgedConstructorDecl BridgedConstructorDecl_createParsed(
945945
auto throwsLoc = cThrowsLoc.unbridged();
946946
auto failabilityMarkLoc = cFailabilityMarkLoc.unbridged();
947947
// FIXME: rethrows
948-
948+
// TODO: Handle LifetimeDependentReturnTypeRepr here.
949949
auto *decl = new (context) ConstructorDecl(
950950
declName, cInitKeywordLoc.unbridged(), failabilityMarkLoc.isValid(),
951951
failabilityMarkLoc, asyncLoc.isValid(), asyncLoc, throwsLoc.isValid(),
952952
throwsLoc, thrownType.unbridged(), parameterList,
953-
genericParams.unbridged(), cDeclContext.unbridged());
953+
genericParams.unbridged(), cDeclContext.unbridged(),
954+
/*InitRetTy*/ nullptr);
954955
decl->setTrailingWhereClause(genericWhereClause.unbridged());
955956
decl->setImplicitlyUnwrappedOptional(isIUO);
956957

lib/AST/ASTVerifier.cpp

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1075,17 +1075,25 @@ class Verifier : public ASTWalker {
10751075
resultType = FD->mapTypeIntoContext(resultType);
10761076
} else if (auto closure = dyn_cast<AbstractClosureExpr>(func)) {
10771077
resultType = closure->getResultType();
1078+
} else if (auto *CD = dyn_cast<ConstructorDecl>(func)) {
1079+
if (CD->hasLifetimeDependentReturn()) {
1080+
resultType = CD->getResultInterfaceType();
1081+
} else {
1082+
resultType = TupleType::getEmpty(Ctx);
1083+
}
10781084
} else {
10791085
resultType = TupleType::getEmpty(Ctx);
10801086
}
1081-
1087+
10821088
if (S->hasResult()) {
1083-
if (isa<ConstructorDecl>(func)) {
1084-
Out << "Expected ReturnStmt not to have a result. A constructor "
1085-
"should not return a result. Returned expression: ";
1086-
S->getResult()->dump(Out);
1087-
Out << "\n";
1088-
abort();
1089+
if (auto *CD = dyn_cast<ConstructorDecl>(func)) {
1090+
if (!CD->hasLifetimeDependentReturn()) {
1091+
Out << "Expected ReturnStmt not to have a result. A constructor "
1092+
"should not return a result. Returned expression: ";
1093+
S->getResult()->dump(Out);
1094+
Out << "\n";
1095+
abort();
1096+
}
10891097
}
10901098

10911099
auto result = S->getResult();

lib/AST/Decl.cpp

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3579,6 +3579,8 @@ TypeRepr *ValueDecl::getResultTypeRepr() const {
35793579
returnRepr = SD->getElementTypeRepr();
35803580
} else if (auto *MD = dyn_cast<MacroDecl>(this)) {
35813581
returnRepr = MD->resultType.getTypeRepr();
3582+
} else if (auto *CD = dyn_cast<ConstructorDecl>(this)) {
3583+
returnRepr = CD->getResultTypeRepr();
35823584
}
35833585

35843586
return returnRepr;
@@ -10419,7 +10421,7 @@ ConstructorDecl::ConstructorDecl(DeclName Name, SourceLoc ConstructorLoc,
1041910421
TypeLoc ThrownType,
1042010422
ParameterList *BodyParams,
1042110423
GenericParamList *GenericParams,
10422-
DeclContext *Parent)
10424+
DeclContext *Parent, TypeRepr *ResultTyR)
1042310425
: AbstractFunctionDecl(DeclKind::Constructor, Parent, Name, ConstructorLoc,
1042410426
Async, AsyncLoc, Throws, ThrowsLoc, ThrownType,
1042510427
/*HasImplicitSelfDecl=*/true,
@@ -10429,7 +10431,8 @@ ConstructorDecl::ConstructorDecl(DeclName Name, SourceLoc ConstructorLoc,
1042910431
{
1043010432
if (BodyParams)
1043110433
setParameters(BodyParams);
10432-
10434+
10435+
InitRetType = TypeLoc(ResultTyR);
1043310436
Bits.ConstructorDecl.HasStubImplementation = 0;
1043410437
Bits.ConstructorDecl.Failable = Failable;
1043510438

@@ -10450,11 +10453,16 @@ ConstructorDecl *ConstructorDecl::createImported(
1045010453
failable, failabilityLoc,
1045110454
async, asyncLoc,
1045210455
throws, throwsLoc, TypeLoc::withoutLoc(thrownType),
10453-
bodyParams, genericParams, parent);
10456+
bodyParams, genericParams, parent,
10457+
/*LifetimeDependenceTypeRepr*/ nullptr);
1045410458
ctor->setClangNode(clangNode);
1045510459
return ctor;
1045610460
}
1045710461

10462+
void ConstructorDecl::setDeserializedResultTypeLoc(TypeLoc ResultTyR) {
10463+
InitRetType = ResultTyR;
10464+
}
10465+
1045810466
bool ConstructorDecl::isObjCZeroParameterWithLongSelector() const {
1045910467
// The initializer must have a single, non-empty argument name.
1046010468
if (getName().getArgumentNames().size() != 1 ||
@@ -10468,6 +10476,10 @@ bool ConstructorDecl::isObjCZeroParameterWithLongSelector() const {
1046810476
return params->get(0)->getInterfaceType()->isVoid();
1046910477
}
1047010478

10479+
bool ConstructorDecl::hasLifetimeDependentReturn() const {
10480+
return isa_and_nonnull<LifetimeDependentReturnTypeRepr>(getResultTypeRepr());
10481+
}
10482+
1047110483
DestructorDecl::DestructorDecl(SourceLoc DestructorLoc, DeclContext *Parent)
1047210484
: AbstractFunctionDecl(DeclKind::Destructor, Parent,
1047310485
DeclBaseName::createDestructor(), DestructorLoc,

lib/ClangImporter/ImportDecl.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3646,7 +3646,8 @@ namespace {
36463646
/*failable=*/false, /*FailabilityLoc=*/SourceLoc(),
36473647
/*Async=*/false, /*AsyncLoc=*/SourceLoc(),
36483648
/*Throws=*/false, /*ThrowsLoc=*/SourceLoc(),
3649-
/*ThrownType=*/TypeLoc(), bodyParams, genericParams, dc);
3649+
/*ThrownType=*/TypeLoc(), bodyParams, genericParams, dc,
3650+
/*LifetimeDependentReturnTypeRepr*/ nullptr);
36503651
} else {
36513652
auto resultTy = importedType.getType();
36523653

@@ -6221,7 +6222,8 @@ Decl *SwiftDeclConverter::importGlobalAsInitializer(
62216222
failable, /*FailabilityLoc=*/SourceLoc(),
62226223
/*Async=*/false, /*AsyncLoc=*/SourceLoc(),
62236224
/*Throws=*/false, /*ThrowsLoc=*/SourceLoc(), /*ThrownType=*/TypeLoc(),
6224-
parameterList, /*GenericParams=*/nullptr, dc);
6225+
parameterList, /*GenericParams=*/nullptr, dc,
6226+
/*LifetimeDependentReturnTypeRepr*/ nullptr);
62256227
result->setImplicitlyUnwrappedOptional(isIUO);
62266228
result->getASTContext().evaluator.cacheOutput(InitKindRequest{result},
62276229
std::move(initKind));
@@ -6735,7 +6737,8 @@ ConstructorDecl *SwiftDeclConverter::importConstructor(
67356737
/*Async=*/false, /*AsyncLoc=*/SourceLoc(),
67366738
/*Throws=*/importedName.getErrorInfo().has_value(),
67376739
/*ThrowsLoc=*/SourceLoc(), /*ThrownType=*/TypeLoc(), bodyParams,
6738-
/*GenericParams=*/nullptr, const_cast<DeclContext *>(dc));
6740+
/*GenericParams=*/nullptr, const_cast<DeclContext *>(dc),
6741+
/*LifetimeDependentReturnTypeRepr*/ nullptr);
67396742

67406743
addObjCAttribute(result, selector);
67416744
recordMemberInContext(dc, result);

lib/ClangImporter/SwiftDeclSynthesizer.cpp

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -493,9 +493,10 @@ SwiftDeclSynthesizer::createDefaultConstructor(NominalTypeDecl *structDecl) {
493493
ConstructorDecl(name, structDecl->getLoc(),
494494
/*Failable=*/false, /*FailabilityLoc=*/SourceLoc(),
495495
/*Async=*/false, /*AsyncLoc=*/SourceLoc(),
496-
/*Throws=*/false, /*ThrowsLoc=*/SourceLoc(),
496+
/*Throws=*/false, /*ThrowsLoc=*/SourceLoc(),
497497
/*ThrownType=*/TypeLoc(), emptyPL,
498-
/*GenericParams=*/nullptr, structDecl);
498+
/*GenericParams=*/nullptr, structDecl,
499+
/*LifetimeDependentReturnTypeRepr*/ nullptr);
499500

500501
constructor->setAccess(AccessLevel::Public);
501502

@@ -623,9 +624,10 @@ ConstructorDecl *SwiftDeclSynthesizer::createValueConstructor(
623624
ConstructorDecl(name, structDecl->getLoc(),
624625
/*Failable=*/false, /*FailabilityLoc=*/SourceLoc(),
625626
/*Async=*/false, /*AsyncLoc=*/SourceLoc(),
626-
/*Throws=*/false, /*ThrowsLoc=*/SourceLoc(),
627+
/*Throws=*/false, /*ThrowsLoc=*/SourceLoc(),
627628
/*ThrownType=*/TypeLoc(), paramList,
628-
/*GenericParams=*/nullptr, structDecl);
629+
/*GenericParams=*/nullptr, structDecl,
630+
/*LifetimeDependentReturnTypeRepr*/ nullptr);
629631

630632
constructor->setAccess(AccessLevel::Public);
631633

@@ -1271,13 +1273,14 @@ SwiftDeclSynthesizer::makeEnumRawValueConstructor(EnumDecl *enumDecl) {
12711273
auto paramPL = ParameterList::createWithoutLoc(param);
12721274

12731275
DeclName name(C, DeclBaseName::createConstructor(), paramPL);
1274-
auto *ctorDecl = new (C)
1275-
ConstructorDecl(name, enumDecl->getLoc(),
1276-
/*Failable=*/true, /*FailabilityLoc=*/SourceLoc(),
1277-
/*Async=*/false, /*AsyncLoc=*/SourceLoc(),
1278-
/*Throws=*/false, /*ThrowsLoc=*/SourceLoc(),
1279-
/*ThrownType=*/TypeLoc(), paramPL,
1280-
/*GenericParams=*/nullptr, enumDecl);
1276+
auto *ctorDecl =
1277+
new (C) ConstructorDecl(name, enumDecl->getLoc(),
1278+
/*Failable=*/true, /*FailabilityLoc=*/SourceLoc(),
1279+
/*Async=*/false, /*AsyncLoc=*/SourceLoc(),
1280+
/*Throws=*/false, /*ThrowsLoc=*/SourceLoc(),
1281+
/*ThrownType=*/TypeLoc(), paramPL,
1282+
/*GenericParams=*/nullptr, enumDecl,
1283+
/*LifetimeDependentReturnTypeRepr*/ nullptr);
12811284
ctorDecl->setImplicit();
12821285
ctorDecl->setAccess(AccessLevel::Public);
12831286
ctorDecl->setBodySynthesizer(synthesizeEnumRawValueConstructorBody, enumDecl);

lib/Parse/ParseDecl.cpp

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9830,7 +9830,16 @@ Parser::parseDeclInit(ParseDeclOptions Flags, DeclAttributes &Attributes) {
98309830
isAsync = true;
98319831
}
98329832

9833-
if (FuncRetTy) {
9833+
if (auto *lifetimeTyR =
9834+
dyn_cast_or_null<LifetimeDependentReturnTypeRepr>(FuncRetTy)) {
9835+
auto *identTyR = dyn_cast<SimpleIdentTypeRepr>(lifetimeTyR->getBase());
9836+
if (!identTyR ||
9837+
identTyR->getNameRef().getBaseIdentifier() != Context.Id_Self) {
9838+
diagnose(FuncRetTy->getStartLoc(),
9839+
diag::lifetime_dependence_invalid_init_return);
9840+
return nullptr;
9841+
}
9842+
} else if (FuncRetTy) {
98349843
diagnose(FuncRetTy->getStartLoc(), diag::initializer_result_type)
98359844
.fixItRemove(FuncRetTy->getSourceRange());
98369845
}
@@ -9849,7 +9858,7 @@ Parser::parseDeclInit(ParseDeclOptions Flags, DeclAttributes &Attributes) {
98499858
isAsync, asyncLoc,
98509859
throwsLoc.isValid(), throwsLoc,
98519860
thrownTy, BodyParams, GenericParams,
9852-
CurDeclContext);
9861+
CurDeclContext, FuncRetTy);
98539862
CD->setImplicitlyUnwrappedOptional(IUO);
98549863
CD->getAttrs() = Attributes;
98559864

0 commit comments

Comments
 (0)