Skip to content

Commit f2e46f9

Browse files
committed
Introduce LifetimeDependence experimental feature
1 parent 7bbb63a commit f2e46f9

File tree

6 files changed

+40
-12
lines changed

6 files changed

+40
-12
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8031,6 +8031,10 @@ ERROR(lifetime_dependence_cannot_use_parsed_borrow_consuming, none,
80318031
ERROR(lifetime_dependence_duplicate_target, none,
80328032
"invalid duplicate target lifetime dependencies on function", ())
80338033

8034+
ERROR(lifetime_dependence_feature_required, none,
8035+
"returning ~Escapable type requires '-enable-experimental-feature "
8036+
"LifetimeDependence'", ())
8037+
80348038
//===----------------------------------------------------------------------===//
80358039
// MARK: Sending
80368040
//===----------------------------------------------------------------------===//

include/swift/Basic/Features.def

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -354,10 +354,12 @@ EXPERIMENTAL_FEATURE(SuppressedAssociatedTypes, true)
354354
/// Allow destructuring stored `let` bindings in structs.
355355
EXPERIMENTAL_FEATURE(StructLetDestructuring, true)
356356

357-
/// Enable non-escapable type attributes and function attributes that support
358-
/// lifetime-dependent results.
357+
/// Enable non-escapable types.
359358
SUPPRESSIBLE_EXPERIMENTAL_FEATURE(NonescapableTypes, true)
360359

360+
/// Enable returning non-escapable types from functions.
361+
EXPERIMENTAL_FEATURE(LifetimeDependence, true)
362+
361363
/// Enable the `@_staticExclusiveOnly` attribute.
362364
EXPERIMENTAL_FEATURE(StaticExclusiveOnly, true)
363365

include/swift/Parse/Parser.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1191,7 +1191,7 @@ class Parser {
11911191

11921192
bool isParameterSpecifier() {
11931193
if (Tok.is(tok::kw_inout)) return true;
1194-
if (Context.LangOpts.hasFeature(Feature::NonescapableTypes) &&
1194+
if (Context.LangOpts.hasFeature(Feature::LifetimeDependence) &&
11951195
isSILLifetimeDependenceToken())
11961196
return true;
11971197
if (!canHaveParameterSpecifierContextualKeyword()) return false;

lib/AST/FeatureSet.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,19 @@ static bool usesFeatureSendingArgsAndResults(Decl *decl) {
249249
return false;
250250
}
251251

252+
static bool usesFeatureLifetimeDependence(Decl *decl) {
253+
if (decl->getAttrs().hasAttribute<LifetimeAttr>()) {
254+
return true;
255+
}
256+
auto *afd = dyn_cast<AbstractFunctionDecl>(decl);
257+
if (!afd) {
258+
return false;
259+
}
260+
return afd->getInterfaceType()
261+
->getAs<AnyFunctionType>()
262+
->hasLifetimeDependencies();
263+
}
264+
252265
UNINTERESTING_FEATURE(DynamicActorIsolation)
253266
UNINTERESTING_FEATURE(NonfrozenEnumExhaustivity)
254267
UNINTERESTING_FEATURE(ClosureIsolation)

lib/AST/LifetimeDependence.cpp

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,11 @@ static Type getResultOrYield(AbstractFunctionDecl *afd) {
216216
}
217217

218218
static bool hasEscapableResultOrYield(AbstractFunctionDecl *afd) {
219-
return getResultOrYield(afd)->isEscapable();
219+
auto resultType = getResultOrYield(afd);
220+
if (!resultType->is<NominalType>()) {
221+
return true;
222+
}
223+
return resultType->isEscapable();
220224
}
221225

222226
static std::optional<LifetimeDependenceKind>
@@ -508,6 +512,10 @@ LifetimeDependenceInfo::infer(AbstractFunctionDecl *afd) {
508512
return std::nullopt;
509513
}
510514

515+
if (afd->getAttrs().hasAttribute<UnsafeNonEscapableResultAttr>()) {
516+
return std::nullopt;
517+
}
518+
511519
// Setters infer 'self' dependence on 'newValue'.
512520
if (auto accessor = dyn_cast<AccessorDecl>(afd)) {
513521
if (accessor->getAccessorKind() == AccessorKind::Set) {
@@ -529,10 +537,6 @@ LifetimeDependenceInfo::infer(AbstractFunctionDecl *afd) {
529537
return std::nullopt;
530538
}
531539

532-
if (afd->getAttrs().hasAttribute<UnsafeNonEscapableResultAttr>()) {
533-
return std::nullopt;
534-
}
535-
536540
auto &diags = ctx.Diags;
537541
auto returnTypeRepr = afd->getResultTypeRepr();
538542
auto returnLoc = returnTypeRepr ? returnTypeRepr->getLoc() : afd->getLoc();
@@ -547,6 +551,11 @@ LifetimeDependenceInfo::infer(AbstractFunctionDecl *afd) {
547551
}
548552
}
549553

554+
if (!ctx.LangOpts.hasFeature(Feature::LifetimeDependence)) {
555+
diags.diagnose(returnLoc, diag::lifetime_dependence_feature_required);
556+
return std::nullopt;
557+
}
558+
550559
if (!cd && afd->hasImplicitSelfDecl()) {
551560
Type selfTypeInContext = dc->getSelfTypeInContext();
552561
if (selfTypeInContext->isEscapable()) {

lib/Parse/ParseDecl.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2717,9 +2717,9 @@ parseLifetimeDescriptor(Parser &P,
27172717
ParserResult<LifetimeAttr> Parser::parseLifetimeAttribute(SourceLoc atLoc,
27182718
SourceLoc loc) {
27192719
ParserStatus status;
2720-
if (!Context.LangOpts.hasFeature(Feature::NonescapableTypes)) {
2720+
if (!Context.LangOpts.hasFeature(Feature::LifetimeDependence)) {
27212721
diagnose(loc, diag::requires_experimental_feature, "@lifetime", false,
2722-
getFeatureName(Feature::NonescapableTypes));
2722+
getFeatureName(Feature::LifetimeDependence));
27232723
status.setIsParseError();
27242724
return status;
27252725
}
@@ -5397,10 +5397,10 @@ ParserStatus Parser::ParsedTypeAttributeList::slowParse(Parser &P) {
53975397
}
53985398

53995399
if (P.isSILLifetimeDependenceToken()) {
5400-
if (!P.Context.LangOpts.hasFeature(Feature::NonescapableTypes)) {
5400+
if (!P.Context.LangOpts.hasFeature(Feature::LifetimeDependence)) {
54015401
P.diagnose(Tok, diag::requires_experimental_feature,
54025402
"lifetime dependence specifier", false,
5403-
getFeatureName(Feature::NonescapableTypes));
5403+
getFeatureName(Feature::LifetimeDependence));
54045404
}
54055405
P.consumeToken(); // consume '@'
54065406
auto loc = P.consumeToken(); // consume 'lifetime'

0 commit comments

Comments
 (0)