Skip to content

Commit ba17068

Browse files
committed
Introduce LifetimeDependence experimental feature
1 parent 1b2a3d3 commit ba17068

File tree

6 files changed

+44
-12
lines changed

6 files changed

+44
-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: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,15 @@ static Type getResultOrYield(AbstractFunctionDecl *afd) {
216216
}
217217

218218
static bool hasEscapableResultOrYield(AbstractFunctionDecl *afd) {
219-
return getResultOrYield(afd)->isEscapable();
219+
auto resultType = getResultOrYield(afd);
220+
// FIXME: This check is temporary until rdar://139976667 is fixed.
221+
// ModuleType created with ModuleType::get methods are ~Copyable and
222+
// ~Escapable because the Copyable and Escapable conformance is not added to
223+
// them by default.
224+
if (resultType->is<ModuleType>()) {
225+
return true;
226+
}
227+
return resultType->isEscapable();
220228
}
221229

222230
static std::optional<LifetimeDependenceKind>
@@ -508,6 +516,10 @@ LifetimeDependenceInfo::infer(AbstractFunctionDecl *afd) {
508516
return std::nullopt;
509517
}
510518

519+
if (afd->getAttrs().hasAttribute<UnsafeNonEscapableResultAttr>()) {
520+
return std::nullopt;
521+
}
522+
511523
// Setters infer 'self' dependence on 'newValue'.
512524
if (auto accessor = dyn_cast<AccessorDecl>(afd)) {
513525
if (accessor->getAccessorKind() == AccessorKind::Set) {
@@ -519,10 +531,6 @@ LifetimeDependenceInfo::infer(AbstractFunctionDecl *afd) {
519531
return std::nullopt;
520532
}
521533

522-
if (afd->getAttrs().hasAttribute<UnsafeNonEscapableResultAttr>()) {
523-
return std::nullopt;
524-
}
525-
526534
auto &diags = ctx.Diags;
527535
auto returnTypeRepr = afd->getResultTypeRepr();
528536
auto returnLoc = returnTypeRepr ? returnTypeRepr->getLoc() : afd->getLoc();
@@ -537,6 +545,11 @@ LifetimeDependenceInfo::infer(AbstractFunctionDecl *afd) {
537545
}
538546
}
539547

548+
if (!ctx.LangOpts.hasFeature(Feature::LifetimeDependence)) {
549+
diags.diagnose(returnLoc, diag::lifetime_dependence_feature_required);
550+
return std::nullopt;
551+
}
552+
540553
if (!cd && afd->hasImplicitSelfDecl()) {
541554
Type selfTypeInContext = dc->getSelfTypeInContext();
542555
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)