Skip to content

Commit c8ece10

Browse files
committed
Handle explicit lifetime dependence specifiers in initializers
1 parent a6dbfa9 commit c8ece10

19 files changed

+191
-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: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8299,15 +8299,18 @@ class ConstructorDecl : public AbstractFunctionDecl {
82998299
/// inserted at the end of the initializer by SILGen.
83008300
Expr *CallToSuperInit = nullptr;
83018301

8302+
/// Valid when lifetime dependence specifiers are present.
8303+
TypeLoc InitRetType;
8304+
83028305
public:
8303-
ConstructorDecl(DeclName Name, SourceLoc ConstructorLoc,
8306+
ConstructorDecl(DeclName Name, SourceLoc ConstructorLoc,
83048307
bool Failable, SourceLoc FailabilityLoc,
83058308
bool Async, SourceLoc AsyncLoc,
83068309
bool Throws, SourceLoc ThrowsLoc,
83078310
TypeLoc thrownTy,
83088311
ParameterList *BodyParams,
8309-
GenericParamList *GenericParams,
8310-
DeclContext *Parent);
8312+
GenericParamList *GenericParams,
8313+
DeclContext *Parent, TypeRepr *InitRetTy);
83118314

83128315
static ConstructorDecl *
83138316
createImported(ASTContext &ctx, ClangNode clangNode, DeclName name,
@@ -8329,6 +8332,8 @@ class ConstructorDecl : public AbstractFunctionDecl {
83298332
/// Get the interface type of the initializing constructor.
83308333
Type getInitializerInterfaceType();
83318334

8335+
TypeRepr *getResultTypeRepr() const { return InitRetType.getTypeRepr(); }
8336+
83328337
/// Get the typechecked call to super.init expression, which needs to be
83338338
/// inserted at the end of the initializer by SILGen.
83348339
Expr *getSuperInitCall() { return CallToSuperInit; }
@@ -8408,6 +8413,8 @@ class ConstructorDecl : public AbstractFunctionDecl {
84088413
Bits.ConstructorDecl.HasStubImplementation = stub;
84098414
}
84108415

8416+
bool hasLifetimeDependentReturn() const;
8417+
84118418
ConstructorDecl *getOverriddenDecl() const {
84128419
return cast_or_null<ConstructorDecl>(
84138420
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
@@ -7827,5 +7827,9 @@ ERROR(pack_iteration_where_clause_not_supported, none,
78277827
"cannot infer lifetime dependence, no ~Escapable or ~Copyable "
78287828
"parameters with ownership modifiers present",
78297829
())
7830+
ERROR(lifetime_dependence_ctor_non_self_or_nil_return, none,
7831+
"expected nil or self as return values in an initializer with "
7832+
"lifetime dependent specifiers",
7833+
())
78307834
#define UNDEFINE_DIAGNOSTIC_MACROS
78317835
#include "DefineDiagnosticMacros.h"

lib/AST/ASTBridging.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -943,12 +943,13 @@ BridgedConstructorDecl BridgedConstructorDecl_createParsed(
943943
auto throwsLoc = cThrowsLoc.unbridged();
944944
auto failabilityMarkLoc = cFailabilityMarkLoc.unbridged();
945945
// FIXME: rethrows
946-
946+
// TODO: Handle LifetimeDependentReturnTypeRepr here.
947947
auto *decl = new (context) ConstructorDecl(
948948
declName, cInitKeywordLoc.unbridged(), failabilityMarkLoc.isValid(),
949949
failabilityMarkLoc, asyncLoc.isValid(), asyncLoc, throwsLoc.isValid(),
950950
throwsLoc, thrownType.unbridged(), parameterList,
951-
genericParams.unbridged(), cDeclContext.unbridged());
951+
genericParams.unbridged(), cDeclContext.unbridged(),
952+
/*InitRetTy*/ nullptr);
952953
decl->setTrailingWhereClause(genericWhereClause.unbridged());
953954
decl->setImplicitlyUnwrappedOptional(isIUO);
954955

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: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3577,6 +3577,8 @@ TypeRepr *ValueDecl::getResultTypeRepr() const {
35773577
returnRepr = SD->getElementTypeRepr();
35783578
} else if (auto *MD = dyn_cast<MacroDecl>(this)) {
35793579
returnRepr = MD->resultType.getTypeRepr();
3580+
} else if (auto *CD = dyn_cast<ConstructorDecl>(this)) {
3581+
returnRepr = CD->getResultTypeRepr();
35803582
}
35813583

35823584
return returnRepr;
@@ -10383,7 +10385,7 @@ ConstructorDecl::ConstructorDecl(DeclName Name, SourceLoc ConstructorLoc,
1038310385
TypeLoc ThrownType,
1038410386
ParameterList *BodyParams,
1038510387
GenericParamList *GenericParams,
10386-
DeclContext *Parent)
10388+
DeclContext *Parent, TypeRepr *ResultTyR)
1038710389
: AbstractFunctionDecl(DeclKind::Constructor, Parent, Name, ConstructorLoc,
1038810390
Async, AsyncLoc, Throws, ThrowsLoc, ThrownType,
1038910391
/*HasImplicitSelfDecl=*/true,
@@ -10393,7 +10395,8 @@ ConstructorDecl::ConstructorDecl(DeclName Name, SourceLoc ConstructorLoc,
1039310395
{
1039410396
if (BodyParams)
1039510397
setParameters(BodyParams);
10396-
10398+
10399+
InitRetType = TypeLoc(ResultTyR);
1039710400
Bits.ConstructorDecl.HasStubImplementation = 0;
1039810401
Bits.ConstructorDecl.Failable = Failable;
1039910402

@@ -10414,7 +10417,8 @@ ConstructorDecl *ConstructorDecl::createImported(
1041410417
failable, failabilityLoc,
1041510418
async, asyncLoc,
1041610419
throws, throwsLoc, TypeLoc::withoutLoc(thrownType),
10417-
bodyParams, genericParams, parent);
10420+
bodyParams, genericParams, parent,
10421+
/*LifetimeDependenceTypeRepr*/ nullptr);
1041810422
ctor->setClangNode(clangNode);
1041910423
return ctor;
1042010424
}
@@ -10432,6 +10436,10 @@ bool ConstructorDecl::isObjCZeroParameterWithLongSelector() const {
1043210436
return params->get(0)->getInterfaceType()->isVoid();
1043310437
}
1043410438

10439+
bool ConstructorDecl::hasLifetimeDependentReturn() const {
10440+
return isa_and_nonnull<LifetimeDependentReturnTypeRepr>(getResultTypeRepr());
10441+
}
10442+
1043510443
DestructorDecl::DestructorDecl(SourceLoc DestructorLoc, DeclContext *Parent)
1043610444
: AbstractFunctionDecl(DeclKind::Destructor, Parent,
1043710445
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
@@ -9817,7 +9817,16 @@ Parser::parseDeclInit(ParseDeclOptions Flags, DeclAttributes &Attributes) {
98179817
isAsync = true;
98189818
}
98199819

9820-
if (FuncRetTy) {
9820+
if (auto *lifetimeTyR =
9821+
dyn_cast_or_null<LifetimeDependentReturnTypeRepr>(FuncRetTy)) {
9822+
auto *identTyR = dyn_cast<SimpleIdentTypeRepr>(lifetimeTyR->getBase());
9823+
if (!identTyR ||
9824+
identTyR->getNameRef().getBaseIdentifier() != Context.Id_Self) {
9825+
diagnose(FuncRetTy->getStartLoc(),
9826+
diag::lifetime_dependence_invalid_init_return);
9827+
return nullptr;
9828+
}
9829+
} else if (FuncRetTy) {
98219830
diagnose(FuncRetTy->getStartLoc(), diag::initializer_result_type)
98229831
.fixItRemove(FuncRetTy->getSourceRange());
98239832
}
@@ -9836,7 +9845,7 @@ Parser::parseDeclInit(ParseDeclOptions Flags, DeclAttributes &Attributes) {
98369845
isAsync, asyncLoc,
98379846
throwsLoc.isValid(), throwsLoc,
98389847
thrownTy, BodyParams, GenericParams,
9839-
CurDeclContext);
9848+
CurDeclContext, FuncRetTy);
98409849
CD->setImplicitlyUnwrappedOptional(IUO);
98419850
CD->getAttrs() = Attributes;
98429851

0 commit comments

Comments
 (0)