Skip to content

Commit 1be434d

Browse files
authored
Merge pull request #77637 from meg-gupta/lifetimeexperimental
Enable NonEscapable types by default and move lifetime dependence support under a new feature
2 parents c2f9b2d + 92782a0 commit 1be434d

File tree

93 files changed

+187
-404
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

93 files changed

+187
-404
lines changed

Runtimes/Core/core/CMakeLists.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,6 @@ target_compile_options(swiftCore PRIVATE
273273
"$<$<COMPILE_LANGUAGE:Swift>:SHELL:-enable-experimental-feature SuppressedAssociatedTypes>"
274274
"$<$<COMPILE_LANGUAGE:Swift>:SHELL:-enable-experimental-feature SE427NoInferenceOnExtension>"
275275
"$<$<COMPILE_LANGUAGE:Swift>:SHELL:-enable-experimental-feature AllowUnsafeAttribute>"
276-
"$<$<COMPILE_LANGUAGE:Swift>:SHELL:-enable-experimental-feature NonescapableTypes>"
277276
"$<$<COMPILE_LANGUAGE:Swift>:SHELL:-enable-experimental-feature MemberImportVisibility>"
278277
"$<$<COMPILE_LANGUAGE:Swift>:SHELL:-enable-experimental-feature TypedThrows>"
279278
"$<$<COMPILE_LANGUAGE:Swift>:SHELL:-enable-experimental-feature Macros>"

include/swift/AST/DiagnosticsSema.def

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7784,9 +7784,6 @@ NOTE(note_inverse_preventing_conformance,none,
77847784
NOTE(note_inverse_preventing_conformance_explicit,none,
77857785
"%kind0 has '~%1' constraint preventing '%1' conformance",
77867786
(const ValueDecl *, StringRef))
7787-
ERROR(escapable_requires_feature_flag,none,
7788-
"type 'Escapable' requires -enable-experimental-feature NonescapableTypes",
7789-
())
77907787
ERROR(non_bitwise_copyable_type_class,none,
77917788
"class cannot conform to 'BitwiseCopyable'", ())
77927789
ERROR(non_bitwise_copyable_type_indirect_enum,none,
@@ -7910,9 +7907,6 @@ ERROR(noncopyable_cannot_have_read_set_accessor,none,
79107907
"noncopyable %select{variable|subscript}0 cannot provide a read and set accessor",
79117908
(unsigned))
79127909

7913-
ERROR(nonescapable_types_attr_disabled,none,
7914-
"attribute requires '-enable-experimental-feature NonescapableTypes'", ())
7915-
79167910
ERROR(span_requires_feature_flag,none,
79177911
"'%0' requires -enable-experimental-feature Span",
79187912
(StringRef))
@@ -8031,6 +8025,10 @@ ERROR(lifetime_dependence_cannot_use_parsed_borrow_consuming, none,
80318025
ERROR(lifetime_dependence_duplicate_target, none,
80328026
"invalid duplicate target lifetime dependencies on function", ())
80338027

8028+
ERROR(lifetime_dependence_feature_required, none,
8029+
"returning ~Escapable type requires '-enable-experimental-feature "
8030+
"LifetimeDependence'", ())
8031+
80348032
//===----------------------------------------------------------------------===//
80358033
// MARK: Sending
80368034
//===----------------------------------------------------------------------===//

include/swift/AST/PrintOptions.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -397,9 +397,6 @@ struct PrintOptions {
397397
/// Replace BitwiseCopyable with _BitwiseCopyable.
398398
bool SuppressBitwiseCopyable = false;
399399

400-
/// Suppress ~Escapable types and lifetime dependence annotations
401-
bool SuppressNonEscapableTypes = false;
402-
403400
/// Suppress modify/read accessors.
404401
bool SuppressCoroutineAccessors = false;
405402

include/swift/Basic/Features.def

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,7 @@ BASELINE_LANGUAGE_FEATURE(BorrowingSwitch, 432, "Noncopyable type pattern matchi
202202
CONDITIONALLY_SUPPRESSIBLE_LANGUAGE_FEATURE(IsolatedAny, 431, "@isolated(any) function types")
203203
LANGUAGE_FEATURE(IsolatedAny2, 431, "@isolated(any) function types")
204204
LANGUAGE_FEATURE(ObjCImplementation, 436, "@objc @implementation extensions")
205+
LANGUAGE_FEATURE(NonescapableTypes, 446, "Nonescapable types")
205206

206207
// Swift 6
207208
UPCOMING_FEATURE(ConciseMagicFile, 274, 6)
@@ -354,9 +355,8 @@ EXPERIMENTAL_FEATURE(SuppressedAssociatedTypes, true)
354355
/// Allow destructuring stored `let` bindings in structs.
355356
EXPERIMENTAL_FEATURE(StructLetDestructuring, true)
356357

357-
/// Enable non-escapable type attributes and function attributes that support
358-
/// lifetime-dependent results.
359-
SUPPRESSIBLE_EXPERIMENTAL_FEATURE(NonescapableTypes, true)
358+
/// Enable returning non-escapable types from functions.
359+
EXPERIMENTAL_FEATURE(LifetimeDependence, true)
360360

361361
/// Enable the `@_staticExclusiveOnly` attribute.
362362
EXPERIMENTAL_FEATURE(StaticExclusiveOnly, true)

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/ASTPrinter.cpp

Lines changed: 0 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -2000,11 +2000,6 @@ void PrintAST::printSingleDepthOfGenericSignature(
20002000
if (dependsOnOpaque(inverse.subject))
20012001
continue;
20022002

2003-
if (inverse.getKind() == InvertibleProtocolKind::Escapable &&
2004-
Options.SuppressNonEscapableTypes) {
2005-
continue;
2006-
}
2007-
20082003
if (isFirstReq) {
20092004
if (printRequirements)
20102005
Printer << " " << tok::kw_where << " ";
@@ -3140,16 +3135,6 @@ suppressingFeatureAllowUnsafeAttribute(PrintOptions &options,
31403135
options.ExcludeAttrList.resize(originalExcludeAttrCount);
31413136
}
31423137

3143-
static void
3144-
suppressingFeatureNonescapableTypes(PrintOptions &options,
3145-
llvm::function_ref<void()> action) {
3146-
unsigned originalExcludeAttrCount = options.ExcludeAttrList.size();
3147-
options.ExcludeAttrList.push_back(DeclAttrKind::Lifetime);
3148-
llvm::SaveAndRestore<bool> scope(options.SuppressNonEscapableTypes, true);
3149-
action();
3150-
options.ExcludeAttrList.resize(originalExcludeAttrCount);
3151-
}
3152-
31533138
static void
31543139
suppressingFeatureCoroutineAccessors(PrintOptions &options,
31553140
llvm::function_ref<void()> action) {
@@ -7862,26 +7847,6 @@ swift::getInheritedForPrinting(
78627847
}
78637848
continue;
78647849
}
7865-
7866-
// Suppress Escapable and ~Escapable.
7867-
if (options.SuppressNonEscapableTypes) {
7868-
if (auto pct = ty->getAs<ProtocolCompositionType>()) {
7869-
auto inverses = pct->getInverses();
7870-
if (inverses.contains(InvertibleProtocolKind::Escapable)) {
7871-
inverses.remove(InvertibleProtocolKind::Escapable);
7872-
ty = ProtocolCompositionType::get(decl->getASTContext(),
7873-
pct->getMembers(), inverses,
7874-
pct->hasExplicitAnyObject());
7875-
if (ty->isAny())
7876-
continue;
7877-
}
7878-
}
7879-
7880-
if (auto protoTy = ty->getAs<ProtocolType>())
7881-
if (protoTy->getDecl()->isSpecificProtocol(
7882-
KnownProtocolKind::Escapable))
7883-
continue;
7884-
}
78857850
}
78867851

78877852
if (options.SuppressConformanceSuppression &&

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
}
@@ -5392,10 +5392,10 @@ ParserStatus Parser::ParsedTypeAttributeList::slowParse(Parser &P) {
53925392
}
53935393

53945394
if (P.isSILLifetimeDependenceToken()) {
5395-
if (!P.Context.LangOpts.hasFeature(Feature::NonescapableTypes)) {
5395+
if (!P.Context.LangOpts.hasFeature(Feature::LifetimeDependence)) {
53965396
P.diagnose(Tok, diag::requires_experimental_feature,
53975397
"lifetime dependence specifier", false,
5398-
getFeatureName(Feature::NonescapableTypes));
5398+
getFeatureName(Feature::LifetimeDependence));
53995399
}
54005400
P.consumeToken(); // consume '@'
54015401
auto loc = P.consumeToken(); // consume 'lifetime'

lib/Sema/TypeCheckAttr.cpp

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7693,18 +7693,10 @@ void AttributeChecker::visitRawLayoutAttr(RawLayoutAttr *attr) {
76937693
sd->setHasUnreferenceableStorage(true);
76947694
}
76957695

7696-
void AttributeChecker::visitNonEscapableAttr(NonEscapableAttr *attr) {
7697-
if (!Ctx.LangOpts.hasFeature(Feature::NonescapableTypes)) {
7698-
diagnoseAndRemoveAttr(attr, diag::nonescapable_types_attr_disabled);
7699-
}
7700-
}
7696+
void AttributeChecker::visitNonEscapableAttr(NonEscapableAttr *attr) {}
77017697

77027698
void AttributeChecker::visitUnsafeNonEscapableResultAttr(
7703-
UnsafeNonEscapableResultAttr *attr) {
7704-
if (!Ctx.LangOpts.hasFeature(Feature::NonescapableTypes)) {
7705-
diagnoseAndRemoveAttr(attr, diag::nonescapable_types_attr_disabled);
7706-
}
7707-
}
7699+
UnsafeNonEscapableResultAttr *attr) {}
77087700

77097701
void AttributeChecker::visitStaticExclusiveOnlyAttr(
77107702
StaticExclusiveOnlyAttr *attr) {

lib/Sema/TypeCheckDeclPrimary.cpp

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -125,13 +125,6 @@ class CheckRepressions {
125125
}
126126
auto ipk = getInvertibleProtocolKind(*kp);
127127
if (ipk) {
128-
// Gate the '~Escapable' type behind a specific flag for now.
129-
// Uses of 'Escapable' itself are already diagnosed; return ErrorType.
130-
if (*ipk == InvertibleProtocolKind::Escapable &&
131-
!ctx.LangOpts.hasFeature(Feature::NonescapableTypes)) {
132-
return ErrorType::get(ctx);
133-
}
134-
135128
return ProtocolCompositionType::getInverseOf(ctx, *ipk);
136129
}
137130
auto rpk = getRepressibleProtocolKind(*kp);

lib/Sema/TypeCheckType.cpp

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4959,22 +4959,6 @@ TypeResolver::resolveDeclRefTypeRepr(DeclRefTypeRepr *repr,
49594959
auto *dc = getDeclContext();
49604960
auto &ctx = getASTContext();
49614961

4962-
// Gate the 'Escapable' type behind a specific flag for now.
4963-
//
4964-
// NOTE: we do not return an ErrorType, though! We're just artificially
4965-
// preventing people from referring to the type without the feature.
4966-
if (auto proto = result->getAs<ProtocolType>()) {
4967-
if (auto known = proto->getKnownProtocol()) {
4968-
if (*known == KnownProtocolKind::Escapable
4969-
&& !isSILSourceFile()
4970-
&& !isInterfaceFile()
4971-
&& !ctx.LangOpts.hasFeature(Feature::NonescapableTypes)) {
4972-
diagnoseInvalid(repr, repr->getLoc(),
4973-
diag::escapable_requires_feature_flag);
4974-
}
4975-
}
4976-
}
4977-
49784962
if (ctx.LangOpts.hasFeature(Feature::ImplicitSome) &&
49794963
options.isConstraintImplicitExistential()) {
49804964
// Check whether this type is an implicit opaque result type.
@@ -5991,14 +5975,6 @@ NeverNullType TypeResolver::resolveInverseType(InverseTypeRepr *repr,
59915975

59925976
if (auto kp = ty->getKnownProtocol()) {
59935977
if (auto kind = getInvertibleProtocolKind(*kp)) {
5994-
5995-
// Gate the '~Escapable' type behind a specific flag for now.
5996-
// Uses of 'Escapable' itself are already diagnosed; return ErrorType.
5997-
if (*kind == InvertibleProtocolKind::Escapable &&
5998-
!getASTContext().LangOpts.hasFeature(Feature::NonescapableTypes)) {
5999-
return wrapInExistential(ErrorType::get(getASTContext()));
6000-
}
6001-
60025978
return wrapInExistential(
60035979
ProtocolCompositionType::getInverseOf(getASTContext(), *kind));
60045980
}

stdlib/cmake/modules/SwiftSource.cmake

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -634,6 +634,8 @@ function(_compile_swift_files
634634
list(APPEND swift_flags "-enable-experimental-feature" "SE427NoInferenceOnExtension")
635635
list(APPEND swift_flags "-enable-experimental-feature" "AllowUnsafeAttribute")
636636
list(APPEND swift_flags "-enable-experimental-feature" "NonescapableTypes")
637+
list(APPEND swift_flags "-enable-experimental-feature" "LifetimeDependence")
638+
637639
list(APPEND swift_flags "-enable-upcoming-feature" "MemberImportVisibility")
638640

639641
if (SWIFT_STDLIB_ENABLE_STRICT_CONCURRENCY_COMPLETE)

stdlib/public/core/Misc.swift

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -234,19 +234,11 @@ func _rethrowsViaClosure(_ fn: () throws -> ()) rethrows {
234234
@_marker public protocol Escapable {}
235235

236236
#if $BitwiseCopyable2
237-
#if $NonescapableTypes
238237
@_marker public protocol BitwiseCopyable: ~Escapable { }
239-
#else
240-
@_marker public protocol BitwiseCopyable { }
241-
#endif
242238

243239
@available(*, deprecated, message: "Use BitwiseCopyable")
244240
public typealias _BitwiseCopyable = BitwiseCopyable
245241
#else
246-
#if $NonescapableTypes
247242
@_marker public protocol _BitwiseCopyable: ~Escapable { }
248-
#else
249-
@_marker public protocol _BitwiseCopyable { }
250-
#endif
251243
public typealias BitwiseCopyable = _BitwiseCopyable
252244
#endif

stdlib/public/core/Sendable.swift

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -132,11 +132,7 @@
132132
/// ### Sendable Metatypes
133133
///
134134
/// Metatypes such as `Int.Type` implicitly conform to the `Sendable` protocol.
135-
#if $NonescapableTypes
136135
@_marker public protocol Sendable: ~Copyable, ~Escapable { }
137-
#else
138-
@_marker public protocol Sendable: ~Copyable { }
139-
#endif
140136

141137
///
142138
/// A type whose values can safely be passed across concurrency domains by copying,

0 commit comments

Comments
 (0)